From 8ea3608e3f15e70149318d0806ceff4586c56a43 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Tue, 6 Feb 2024 14:58:11 +0200 Subject: [PATCH 01/14] start with refactoring some ugly if's. --- vmhost/contexts/asyncComposability.go | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/vmhost/contexts/asyncComposability.go b/vmhost/contexts/asyncComposability.go index 495aa30ff..6ec53922f 100644 --- a/vmhost/contexts/asyncComposability.go +++ b/vmhost/contexts/asyncComposability.go @@ -63,31 +63,34 @@ func (context *asyncContext) complete() error { return nil } + gasToAccumulate := context.gasAccumulated + notifyChildComplete := true currentCallID := context.GetCallID() - if context.callType == vm.AsynchronousCall { + switch context.callType { + case vm.AsynchronousCall: vmOutput := context.childResults - isCallbackComplete, _, err := context.callCallback(currentCallID, vmOutput, nil) + notifyChildComplete, _, err = context.callCallback(currentCallID, vmOutput, nil) if err != nil { return err } - if isCallbackComplete { - return context.NotifyChildIsComplete(currentCallID, 0) - } - } else if context.callType == vm.AsynchronousCallBack { + gasToAccumulate = 0 + case vm.AsynchronousCallBack: err = context.LoadParentContext() if err != nil { return err } - currentCallID := context.GetCallerCallID() - return context.NotifyChildIsComplete(currentCallID, context.gasAccumulated) - } else if context.callType == vm.DirectCall { + currentCallID = context.GetCallerCallID() + case vm.DirectCall: err = context.LoadParentContext() if err != nil { return err } + currentCallID = nil + } - return context.NotifyChildIsComplete(nil, context.gasAccumulated) + if notifyChildComplete { + return context.NotifyChildIsComplete(currentCallID, gasToAccumulate) } return nil From 33f21980d2aa0056f12952c3dfbef2c08bb8322c Mon Sep 17 00:00:00 2001 From: robertsasu Date: Wed, 7 Feb 2024 15:56:19 +0200 Subject: [PATCH 02/14] resolving todo's --- scenario/gasSchedules/gasSchedules.go | 1 - test/contracts/erc20/erc20.c | 1 - vmhost/contexts/async.go | 4 +- vmhost/contexts/asyncLocal.go | 37 +++---- vmhost/contexts/asyncParams.go | 136 ++------------------------ vmhost/hostCore/execution.go | 2 - vmhost/interface.go | 2 +- 7 files changed, 24 insertions(+), 159 deletions(-) diff --git a/scenario/gasSchedules/gasSchedules.go b/scenario/gasSchedules/gasSchedules.go index 807248821..178de9023 100644 --- a/scenario/gasSchedules/gasSchedules.go +++ b/scenario/gasSchedules/gasSchedules.go @@ -1,6 +1,5 @@ package gasschedules -// TODO: go:embed can be used after we upgrade to go 1.16 // import _ "embed" // //go:embed gasScheduleV1.toml diff --git a/test/contracts/erc20/erc20.c b/test/contracts/erc20/erc20.c index 5e3aab34c..0f49c4de6 100644 --- a/test/contracts/erc20/erc20.c +++ b/test/contracts/erc20/erc20.c @@ -44,7 +44,6 @@ void computeAllowanceKey(byte *destination, byte *from, byte* to) { // Note: in smart contract addresses, the first 10 bytes are all 0 // therefore we read from byte 10 onwards to provide more significant bytes // and to minimize the chance for collisions - // TODO: switching to a hash instead of a concatenation of addresses might make it safer for (int i = 0; i < 15; i++) { destination[1+i] = from[10+i]; } diff --git a/vmhost/contexts/async.go b/vmhost/contexts/async.go index b90e87a0c..f66f86c1a 100644 --- a/vmhost/contexts/async.go +++ b/vmhost/contexts/async.go @@ -183,7 +183,7 @@ func (context *asyncContext) PushState() { callbackData: context.callbackData, gasAccumulated: context.gasAccumulated, returnData: context.returnData, - asyncCallGroups: context.asyncCallGroups, // TODO matei-p use cloneCallGroups()? + asyncCallGroups: context.cloneCallGroups(), callType: context.callType, callbackAsyncInitiatorCallID: context.callbackAsyncInitiatorCallID, @@ -864,7 +864,7 @@ func (context *asyncContext) callCallback(callID []byte, vmOutput *vmcommon.VMOu } context.host.Metering().DisableRestoreGas() - isComplete, callbackVMOutput := loadedContext.ExecuteSyncCallbackAndFinishOutput(asyncCall, vmOutput, nil, gasAccumulated, err) + isComplete, callbackVMOutput := loadedContext.ExecuteLocalCallbackAndFinishOutput(asyncCall, vmOutput, nil, gasAccumulated, err) context.host.Metering().EnableRestoreGas() return isComplete, callbackVMOutput, nil } diff --git a/vmhost/contexts/asyncLocal.go b/vmhost/contexts/asyncLocal.go index 9b59bf6fe..491577378 100644 --- a/vmhost/contexts/asyncLocal.go +++ b/vmhost/contexts/asyncLocal.go @@ -35,7 +35,6 @@ func (context *asyncContext) executeAsyncLocalCalls() error { return nil } -// TODO split this method into smaller ones func (context *asyncContext) executeAsyncLocalCall(asyncCall *vmhost.AsyncCall) error { destinationCallInput, err := context.createContractCallInput(asyncCall) if err != nil { @@ -79,10 +78,11 @@ func (context *asyncContext) executeAsyncLocalCall(asyncCall *vmhost.AsyncCall) asyncCall.UpdateStatus(vmOutput.ReturnCode) if isComplete { + callbackGasRemaining := uint64(0) if asyncCall.HasCallback() { // Restore gas locked while still on the caller instance; otherwise, the // locked gas will appear to have been used twice by the caller instance. - isCallbackComplete, callbackVMOutput := context.ExecuteSyncCallbackAndFinishOutput(asyncCall, vmOutput, destinationCallInput, 0, err) + isCallbackComplete, callbackVMOutput := context.ExecuteLocalCallbackAndFinishOutput(asyncCall, vmOutput, destinationCallInput, 0, err) if callbackVMOutput == nil { return vmhost.ErrAsyncNoOutputFromCallback } @@ -90,33 +90,30 @@ func (context *asyncContext) executeAsyncLocalCall(asyncCall *vmhost.AsyncCall) context.host.CompleteLogEntriesWithCallType(callbackVMOutput, vmhost.AsyncCallbackString) if isCallbackComplete { - callbackGasRemaining := callbackVMOutput.GasRemaining + callbackGasRemaining = callbackVMOutput.GasRemaining callbackVMOutput.GasRemaining = 0 - return context.completeChild(asyncCall.CallID, callbackGasRemaining) } - } else { - return context.completeChild(asyncCall.CallID, 0) } + + return context.completeChild(asyncCall.CallID, callbackGasRemaining) } return nil } -// ExecuteSyncCallbackAndFinishOutput executes the callback and finishes the output -// TODO rename to executeLocalCallbackAndFinishOutput -func (context *asyncContext) ExecuteSyncCallbackAndFinishOutput( +// ExecuteLocalCallbackAndFinishOutput executes the callback and finishes the output +func (context *asyncContext) ExecuteLocalCallbackAndFinishOutput( asyncCall *vmhost.AsyncCall, vmOutput *vmcommon.VMOutput, _ *vmcommon.ContractCallInput, gasAccumulated uint64, err error) (bool, *vmcommon.VMOutput) { - callbackVMOutput, isComplete, _ := context.executeSyncCallback(asyncCall, vmOutput, gasAccumulated, err) + callbackVMOutput, isComplete, _ := context.executeLocalCallback(asyncCall, vmOutput, gasAccumulated, err) context.finishAsyncLocalCallbackExecution() return isComplete, callbackVMOutput } -// TODO rename to executeLocalCallback -func (context *asyncContext) executeSyncCallback( +func (context *asyncContext) executeLocalCallback( asyncCall *vmhost.AsyncCall, destinationVMOutput *vmcommon.VMOutput, gasAccumulated uint64, @@ -124,11 +121,11 @@ func (context *asyncContext) executeSyncCallback( ) (*vmcommon.VMOutput, bool, error) { callbackInput, err := context.createCallbackInput(asyncCall, destinationVMOutput, gasAccumulated, destinationErr) if err != nil { - logAsync.Trace("executeSyncCallback", "error", err) + logAsync.Trace("executeLocalCallback", "error", err) return nil, true, err } - logAsync.Trace("executeSyncCallback", + logAsync.Trace("executeLocalCallback", "caller", callbackInput.CallerAddr, "dest", callbackInput.RecipientAddr, "func", callbackInput.Function, @@ -183,7 +180,7 @@ func (context *asyncContext) executeSyncHalfOfBuiltinFunction(asyncCall *vmhost. if vmOutput.ReturnCode != vmcommon.Ok { asyncCall.Reject() if asyncCall.HasCallback() { - _, _, _ = context.executeSyncCallback(asyncCall, vmOutput, 0, err) + _, _, _ = context.executeLocalCallback(asyncCall, vmOutput, 0, err) context.finishAsyncLocalCallbackExecution() } } @@ -240,7 +237,6 @@ func (context *asyncContext) createContractCallInput(asyncCall *vmhost.AsyncCall return contractCallInput, nil } -// TODO function too large; refactor needed func (context *asyncContext) createCallbackInput( asyncCall *vmhost.AsyncCall, vmOutput *vmcommon.VMOutput, @@ -255,14 +251,12 @@ func (context *asyncContext) createCallbackInput( } arguments := context.getArgumentsForCallback(vmOutput, destinationErr) - returnWithError := false if destinationErr != nil || vmOutput.ReturnCode != vmcommon.Ok { returnWithError = true } callbackFunction := asyncCall.GetCallbackName() - dataLength := computeDataLengthFromArguments(callbackFunction, arguments) gasLimit, err := context.computeGasLimitForCallback(asyncCall, vmOutput, dataLength) if err != nil { @@ -270,9 +264,8 @@ func (context *asyncContext) createCallbackInput( } originalCaller := runtime.GetOriginalCallerAddress() - caller := context.address - lastTransferInfo := context.extractLastTransferWithoutData(caller, vmOutput) + lastTransferData := context.extractLastTransferWithoutData(caller, vmOutput) // Return to the sender SC, calling its specified callback method. contractCallInput := &vmcommon.ContractCallInput{ @@ -280,7 +273,7 @@ func (context *asyncContext) createCallbackInput( OriginalCallerAddr: originalCaller, CallerAddr: actualCallbackInitiator, Arguments: arguments, - CallValue: lastTransferInfo.callValue, + CallValue: lastTransferData.callValue, CallType: vm.AsynchronousCallBack, GasPrice: runtime.GetVMInput().GasPrice, GasProvided: gasLimit, @@ -289,7 +282,7 @@ func (context *asyncContext) createCallbackInput( OriginalTxHash: runtime.GetOriginalTxHash(), PrevTxHash: runtime.GetPrevTxHash(), ReturnCallAfterError: returnWithError, - ESDTTransfers: lastTransferInfo.lastESDTTransfers, + ESDTTransfers: lastTransferData.lastESDTTransfers, }, RecipientAddr: caller, Function: callbackFunction, diff --git a/vmhost/contexts/asyncParams.go b/vmhost/contexts/asyncParams.go index 15ec142e1..349c8fb20 100644 --- a/vmhost/contexts/asyncParams.go +++ b/vmhost/contexts/asyncParams.go @@ -8,31 +8,23 @@ import ( vmcommon "github.com/multiversx/mx-chain-vm-common-go" "github.com/multiversx/mx-chain-vm-common-go/txDataBuilder" "github.com/multiversx/mx-chain-vm-go/crypto" - "github.com/multiversx/mx-chain-vm-go/vmhost" ) -/* - Called to process OutputTransfers created by a - direct call (on dest) builtin function call by the VM -*/ +// AddAsyncArgumentsToOutputTransfers +// Called to process OutputTransfers created by a +// direct call (on dest) builtin function call by the VM func AddAsyncArgumentsToOutputTransfers( - output vmhost.OutputContext, - address []byte, asyncParams *vmcommon.AsyncArguments, callType vm.CallType, - vmOutput *vmcommon.VMOutput) error { + vmOutput *vmcommon.VMOutput, +) error { if asyncParams == nil { return nil } + for _, outAcc := range vmOutput.OutputAccounts { - // if !bytes.Equal(address, outAcc.Address) { - // continue - // } for t, outTransfer := range outAcc.OutputTransfers { - // if !bytes.Equal(address, outTransfer.SenderAddress) { - // continue - // } if outTransfer.CallType != callType { continue } @@ -84,122 +76,6 @@ func createDataFromAsyncParams( return callData.ToBytes(), nil } -/* - Called when a SCR for a callback is created outside the VM - (by createAsyncCallBackSCRFromVMOutput()) - This is the case - A) after an async call executed following a builtin function call, - B) other cases where processing the output trasnfers of a VMOutput did - not produce a SCR of type AsynchronousCallBack - TODO(check): function not used? -*/ -func AppendAsyncArgumentsToCallbackCallData( - hasher crypto.Hasher, - data []byte, - asyncArguments *vmcommon.AsyncArguments, - parseArgumentsFunc func(data string) ([][]byte, error)) ([]byte, error) { - - return appendAsyncParamsToCallData( - CreateCallbackAsyncParams(hasher, asyncArguments), - data, - false, - parseArgumentsFunc) -} - -/* - Called when a SCR is created from VMOutput in order to recompose - async data and call data into a transfer data ready for the SCR - (by preprocessOutTransferToSCR()) - TODO(check): function not used? -*/ -func AppendTransferAsyncDataToCallData( - callData []byte, - asyncData []byte, - parseArgumentsFunc func(data string) ([][]byte, error)) ([]byte, error) { - - var asyncParams [][]byte - if asyncData != nil { - asyncParams, _ = parseArgumentsFunc(string(asyncData)) - // string start with a @ so first parsed argument will be empty always - asyncParams = asyncParams[1:] - } else { - return callData, nil - } - - return appendAsyncParamsToCallData( - asyncParams, - callData, - true, - parseArgumentsFunc) -} - -func appendAsyncParamsToCallData( - asyncParams [][]byte, - data []byte, - hasFunction bool, - parseArgumentsFunc func(data string) ([][]byte, error)) ([]byte, error) { - - if data == nil { - return nil, nil - } - - args, err := parseArgumentsFunc(string(data)) - if err != nil { - return nil, err - } - - var functionName string - if hasFunction { - functionName = string(args[0]) - } - - // check if there is only one argument and that is 0 - if len(args) != 0 { - args = args[1:] - } - - callData := txDataBuilder.NewBuilder() - - if functionName != "" { - callData.Func(functionName) - } - - if len(args) != 0 { - for _, arg := range args { - callData.Bytes(arg) - } - } else { - if !hasFunction { - callData.Bytes([]byte{}) - } - } - - for _, asyncParam := range asyncParams { - callData.Bytes(asyncParam) - } - - return callData.ToBytes(), nil -} - -/* - Used by when a callback SCR is created - 1) after a failure of an async call - Async data is extracted (by extractAsyncCallParamsFromTxData()) and then - reappended to the new SCR's callback data (by reapendAsyncParamsToTxData()) - 2) from the last transfer (see useLastTransferAsAsyncCallBackWhenNeeded()) -*/ -func CreateCallbackAsyncParams(hasher crypto.Hasher, asyncParams *vmcommon.AsyncArguments) [][]byte { - if asyncParams == nil { - return nil - } - newAsyncParams := make([][]byte, 4) - newAsyncParams[0] = GenerateNewCallID(hasher, asyncParams.CallID, []byte{0}) - newAsyncParams[1] = asyncParams.CallID - newAsyncParams[2] = asyncParams.CallerCallID - newAsyncParams[3] = []byte{0} - return newAsyncParams -} - // GenerateNewCallID will generate a new call ID as byte slice func GenerateNewCallID(hasher crypto.Hasher, parentCallID []byte, suffix []byte) []byte { newCallID := append(parentCallID, suffix...) diff --git a/vmhost/hostCore/execution.go b/vmhost/hostCore/execution.go index 1eb04379e..f5d07bd69 100644 --- a/vmhost/hostCore/execution.go +++ b/vmhost/hostCore/execution.go @@ -429,8 +429,6 @@ func (host *vmHost) handleBuiltinFunctionCall(input *vmcommon.ContractCallInput) } err = contexts.AddAsyncArgumentsToOutputTransfers( - host.Output(), - input.RecipientAddr, input.AsyncArguments, vm.AsynchronousCall, builtinOutput) diff --git a/vmhost/interface.go b/vmhost/interface.go index 4348f2c65..e210e4434 100644 --- a/vmhost/interface.go +++ b/vmhost/interface.go @@ -399,7 +399,7 @@ type AsyncContext interface { GetAsyncCallByCallID(callID []byte) AsyncCallLocation LoadParentContextFromStackOrStorage() (AsyncContext, error) - ExecuteSyncCallbackAndFinishOutput( + ExecuteLocalCallbackAndFinishOutput( asyncCall *AsyncCall, vmOutput *vmcommon.VMOutput, destinationCallInput *vmcommon.ContractCallInput, From 67c668368520e0eac53f95769d784aeadd8faa05 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Wed, 14 Feb 2024 13:55:05 +0200 Subject: [PATCH 03/14] fix --- vmhost/hostCore/host.go | 19 +------------------ vmhost/hostCore/host_test.go | 12 ------------ 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/vmhost/hostCore/host.go b/vmhost/hostCore/host.go index 21ecb5bd1..f299e758f 100644 --- a/vmhost/hostCore/host.go +++ b/vmhost/hostCore/host.go @@ -37,23 +37,6 @@ var _ scenexec.VMInterface = (*vmHost)(nil) const minExecutionTimeout = time.Second const internalVMErrors = "internalVMErrors" -// allFlags must have all flags used by mx-chain-vm-go in the current version -var allFlags = []core.EnableEpochFlag{ - vmhost.MultiESDTTransferFixOnCallBackFlag, - vmhost.RemoveNonUpdatedStorageFlag, - vmhost.CreateNFTThroughExecByCallerFlag, - vmhost.StorageAPICostOptimizationFlag, - vmhost.CheckExecuteOnReadOnlyFlag, - vmhost.FailExecutionOnEveryAPIErrorFlag, - vmhost.ManagedCryptoAPIsFlag, - vmhost.DisableExecByCallerFlag, - vmhost.RefactorContextFlag, - vmhost.RuntimeMemStoreLimitFlag, - vmhost.RuntimeCodeSizeFixFlag, - vmhost.FixOOGReturnCodeFlag, - vmhost.DynamicGasCostForDataTrieStorageLoadFlag, -} - // vmHost implements HostContext interface. type vmHost struct { cryptoHook crypto.VMCrypto @@ -104,7 +87,7 @@ func NewVMHost( if check.IfNil(hostParameters.EnableEpochsHandler) { return nil, vmhost.ErrNilEnableEpochsHandler } - err := core.CheckHandlerCompatibility(hostParameters.EnableEpochsHandler, allFlags) + err := core.CheckHandlerCompatibility(hostParameters.EnableEpochsHandler, []core.EnableEpochFlag{}) if err != nil { return nil, err } diff --git a/vmhost/hostCore/host_test.go b/vmhost/hostCore/host_test.go index bcd79ec3d..a01bc3724 100644 --- a/vmhost/hostCore/host_test.go +++ b/vmhost/hostCore/host_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/multiversx/mx-chain-scenario-go/worldmock" - "github.com/multiversx/mx-chain-core-go/core" vmcommon "github.com/multiversx/mx-chain-vm-common-go" "github.com/multiversx/mx-chain-vm-common-go/builtInFunctions" "github.com/multiversx/mx-chain-vm-common-go/parsers" @@ -72,17 +71,6 @@ func TestNewVMHost(t *testing.T) { require.Nil(t, host) require.ErrorIs(t, err, vmhost.ErrNilEnableEpochsHandler) }) - t.Run("InvalidEnableEpochsHandler", func(t *testing.T) { - hostParameters := makeHostParameters() - hostParameters.EnableEpochsHandler = &worldmock.EnableEpochsHandlerStub{ - IsFlagDefinedCalled: func(flag core.EnableEpochFlag) bool { - return false - }, - } - host, err := NewVMHost(blockchainHook, hostParameters) - require.Nil(t, host) - require.ErrorIs(t, err, core.ErrInvalidEnableEpochsHandler) - }) t.Run("NilHasher", func(t *testing.T) { hostParameters := makeHostParameters() hostParameters.Hasher = nil From 76ddb2c7b60fdb518775b9f4c57d6b628e3f8b28 Mon Sep 17 00:00:00 2001 From: Laurentiu Ciobanu Date: Fri, 5 Apr 2024 11:29:47 +0300 Subject: [PATCH 04/14] refactor output in case of error for async callback and empty function name check --- vmhost/contexts/output.go | 38 +++++++++++++- vmhost/hostCore/execution.go | 96 +++++++++++++++++++----------------- 2 files changed, 89 insertions(+), 45 deletions(-) diff --git a/vmhost/contexts/output.go b/vmhost/contexts/output.go index 1c7e93207..82d6ab400 100644 --- a/vmhost/contexts/output.go +++ b/vmhost/contexts/output.go @@ -562,14 +562,50 @@ func (context *outputContext) DeployCode(input vmhost.CodeDeployInput) { context.codeUpdates[string(input.ContractAddress)] = empty } +// createVMOutputInCaseOfErrorOfAsyncCallback appends the deletion of the async context to the output +func (context *outputContext) createVMOutputInCaseOfErrorOfAsyncCallback(err error, returnCode vmcommon.ReturnCode, returnMessage string) *vmcommon.VMOutput { + async := context.host.Async() + metering := context.host.Metering() + + callId := async.GetCallbackAsyncInitiatorCallID() + + context.PushState() + + context.outputState = &vmcommon.VMOutput{ + GasRemaining: 0, + GasRefund: big.NewInt(0), + ReturnCode: returnCode, + ReturnMessage: returnMessage, + } + + err = async.DeleteFromCallID(callId) + logOutput.Trace("failed to delete Async Context", "callId", callId, "err", err) + + vmOutput := context.GetVMOutput() + context.PopSetActiveState() + + metering.UpdateGasStateOnFailure(vmOutput) + + return vmOutput +} + // CreateVMOutputInCaseOfError creates a new vmOutput with the given error set as return message. func (context *outputContext) CreateVMOutputInCaseOfError(err error) *vmcommon.VMOutput { runtime := context.host.Runtime() + async := context.host.Async() + metering := context.host.Metering() + + callType := runtime.GetVMInput().CallType + runtime.AddError(err, runtime.FunctionName()) returnCode := context.resolveReturnCodeFromError(err) returnMessage := context.resolveReturnMessageFromError(err) + if callType == vm.AsynchronousCallBack && async.HasCallback() { + return context.createVMOutputInCaseOfErrorOfAsyncCallback(err, returnCode, returnMessage) + } + vmOutput := &vmcommon.VMOutput{ GasRemaining: 0, GasRefund: big.NewInt(0), @@ -577,7 +613,7 @@ func (context *outputContext) CreateVMOutputInCaseOfError(err error) *vmcommon.V ReturnMessage: returnMessage, } - context.host.Metering().UpdateGasStateOnFailure(vmOutput) + metering.UpdateGasStateOnFailure(vmOutput) return vmOutput } diff --git a/vmhost/hostCore/execution.go b/vmhost/hostCore/execution.go index d2eff2b70..0b87a401c 100644 --- a/vmhost/hostCore/execution.go +++ b/vmhost/hostCore/execution.go @@ -1145,6 +1145,14 @@ func (host *vmHost) checkFinalGasAfterExit() error { return nil } +func (host *vmHost) checkValidFunctionName(name string) error { + if name == "" { + return executor.ErrInvalidFunction + } + + return nil +} + func (host *vmHost) callInitFunction() error { return host.callSCFunction(vmhost.InitFunctionName) } @@ -1154,12 +1162,18 @@ func (host *vmHost) callUpgradeFunction() error { } func (host *vmHost) callSCFunction(functionName string) error { + err := host.checkValidFunctionName(functionName) + if err != nil { + log.Trace("call SC method failed", "error", err, "src", "checkValidFunctionName") + return err + } + runtime := host.Runtime() if !runtime.HasFunction(functionName) { return executor.ErrFuncNotFound } - err := runtime.CallSCFunction(functionName) + err = runtime.CallSCFunction(functionName) if err != nil { err = host.handleBreakpointIfAny(err) } @@ -1236,12 +1250,6 @@ func (host *vmHost) callSCMethodAsynchronousCallBack() error { metering.UseGas(metering.GasLeft()) } - // TODO matei-p R2 Returning an error here will cause the VMOutput to be - // empty (due to CreateVMOutputInCaseOfError()). But in release 2 of - // Promises, CreateVMOutputInCaseOfError() should still contain storage - // deletions caused by AsyncContext cleanup, even if callbackErr != nil and - // was returned here. The storage deletions MUST be persisted in the data - // trie once R2 goes live. if !isCallComplete { return callbackErr } @@ -1263,47 +1271,47 @@ func (host *vmHost) callFunctionAndExecuteAsync() (bool, error) { runtime := host.Runtime() async := host.Async() - // TODO refactor this, and apply this condition in other places where a - // function is called - if runtime.FunctionName() != "" { - err := host.verifyAllowedFunctionCall() - if err != nil { - log.Trace("call SC method failed", "error", err, "src", "verifyAllowedFunctionCall") - return false, err - } + err := host.checkValidFunctionName(runtime.FunctionName()) + if err != nil { + log.Trace("call SC method failed", "error", err, "src", "checkValidFunctionName") + return false, err + } - functionName, err := runtime.FunctionNameChecked() - if err != nil { - log.Trace("call SC method failed", "error", err, "src", "FunctionNameChecked") - return false, err - } + err = host.verifyAllowedFunctionCall() + if err != nil { + log.Trace("call SC method failed", "error", err, "src", "verifyAllowedFunctionCall") + return false, err + } - err = runtime.CallSCFunction(functionName) - if err != nil { - err = host.handleBreakpointIfAny(err) - log.Trace("breakpoint detected and handled", "err", err) - } - if err == nil { - err = host.checkFinalGasAfterExit() - } - if err != nil { - log.Trace("call SC method failed", "error", err, "src", "sc function") - return true, err - } + functionName, err := runtime.FunctionNameChecked() + if err != nil { + log.Trace("call SC method failed", "error", err, "src", "FunctionNameChecked") + return false, err + } - err = async.Execute() - if err != nil { - log.Trace("call SC method failed", "error", err, "src", "async execution") - return false, err - } + err = runtime.CallSCFunction(functionName) + if err != nil { + err = host.handleBreakpointIfAny(err) + log.Trace("breakpoint detected and handled", "err", err) + } + if err == nil { + err = host.checkFinalGasAfterExit() + } + if err != nil { + log.Trace("call SC method failed", "error", err, "src", "sc function") + return true, err + } - if !async.IsComplete() || async.HasLegacyGroup() { - async.SetResults(host.Output().GetVMOutput()) - err = async.Save() - return false, err - } - } else { - return false, executor.ErrInvalidFunction + err = async.Execute() + if err != nil { + log.Trace("call SC method failed", "error", err, "src", "async execution") + return false, err + } + + if !async.IsComplete() || async.HasLegacyGroup() { + async.SetResults(host.Output().GetVMOutput()) + err = async.Save() + return false, err } return true, nil From c9ba5b7e8740b47da9483f9d2d1c7e97d2b9c724 Mon Sep 17 00:00:00 2001 From: Laurentiu Ciobanu Date: Fri, 5 Apr 2024 12:39:22 +0300 Subject: [PATCH 05/14] refactor output in case of error for async callback --- vmhost/contexts/output.go | 18 ++++++++++-------- vmhost/hosttest/execution_test.go | 2 ++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/vmhost/contexts/output.go b/vmhost/contexts/output.go index 82d6ab400..480d1a72a 100644 --- a/vmhost/contexts/output.go +++ b/vmhost/contexts/output.go @@ -572,16 +572,19 @@ func (context *outputContext) createVMOutputInCaseOfErrorOfAsyncCallback(err err context.PushState() context.outputState = &vmcommon.VMOutput{ - GasRemaining: 0, - GasRefund: big.NewInt(0), - ReturnCode: returnCode, - ReturnMessage: returnMessage, + GasRemaining: 0, + GasRefund: big.NewInt(0), + ReturnCode: returnCode, + ReturnMessage: returnMessage, + OutputAccounts: make(map[string]*vmcommon.OutputAccount), } err = async.DeleteFromCallID(callId) - logOutput.Trace("failed to delete Async Context", "callId", callId, "err", err) + if err != nil { + logOutput.Trace("failed to delete Async Context", "callId", callId, "err", err) + } - vmOutput := context.GetVMOutput() + vmOutput := context.outputState // GetVMOutput updates metering context.PopSetActiveState() metering.UpdateGasStateOnFailure(vmOutput) @@ -592,7 +595,6 @@ func (context *outputContext) createVMOutputInCaseOfErrorOfAsyncCallback(err err // CreateVMOutputInCaseOfError creates a new vmOutput with the given error set as return message. func (context *outputContext) CreateVMOutputInCaseOfError(err error) *vmcommon.VMOutput { runtime := context.host.Runtime() - async := context.host.Async() metering := context.host.Metering() callType := runtime.GetVMInput().CallType @@ -602,7 +604,7 @@ func (context *outputContext) CreateVMOutputInCaseOfError(err error) *vmcommon.V returnCode := context.resolveReturnCodeFromError(err) returnMessage := context.resolveReturnMessageFromError(err) - if callType == vm.AsynchronousCallBack && async.HasCallback() { + if callType == vm.AsynchronousCallBack { return context.createVMOutputInCaseOfErrorOfAsyncCallback(err, returnCode, returnMessage) } diff --git a/vmhost/hosttest/execution_test.go b/vmhost/hosttest/execution_test.go index f2edcfdd0..018baaf2e 100644 --- a/vmhost/hosttest/execution_test.go +++ b/vmhost/hosttest/execution_test.go @@ -2905,6 +2905,8 @@ func TestExecution_AsyncCall_CallBackFails(t *testing.T) { } func TestExecution_AsyncCall_Promises_CallBackFails(t *testing.T) { + _ = logger.SetLogLevel("*:TRACE") + // same scenario as in TestExecution_AsyncCall_CallBackFails txHash := []byte("txhash..........................") test.BuildInstanceCallTest(t). From f2a60049be6c8ad43261be42525cf29690c667bc Mon Sep 17 00:00:00 2001 From: Laurentiu Ciobanu Date: Fri, 5 Apr 2024 12:39:52 +0300 Subject: [PATCH 06/14] refactor output in case of error for async callback --- vmhost/hosttest/execution_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/vmhost/hosttest/execution_test.go b/vmhost/hosttest/execution_test.go index 018baaf2e..f2edcfdd0 100644 --- a/vmhost/hosttest/execution_test.go +++ b/vmhost/hosttest/execution_test.go @@ -2905,8 +2905,6 @@ func TestExecution_AsyncCall_CallBackFails(t *testing.T) { } func TestExecution_AsyncCall_Promises_CallBackFails(t *testing.T) { - _ = logger.SetLogLevel("*:TRACE") - // same scenario as in TestExecution_AsyncCall_CallBackFails txHash := []byte("txhash..........................") test.BuildInstanceCallTest(t). From 3a2719cf41476cbb66e3747d902014849c0288de Mon Sep 17 00:00:00 2001 From: Laurentiu Ciobanu Date: Thu, 11 Apr 2024 18:30:16 +0300 Subject: [PATCH 07/14] Add AsyncV3 flag --- vmhost/flags.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vmhost/flags.go b/vmhost/flags.go index ad1a4cbfe..de4d175b2 100644 --- a/vmhost/flags.go +++ b/vmhost/flags.go @@ -3,6 +3,8 @@ package vmhost import "github.com/multiversx/mx-chain-core-go/core" const ( + // AsyncV3Flag defines the flag that activates async v3 + AsyncV3Flag core.EnableEpochFlag = "AsyncV3Flag" // MultiESDTTransferFixOnCallBackFlag defines the flag that activates the multi esdt transfer fix on callback MultiESDTTransferFixOnCallBackFlag core.EnableEpochFlag = "MultiESDTTransferFixOnCallBackFlag" // RemoveNonUpdatedStorageFlag defines the flag that activates the remove non updated storage fix From 6adf73689e1265630b3f8cab0ee8062f211e7df5 Mon Sep 17 00:00:00 2001 From: Laurentiu Ciobanu Date: Thu, 11 Apr 2024 18:30:39 +0300 Subject: [PATCH 08/14] Add test for output in case of error of async callback --- vmhost/contexts/async_test.go | 74 +++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/vmhost/contexts/async_test.go b/vmhost/contexts/async_test.go index 0093c7ca1..12144a237 100644 --- a/vmhost/contexts/async_test.go +++ b/vmhost/contexts/async_test.go @@ -2,6 +2,7 @@ package contexts import ( "errors" + "github.com/multiversx/mx-chain-core-go/core" "math/big" "testing" @@ -496,6 +497,79 @@ func TestAsyncContext_UpdateCurrentCallStatus(t *testing.T) { require.Equal(t, vmhost.AsyncCallRejected, asyncCall.Status) } +func TestAsyncContext_OutputInCaseOfErrorInCallback(t *testing.T) { + user := []byte("user") + contractA := []byte("contractA") + contractB := []byte("contractB") + + host, _ := initializeVMAndWasmerAsyncContext(t) + host.EnableEpochsHandlerField = &worldmock.EnableEpochsHandlerStub{ + IsFlagEnabledCalled: func(flag core.EnableEpochFlag) bool { + return flag == vmhost.AsyncV3Flag + }, + } + + async := makeAsyncContext(t, host, contractA) + host.Storage().SetAddress(contractA) + host.AsyncContext = async + + vmInput := &vmcommon.ContractCallInput{ + VMInput: vmcommon.VMInput{ + CallerAddr: user, + Arguments: [][]byte{{0}}, + CallType: vm.DirectCall, + }, + RecipientAddr: contractA, + } + host.Runtime().InitStateFromContractCallInput(vmInput) + + err := async.RegisterAsyncCall("", &vmhost.AsyncCall{ + Destination: contractB, + Data: []byte("function"), + }) + require.Nil(t, err) + + err = async.Save() + require.Nil(t, err) + + asyncCallId := async.GetCallID() + asyncStoragePrefix := host.Storage().GetVmProtectedPrefix(vmhost.AsyncDataPrefix) + asyncCallKey := vmhost.CustomStorageKey(string(asyncStoragePrefix), asyncCallId) + + data, _, _, _ := host.Storage().GetStorageUnmetered(asyncCallKey) + require.NotEqual(t, len(data), 0) + + vmInput = &vmcommon.ContractCallInput{ + VMInput: vmcommon.VMInput{ + CallerAddr: contractB, + Arguments: [][]byte{{0}}, + CallType: vm.AsynchronousCallBack, + }, + RecipientAddr: contractA, + } + host.Runtime().InitStateFromContractCallInput(vmInput) + + async.callbackAsyncInitiatorCallID = asyncCallId + async.callType = vmInput.CallType + err = async.LoadParentContext() + require.Nil(t, err) + + vmOutput := host.Output().CreateVMOutputInCaseOfError(vmhost.ErrNotEnoughGas) + outputAccount := vmOutput.OutputAccounts[string(contractA)] + + require.NotNil(t, outputAccount) + + storageUpdates := outputAccount.StorageUpdates + require.Equal(t, len(storageUpdates), 1) + + asyncContextDeletionUpdate := storageUpdates[string(asyncCallKey)] + require.NotNil(t, asyncContextDeletionUpdate) + require.Equal(t, len(asyncContextDeletionUpdate.Data), 0) + + data, _, _, _ = host.Storage().GetStorageUnmetered(asyncCallKey) + require.Equal(t, len(data), 0) +} + func TestAsyncContext_SendAsyncCallCrossShard(t *testing.T) { host, world := initializeVMAndWasmerAsyncContext(t) world.AcctMap.PutAccount(&worldmock.Account{ From a0e8e8472e699d572507f4b19533c69742940d57 Mon Sep 17 00:00:00 2001 From: Laurentiu Ciobanu Date: Thu, 11 Apr 2024 18:31:49 +0300 Subject: [PATCH 09/14] Remove redundant output stack operations and guard deleteion by AsyncV3 flag --- vmhost/contexts/output.go | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/vmhost/contexts/output.go b/vmhost/contexts/output.go index 480d1a72a..f84e5f7e3 100644 --- a/vmhost/contexts/output.go +++ b/vmhost/contexts/output.go @@ -569,8 +569,6 @@ func (context *outputContext) createVMOutputInCaseOfErrorOfAsyncCallback(err err callId := async.GetCallbackAsyncInitiatorCallID() - context.PushState() - context.outputState = &vmcommon.VMOutput{ GasRemaining: 0, GasRefund: big.NewInt(0), @@ -584,12 +582,9 @@ func (context *outputContext) createVMOutputInCaseOfErrorOfAsyncCallback(err err logOutput.Trace("failed to delete Async Context", "callId", callId, "err", err) } - vmOutput := context.outputState // GetVMOutput updates metering - context.PopSetActiveState() - - metering.UpdateGasStateOnFailure(vmOutput) + metering.UpdateGasStateOnFailure(context.outputState) - return vmOutput + return context.outputState } // CreateVMOutputInCaseOfError creates a new vmOutput with the given error set as return message. @@ -604,7 +599,7 @@ func (context *outputContext) CreateVMOutputInCaseOfError(err error) *vmcommon.V returnCode := context.resolveReturnCodeFromError(err) returnMessage := context.resolveReturnMessageFromError(err) - if callType == vm.AsynchronousCallBack { + if context.host.EnableEpochsHandler().IsFlagEnabled(vmhost.AsyncV3Flag) && callType == vm.AsynchronousCallBack { return context.createVMOutputInCaseOfErrorOfAsyncCallback(err, returnCode, returnMessage) } From bbee461aa02e2f6c03cb656e9e07801b59cc6771 Mon Sep 17 00:00:00 2001 From: Laurentiu Ciobanu Date: Thu, 11 Apr 2024 19:16:11 +0300 Subject: [PATCH 10/14] A bit of cleanup --- vmhost/contexts/output.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vmhost/contexts/output.go b/vmhost/contexts/output.go index f84e5f7e3..79ef6999c 100644 --- a/vmhost/contexts/output.go +++ b/vmhost/contexts/output.go @@ -563,7 +563,7 @@ func (context *outputContext) DeployCode(input vmhost.CodeDeployInput) { } // createVMOutputInCaseOfErrorOfAsyncCallback appends the deletion of the async context to the output -func (context *outputContext) createVMOutputInCaseOfErrorOfAsyncCallback(err error, returnCode vmcommon.ReturnCode, returnMessage string) *vmcommon.VMOutput { +func (context *outputContext) createVMOutputInCaseOfErrorOfAsyncCallback(returnCode vmcommon.ReturnCode, returnMessage string) *vmcommon.VMOutput { async := context.host.Async() metering := context.host.Metering() @@ -577,7 +577,7 @@ func (context *outputContext) createVMOutputInCaseOfErrorOfAsyncCallback(err err OutputAccounts: make(map[string]*vmcommon.OutputAccount), } - err = async.DeleteFromCallID(callId) + err := async.DeleteFromCallID(callId) if err != nil { logOutput.Trace("failed to delete Async Context", "callId", callId, "err", err) } @@ -600,7 +600,7 @@ func (context *outputContext) CreateVMOutputInCaseOfError(err error) *vmcommon.V returnMessage := context.resolveReturnMessageFromError(err) if context.host.EnableEpochsHandler().IsFlagEnabled(vmhost.AsyncV3Flag) && callType == vm.AsynchronousCallBack { - return context.createVMOutputInCaseOfErrorOfAsyncCallback(err, returnCode, returnMessage) + return context.createVMOutputInCaseOfErrorOfAsyncCallback(returnCode, returnMessage) } vmOutput := &vmcommon.VMOutput{ From c4854af3d79cd158ceba91e989d7f23c03f2b42b Mon Sep 17 00:00:00 2001 From: Laurentiu Ciobanu Date: Fri, 12 Apr 2024 12:22:48 +0300 Subject: [PATCH 11/14] AsyncV3Flag swap order --- vmhost/flags.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vmhost/flags.go b/vmhost/flags.go index de4d175b2..15bc2ab73 100644 --- a/vmhost/flags.go +++ b/vmhost/flags.go @@ -3,8 +3,6 @@ package vmhost import "github.com/multiversx/mx-chain-core-go/core" const ( - // AsyncV3Flag defines the flag that activates async v3 - AsyncV3Flag core.EnableEpochFlag = "AsyncV3Flag" // MultiESDTTransferFixOnCallBackFlag defines the flag that activates the multi esdt transfer fix on callback MultiESDTTransferFixOnCallBackFlag core.EnableEpochFlag = "MultiESDTTransferFixOnCallBackFlag" // RemoveNonUpdatedStorageFlag defines the flag that activates the remove non updated storage fix @@ -31,4 +29,6 @@ const ( FixOOGReturnCodeFlag core.EnableEpochFlag = "FixOOGReturnCodeFlag" // DynamicGasCostForDataTrieStorageLoadFlag defines the flag that activates the dynamic gas cost for data trie storage load DynamicGasCostForDataTrieStorageLoadFlag core.EnableEpochFlag = "DynamicGasCostForDataTrieStorageLoadFlag" + // AsyncV3Flag defines the flag that activates async v3 + AsyncV3Flag core.EnableEpochFlag = "AsyncV3Flag" ) From eb6ecaa1b80a06323a39e8ea8c88bcd10ca62a5a Mon Sep 17 00:00:00 2001 From: Laurentiu Ciobanu Date: Mon, 20 May 2024 08:10:33 +0300 Subject: [PATCH 12/14] async v3 callback order --- config/config.toml | 1 + config/gasCost.go | 1 + config/gasSchedule.go | 1 + executor/vmHooks.go | 3 +- executor/wrapper/wrapperVMHooks.go | 15 +- go.sum | 8 + mock/context/executorMockFunc.go | 1 + vmhost/asyncCall.go | 77 +++--- vmhost/asyncCall.pb.go | 428 +++++++++++------------------ vmhost/asyncCall.proto | 2 + vmhost/contexts/asyncLocal.go | 79 +++++- vmhost/hostCore/execution.go | 4 + vmhost/vmhooks/baseOps.go | 126 +++++++++ wasmer/wasmerImportsCgo.go | 18 +- wasmer2/wasmer2ImportsCgo.go | 14 +- wasmer2/wasmer2Names.go | 1 + 16 files changed, 451 insertions(+), 328 deletions(-) diff --git a/config/config.toml b/config/config.toml index 6f082932f..d4267d14a 100644 --- a/config/config.toml +++ b/config/config.toml @@ -45,6 +45,7 @@ AsyncCallStep = 10 AsyncCallbackGasLock = 10 CreateAsyncCall = 10 + CreateAsyncV3Call = 10 SetAsyncCallback = 10 SetAsyncGroupCallback = 10 SetAsyncContextCallback = 10 diff --git a/config/gasCost.go b/config/gasCost.go index aed3f7f8e..1364aab93 100644 --- a/config/gasCost.go +++ b/config/gasCost.go @@ -70,6 +70,7 @@ type BaseOpsAPICost struct { AsyncCallStep uint64 AsyncCallbackGasLock uint64 CreateAsyncCall uint64 + CreateAsyncV3Call uint64 SetAsyncCallback uint64 SetAsyncGroupCallback uint64 SetAsyncContextCallback uint64 diff --git a/config/gasSchedule.go b/config/gasSchedule.go index 8c660a928..60327e76a 100644 --- a/config/gasSchedule.go +++ b/config/gasSchedule.go @@ -296,6 +296,7 @@ func FillGasMapBaseOpsAPICosts(value, asyncCallbackGasLock uint64) map[string]ui gasMap["AsyncCallStep"] = value gasMap["AsyncCallbackGasLock"] = asyncCallbackGasLock gasMap["CreateAsyncCall"] = value + gasMap["CreateAsyncV3Call"] = value gasMap["SetAsyncCallback"] = value gasMap["SetAsyncGroupCallback"] = value gasMap["SetAsyncContextCallback"] = value diff --git a/executor/vmHooks.go b/executor/vmHooks.go index 87b9b1e3c..d503e61a5 100644 --- a/executor/vmHooks.go +++ b/executor/vmHooks.go @@ -40,6 +40,7 @@ type MainVMHooks interface { TransferESDTNFTExecute(destOffset MemPtr, tokenIDOffset MemPtr, tokenIDLen MemLength, valueOffset MemPtr, nonce int64, gasLimit int64, functionOffset MemPtr, functionLength MemLength, numArguments int32, argumentsLengthOffset MemPtr, dataOffset MemPtr) int32 MultiTransferESDTNFTExecute(destOffset MemPtr, numTokenTransfers int32, tokenTransfersArgsLengthOffset MemPtr, tokenTransferDataOffset MemPtr, gasLimit int64, functionOffset MemPtr, functionLength MemLength, numArguments int32, argumentsLengthOffset MemPtr, dataOffset MemPtr) int32 CreateAsyncCall(destOffset MemPtr, valueOffset MemPtr, dataOffset MemPtr, dataLength MemLength, successOffset MemPtr, successLength MemLength, errorOffset MemPtr, errorLength MemLength, gas int64, extraGasForCallback int64) int32 + CreateAsyncV3Call(destOffset MemPtr, valueOffset MemPtr, dataOffset MemPtr, dataLength MemLength, successOffset MemPtr, successLength MemLength, errorOffset MemPtr, errorLength MemLength, gas int64, extraGasForCallback int64) int32 SetAsyncContextCallback(callback MemPtr, callbackLength MemLength, data MemPtr, dataLength MemLength, gas int64) int32 UpgradeContract(destOffset MemPtr, gasLimit int64, valueOffset MemPtr, codeOffset MemPtr, codeMetadataOffset MemPtr, length MemLength, numArguments int32, argumentsLengthOffset MemPtr, dataOffset MemPtr) UpgradeFromSourceContract(destOffset MemPtr, gasLimit int64, valueOffset MemPtr, sourceContractAddressOffset MemPtr, codeMetadataOffset MemPtr, numArguments int32, argumentsLengthOffset MemPtr, dataOffset MemPtr) @@ -113,7 +114,7 @@ type ManagedVMHooks interface { ManagedGetPrevBlockRandomSeed(resultHandle int32) ManagedGetReturnData(resultID int32, resultHandle int32) ManagedGetMultiESDTCallValue(multiCallValueHandle int32) - ManagedGetBackTransfers(esdtTransfersValueHandle int32, callValueHandle int32) + ManagedGetBackTransfers(esdtTransfersValueHandle int32, egldValueHandle int32) ManagedGetESDTBalance(addressHandle int32, tokenIDHandle int32, nonce int64, valueHandle int32) ManagedGetESDTTokenData(addressHandle int32, tokenIDHandle int32, nonce int64, valueHandle int32, propertiesHandle int32, hashHandle int32, nameHandle int32, attributesHandle int32, creatorHandle int32, royaltiesHandle int32, urisHandle int32) ManagedAsyncCall(destHandle int32, valueHandle int32, functionHandle int32, argumentsHandle int32) diff --git a/executor/wrapper/wrapperVMHooks.go b/executor/wrapper/wrapperVMHooks.go index ee827f4c7..41280a569 100644 --- a/executor/wrapper/wrapperVMHooks.go +++ b/executor/wrapper/wrapperVMHooks.go @@ -203,6 +203,15 @@ func (w *WrapperVMHooks) CreateAsyncCall(destOffset executor.MemPtr, valueOffset return result } +// CreateAsyncV3Call VM hook wrapper +func (w *WrapperVMHooks) CreateAsyncV3Call(destOffset executor.MemPtr, valueOffset executor.MemPtr, dataOffset executor.MemPtr, dataLength executor.MemLength, successOffset executor.MemPtr, successLength executor.MemLength, errorOffset executor.MemPtr, errorLength executor.MemLength, gas int64, extraGasForCallback int64) int32 { + callInfo := fmt.Sprintf("CreateAsyncV3Call(%d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", destOffset, valueOffset, dataOffset, dataLength, successOffset, successLength, errorOffset, errorLength, gas, extraGasForCallback) + w.logger.LogVMHookCallBefore(callInfo) + result := w.wrappedVMHooks.CreateAsyncV3Call(destOffset, valueOffset, dataOffset, dataLength, successOffset, successLength, errorOffset, errorLength, gas, extraGasForCallback) + w.logger.LogVMHookCallAfter(callInfo) + return result +} + // SetAsyncContextCallback VM hook wrapper func (w *WrapperVMHooks) SetAsyncContextCallback(callback executor.MemPtr, callbackLength executor.MemLength, data executor.MemPtr, dataLength executor.MemLength, gas int64) int32 { callInfo := fmt.Sprintf("SetAsyncContextCallback(%d, %d, %d, %d, %d)", callback, callbackLength, data, dataLength, gas) @@ -806,10 +815,10 @@ func (w *WrapperVMHooks) ManagedGetMultiESDTCallValue(multiCallValueHandle int32 } // ManagedGetBackTransfers VM hook wrapper -func (w *WrapperVMHooks) ManagedGetBackTransfers(esdtTransfersValueHandle int32, callValueHandle int32) { - callInfo := fmt.Sprintf("ManagedGetBackTransfers(%d, %d)", esdtTransfersValueHandle, callValueHandle) +func (w *WrapperVMHooks) ManagedGetBackTransfers(esdtTransfersValueHandle int32, egldValueHandle int32) { + callInfo := fmt.Sprintf("ManagedGetBackTransfers(%d, %d)", esdtTransfersValueHandle, egldValueHandle) w.logger.LogVMHookCallBefore(callInfo) - w.wrappedVMHooks.ManagedGetBackTransfers(esdtTransfersValueHandle, callValueHandle) + w.wrappedVMHooks.ManagedGetBackTransfers(esdtTransfersValueHandle, egldValueHandle) w.logger.LogVMHookCallAfter(callInfo) } diff --git a/go.sum b/go.sum index e195000cc..a5d8fae12 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/TwiN/go-color v1.1.0 h1:yhLAHgjp2iAxmNjDiVb6Z073NE65yoaPlcki1Q22yyQ= github.com/TwiN/go-color v1.1.0/go.mod h1:aKVf4e1mD4ai2FtPifkDPP5iyoCwiK08YGzGwerjKo0= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -83,6 +85,7 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/multiversx/concurrent-map v0.1.4/go.mod h1:8cWFRJDOrWHOTNSqgYCUvwT7c7eFQ4U2vKMOp4A/9+o= github.com/multiversx/mx-chain-core-go v1.2.19-0.20240321150532-5960a8922b18 h1:hytqre8g+NIHsq/Kxl/lwIykHna57Gv+E38tt4K5A9I= github.com/multiversx/mx-chain-core-go v1.2.19-0.20240321150532-5960a8922b18/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= github.com/multiversx/mx-chain-crypto-go v1.2.10-0.20231206065052-38843c1f1479 h1:beVIhs5ysylwNplQ/bZ0h5DoDlqKNWgpWE/NMHHNmAw= @@ -109,6 +112,7 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -125,6 +129,7 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho= github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= @@ -147,6 +152,7 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -163,9 +169,11 @@ golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= diff --git a/mock/context/executorMockFunc.go b/mock/context/executorMockFunc.go index c4cc3f95c..40db87da6 100644 --- a/mock/context/executorMockFunc.go +++ b/mock/context/executorMockFunc.go @@ -30,6 +30,7 @@ var functionNames = map[string]struct{}{ "transferESDTNFTExecute": empty, "multiTransferESDTNFTExecute": empty, "createAsyncCall": empty, + "createAsyncV3Call": empty, "setAsyncContextCallback": empty, "upgradeContract": empty, "upgradeFromSourceContract": empty, diff --git a/vmhost/asyncCall.go b/vmhost/asyncCall.go index 0f0151466..36d56240e 100644 --- a/vmhost/asyncCall.go +++ b/vmhost/asyncCall.go @@ -23,21 +23,25 @@ type AsyncCall struct { CallbackClosure []byte IsBuiltinFunctionCall bool + IsAsyncV3 bool + IsCallbackPending bool } // Clone creates a deep clone of the AsyncCall func (ac *AsyncCall) Clone() *AsyncCall { clone := &AsyncCall{ - CallID: ac.CallID, - Status: ac.Status, - ExecutionMode: ac.ExecutionMode, - Destination: make([]byte, len(ac.Destination)), - Data: make([]byte, len(ac.Data)), - GasLimit: ac.GasLimit, - GasLocked: ac.GasLocked, - ValueBytes: make([]byte, len(ac.ValueBytes)), - SuccessCallback: ac.SuccessCallback, - ErrorCallback: ac.ErrorCallback, + CallID: ac.CallID, + Status: ac.Status, + ExecutionMode: ac.ExecutionMode, + Destination: make([]byte, len(ac.Destination)), + Data: make([]byte, len(ac.Data)), + GasLimit: ac.GasLimit, + GasLocked: ac.GasLocked, + ValueBytes: make([]byte, len(ac.ValueBytes)), + SuccessCallback: ac.SuccessCallback, + ErrorCallback: ac.ErrorCallback, + IsAsyncV3: ac.IsAsyncV3, + IsCallbackPending: ac.IsCallbackPending, } copy(clone.Destination, ac.Destination) @@ -105,6 +109,11 @@ func (ac *AsyncCall) HasDefinedAnyCallback() bool { return len(ac.SuccessCallback) > 0 || len(ac.ErrorCallback) > 0 } +// MarkSkippedCallback this async call has skipped calling its callback +func (ac *AsyncCall) MarkSkippedCallback() { + ac.IsCallbackPending = true +} + // UpdateStatus sets the status of the async call depending on the provided ReturnCode func (ac *AsyncCall) UpdateStatus(returnCode vmcommon.ReturnCode) { ac.Status = AsyncCallResolved @@ -135,17 +144,19 @@ func (ac *AsyncCall) IsInterfaceNil() bool { func (ac *AsyncCall) toSerializable() *SerializableAsyncCall { return &SerializableAsyncCall{ - CallID: ac.CallID, - Status: SerializableAsyncCallStatus(ac.Status), - ExecutionMode: SerializableAsyncCallExecutionMode(ac.ExecutionMode), - Destination: ac.Destination, - Data: ac.Data, - GasLimit: ac.GasLimit, - GasLocked: ac.GasLocked, - ValueBytes: ac.ValueBytes, - SuccessCallback: ac.SuccessCallback, - ErrorCallback: ac.ErrorCallback, - CallbackClosure: ac.CallbackClosure, + CallID: ac.CallID, + Status: SerializableAsyncCallStatus(ac.Status), + ExecutionMode: SerializableAsyncCallExecutionMode(ac.ExecutionMode), + Destination: ac.Destination, + Data: ac.Data, + GasLimit: ac.GasLimit, + GasLocked: ac.GasLocked, + ValueBytes: ac.ValueBytes, + SuccessCallback: ac.SuccessCallback, + ErrorCallback: ac.ErrorCallback, + CallbackClosure: ac.CallbackClosure, + IsAsyncV3: ac.IsAsyncV3, + IsCallbackPending: ac.IsCallbackPending, } } @@ -159,16 +170,18 @@ func fromSerializableAsyncCalls(serializableAsyncCalls []*SerializableAsyncCall) func (serAsyncCall *SerializableAsyncCall) fromSerializable() *AsyncCall { return &AsyncCall{ - CallID: serAsyncCall.CallID, - Status: AsyncCallStatus(serAsyncCall.Status), - ExecutionMode: AsyncCallExecutionMode(serAsyncCall.ExecutionMode), - Destination: serAsyncCall.Destination, - Data: serAsyncCall.Data, - GasLimit: serAsyncCall.GasLimit, - GasLocked: serAsyncCall.GasLocked, - ValueBytes: serAsyncCall.ValueBytes, - SuccessCallback: serAsyncCall.SuccessCallback, - ErrorCallback: serAsyncCall.ErrorCallback, - CallbackClosure: serAsyncCall.CallbackClosure, + CallID: serAsyncCall.CallID, + Status: AsyncCallStatus(serAsyncCall.Status), + ExecutionMode: AsyncCallExecutionMode(serAsyncCall.ExecutionMode), + Destination: serAsyncCall.Destination, + Data: serAsyncCall.Data, + GasLimit: serAsyncCall.GasLimit, + GasLocked: serAsyncCall.GasLocked, + ValueBytes: serAsyncCall.ValueBytes, + SuccessCallback: serAsyncCall.SuccessCallback, + ErrorCallback: serAsyncCall.ErrorCallback, + CallbackClosure: serAsyncCall.CallbackClosure, + IsAsyncV3: serAsyncCall.IsAsyncV3, + IsCallbackPending: serAsyncCall.IsCallbackPending, } } diff --git a/vmhost/asyncCall.pb.go b/vmhost/asyncCall.pb.go index 63b6dd399..3fbecdf6f 100644 --- a/vmhost/asyncCall.pb.go +++ b/vmhost/asyncCall.pb.go @@ -4,16 +4,12 @@ package vmhost import ( - bytes "bytes" fmt "fmt" _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" io "io" math "math" math_bits "math/bits" - reflect "reflect" - strconv "strconv" - strings "strings" ) // Reference imports to suppress errors if they are not otherwise used. @@ -30,9 +26,9 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type SerializableAsyncCallStatus int32 const ( - SerializableAsyncCallPending SerializableAsyncCallStatus = 0 - SerializableAsyncCallResolved SerializableAsyncCallStatus = 1 - SerializableAsyncCallRejected SerializableAsyncCallStatus = 2 + SerializableAsyncCallStatus_SerializableAsyncCallPending SerializableAsyncCallStatus = 0 + SerializableAsyncCallStatus_SerializableAsyncCallResolved SerializableAsyncCallStatus = 1 + SerializableAsyncCallStatus_SerializableAsyncCallRejected SerializableAsyncCallStatus = 2 ) var SerializableAsyncCallStatus_name = map[int32]string{ @@ -47,6 +43,10 @@ var SerializableAsyncCallStatus_value = map[string]int32{ "SerializableAsyncCallRejected": 2, } +func (x SerializableAsyncCallStatus) String() string { + return proto.EnumName(SerializableAsyncCallStatus_name, int32(x)) +} + func (SerializableAsyncCallStatus) EnumDescriptor() ([]byte, []int) { return fileDescriptor_a0e9b586d6e1f667, []int{0} } @@ -54,10 +54,10 @@ func (SerializableAsyncCallStatus) EnumDescriptor() ([]byte, []int) { type SerializableAsyncCallExecutionMode int32 const ( - SerializableSyncExecution SerializableAsyncCallExecutionMode = 0 - SerializableAsyncBuiltinFuncIntraShard SerializableAsyncCallExecutionMode = 1 - SerializableAsyncBuiltinFuncCrossShard SerializableAsyncCallExecutionMode = 2 - SerializableAsyncUnknown SerializableAsyncCallExecutionMode = 3 + SerializableAsyncCallExecutionMode_SerializableSyncExecution SerializableAsyncCallExecutionMode = 0 + SerializableAsyncCallExecutionMode_SerializableAsyncBuiltinFuncIntraShard SerializableAsyncCallExecutionMode = 1 + SerializableAsyncCallExecutionMode_SerializableAsyncBuiltinFuncCrossShard SerializableAsyncCallExecutionMode = 2 + SerializableAsyncCallExecutionMode_SerializableAsyncUnknown SerializableAsyncCallExecutionMode = 3 ) var SerializableAsyncCallExecutionMode_name = map[int32]string{ @@ -74,26 +74,33 @@ var SerializableAsyncCallExecutionMode_value = map[string]int32{ "SerializableAsyncUnknown": 3, } +func (x SerializableAsyncCallExecutionMode) String() string { + return proto.EnumName(SerializableAsyncCallExecutionMode_name, int32(x)) +} + func (SerializableAsyncCallExecutionMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor_a0e9b586d6e1f667, []int{1} } type SerializableAsyncCall struct { - CallID []byte `protobuf:"bytes,1,opt,name=CallID,proto3" json:"CallID,omitempty"` - Status SerializableAsyncCallStatus `protobuf:"varint,2,opt,name=Status,proto3,enum=vmhost.SerializableAsyncCallStatus" json:"Status,omitempty"` - ExecutionMode SerializableAsyncCallExecutionMode `protobuf:"varint,3,opt,name=ExecutionMode,proto3,enum=vmhost.SerializableAsyncCallExecutionMode" json:"ExecutionMode,omitempty"` - Destination []byte `protobuf:"bytes,5,opt,name=Destination,proto3" json:"Destination,omitempty"` - Data []byte `protobuf:"bytes,6,opt,name=Data,proto3" json:"Data,omitempty"` - GasLimit uint64 `protobuf:"varint,7,opt,name=GasLimit,proto3" json:"GasLimit,omitempty"` - GasLocked uint64 `protobuf:"varint,8,opt,name=GasLocked,proto3" json:"GasLocked,omitempty"` - ValueBytes []byte `protobuf:"bytes,9,opt,name=ValueBytes,proto3" json:"ValueBytes,omitempty"` - SuccessCallback string `protobuf:"bytes,10,opt,name=SuccessCallback,proto3" json:"SuccessCallback,omitempty"` - ErrorCallback string `protobuf:"bytes,11,opt,name=ErrorCallback,proto3" json:"ErrorCallback,omitempty"` - CallbackClosure []byte `protobuf:"bytes,12,opt,name=CallbackClosure,proto3" json:"CallbackClosure,omitempty"` + CallID []byte `protobuf:"bytes,1,opt,name=CallID,proto3" json:"CallID,omitempty"` + Status SerializableAsyncCallStatus `protobuf:"varint,2,opt,name=Status,proto3,enum=vmhost.SerializableAsyncCallStatus" json:"Status,omitempty"` + ExecutionMode SerializableAsyncCallExecutionMode `protobuf:"varint,3,opt,name=ExecutionMode,proto3,enum=vmhost.SerializableAsyncCallExecutionMode" json:"ExecutionMode,omitempty"` + Destination []byte `protobuf:"bytes,5,opt,name=Destination,proto3" json:"Destination,omitempty"` + Data []byte `protobuf:"bytes,6,opt,name=Data,proto3" json:"Data,omitempty"` + GasLimit uint64 `protobuf:"varint,7,opt,name=GasLimit,proto3" json:"GasLimit,omitempty"` + GasLocked uint64 `protobuf:"varint,8,opt,name=GasLocked,proto3" json:"GasLocked,omitempty"` + ValueBytes []byte `protobuf:"bytes,9,opt,name=ValueBytes,proto3" json:"ValueBytes,omitempty"` + SuccessCallback string `protobuf:"bytes,10,opt,name=SuccessCallback,proto3" json:"SuccessCallback,omitempty"` + ErrorCallback string `protobuf:"bytes,11,opt,name=ErrorCallback,proto3" json:"ErrorCallback,omitempty"` + CallbackClosure []byte `protobuf:"bytes,12,opt,name=CallbackClosure,proto3" json:"CallbackClosure,omitempty"` + IsAsyncV3 bool `protobuf:"varint,13,opt,name=IsAsyncV3,proto3" json:"IsAsyncV3,omitempty"` + IsCallbackPending bool `protobuf:"varint,14,opt,name=IsCallbackPending,proto3" json:"IsCallbackPending,omitempty"` } -func (m *SerializableAsyncCall) Reset() { *m = SerializableAsyncCall{} } -func (*SerializableAsyncCall) ProtoMessage() {} +func (m *SerializableAsyncCall) Reset() { *m = SerializableAsyncCall{} } +func (m *SerializableAsyncCall) String() string { return proto.CompactTextString(m) } +func (*SerializableAsyncCall) ProtoMessage() {} func (*SerializableAsyncCall) Descriptor() ([]byte, []int) { return fileDescriptor_a0e9b586d6e1f667, []int{0} } @@ -131,14 +138,14 @@ func (m *SerializableAsyncCall) GetStatus() SerializableAsyncCallStatus { if m != nil { return m.Status } - return SerializableAsyncCallPending + return SerializableAsyncCallStatus_SerializableAsyncCallPending } func (m *SerializableAsyncCall) GetExecutionMode() SerializableAsyncCallExecutionMode { if m != nil { return m.ExecutionMode } - return SerializableSyncExecution + return SerializableAsyncCallExecutionMode_SerializableSyncExecution } func (m *SerializableAsyncCall) GetDestination() []byte { @@ -197,6 +204,20 @@ func (m *SerializableAsyncCall) GetCallbackClosure() []byte { return nil } +func (m *SerializableAsyncCall) GetIsAsyncV3() bool { + if m != nil { + return m.IsAsyncV3 + } + return false +} + +func (m *SerializableAsyncCall) GetIsCallbackPending() bool { + if m != nil { + return m.IsCallbackPending + } + return false +} + type SerializableAsyncCallGroup struct { Callback string `protobuf:"bytes,1,opt,name=Callback,proto3" json:"Callback,omitempty"` GasLocked uint64 `protobuf:"varint,2,opt,name=GasLocked,proto3" json:"GasLocked,omitempty"` @@ -205,8 +226,9 @@ type SerializableAsyncCallGroup struct { AsyncCalls []*SerializableAsyncCall `protobuf:"bytes,5,rep,name=AsyncCalls,proto3" json:"AsyncCalls,omitempty"` } -func (m *SerializableAsyncCallGroup) Reset() { *m = SerializableAsyncCallGroup{} } -func (*SerializableAsyncCallGroup) ProtoMessage() {} +func (m *SerializableAsyncCallGroup) Reset() { *m = SerializableAsyncCallGroup{} } +func (m *SerializableAsyncCallGroup) String() string { return proto.CompactTextString(m) } +func (*SerializableAsyncCallGroup) ProtoMessage() {} func (*SerializableAsyncCallGroup) Descriptor() ([]byte, []int) { return fileDescriptor_a0e9b586d6e1f667, []int{1} } @@ -278,198 +300,45 @@ func init() { func init() { proto.RegisterFile("asyncCall.proto", fileDescriptor_a0e9b586d6e1f667) } var fileDescriptor_a0e9b586d6e1f667 = []byte{ - // 564 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x54, 0xcd, 0x6e, 0x13, 0x31, - 0x10, 0x5e, 0x27, 0x6d, 0x68, 0xa7, 0x2d, 0x8d, 0x2c, 0x81, 0x4c, 0x69, 0xad, 0x25, 0x20, 0xb4, - 0x8a, 0x44, 0x2a, 0x95, 0x23, 0x42, 0x82, 0xfe, 0x50, 0x55, 0x02, 0xa9, 0xda, 0x08, 0x0e, 0xdc, - 0x9c, 0x5d, 0x37, 0x35, 0xd9, 0xd8, 0xd5, 0xda, 0x5b, 0x08, 0x27, 0x2e, 0xdc, 0x79, 0x0c, 0x5e, - 0x81, 0x37, 0xe8, 0x31, 0xc7, 0x70, 0x23, 0x9b, 0x0b, 0xc7, 0x3e, 0x02, 0x5a, 0x27, 0x59, 0x92, - 0x34, 0x4a, 0x4f, 0x3b, 0xf3, 0xcd, 0x37, 0xdf, 0x37, 0x9e, 0xb5, 0x0c, 0x9b, 0x4c, 0x77, 0x64, - 0x70, 0xc0, 0xa2, 0xa8, 0x76, 0x11, 0x2b, 0xa3, 0x70, 0xe9, 0xb2, 0x7d, 0xae, 0xb4, 0xd9, 0x7a, - 0xd6, 0x14, 0xe6, 0x3c, 0x69, 0xd4, 0x02, 0xd5, 0xde, 0x6d, 0xaa, 0xa6, 0xda, 0xb5, 0xe5, 0x46, - 0x72, 0x66, 0x33, 0x9b, 0xd8, 0x68, 0xd8, 0x56, 0xb9, 0x2a, 0xc2, 0xbd, 0x3a, 0x8f, 0x05, 0x8b, - 0xc4, 0x57, 0xd6, 0x88, 0xf8, 0xeb, 0xb1, 0x2c, 0xbe, 0x0f, 0xa5, 0xec, 0x7b, 0x72, 0x48, 0x90, - 0x8b, 0xbc, 0x75, 0x7f, 0x94, 0xe1, 0x17, 0x50, 0xaa, 0x1b, 0x66, 0x12, 0x4d, 0x0a, 0x2e, 0xf2, - 0xee, 0xee, 0x3d, 0xae, 0x0d, 0x9d, 0x6b, 0x73, 0x65, 0x86, 0x54, 0x7f, 0xd4, 0x82, 0x4f, 0x61, - 0xe3, 0xe8, 0x0b, 0x0f, 0x12, 0x23, 0x94, 0x7c, 0xa7, 0x42, 0x4e, 0x8a, 0x56, 0xa3, 0xba, 0x50, - 0x63, 0xaa, 0xc3, 0x9f, 0x16, 0xc0, 0x2e, 0xac, 0x1d, 0x72, 0x6d, 0x84, 0x64, 0x19, 0x44, 0x96, - 0xed, 0xac, 0x93, 0x10, 0xc6, 0xb0, 0x74, 0xc8, 0x0c, 0x23, 0x25, 0x5b, 0xb2, 0x31, 0xde, 0x82, - 0x95, 0x63, 0xa6, 0xdf, 0x8a, 0xb6, 0x30, 0xe4, 0x8e, 0x8b, 0xbc, 0x25, 0x3f, 0xcf, 0xf1, 0x36, - 0xac, 0x66, 0xb1, 0x0a, 0x5a, 0x3c, 0x24, 0x2b, 0xb6, 0xf8, 0x1f, 0xc0, 0x14, 0xe0, 0x03, 0x8b, - 0x12, 0xbe, 0xdf, 0x31, 0x5c, 0x93, 0x55, 0xab, 0x39, 0x81, 0x60, 0x0f, 0x36, 0xeb, 0x49, 0x10, - 0x70, 0xad, 0xb3, 0xd1, 0x1b, 0x2c, 0x68, 0x11, 0x70, 0x91, 0xb7, 0xea, 0xcf, 0xc2, 0xf8, 0x09, - 0x6c, 0x1c, 0xc5, 0xb1, 0x8a, 0x73, 0xde, 0x9a, 0xe5, 0x4d, 0x83, 0x99, 0xde, 0x38, 0x3e, 0x88, - 0x94, 0x4e, 0x62, 0x4e, 0xd6, 0xad, 0xe9, 0x2c, 0x5c, 0xf9, 0x8d, 0x60, 0x6b, 0xee, 0xfe, 0x8e, - 0x63, 0x95, 0x5c, 0x64, 0x47, 0xce, 0x9d, 0x90, 0x75, 0xca, 0xf3, 0xe9, 0x23, 0x17, 0x66, 0x8f, - 0x5c, 0x81, 0xf5, 0x31, 0xd3, 0x2e, 0xb2, 0x68, 0xfd, 0xa7, 0xb0, 0x6c, 0x2d, 0x27, 0x21, 0x97, - 0x46, 0x9c, 0x09, 0x1e, 0x93, 0x25, 0xab, 0x3f, 0x81, 0xe0, 0x97, 0x00, 0xf9, 0x3c, 0x9a, 0x2c, - 0xbb, 0x45, 0x6f, 0x6d, 0x6f, 0x67, 0xe1, 0x5f, 0xf7, 0x27, 0x1a, 0xaa, 0xdf, 0x11, 0x3c, 0x5c, - 0x70, 0xbf, 0xb0, 0x0b, 0xdb, 0x73, 0xcb, 0xa7, 0x5c, 0x86, 0x42, 0x36, 0xcb, 0x0e, 0x7e, 0x04, - 0x3b, 0xf3, 0x6d, 0xb8, 0x56, 0xd1, 0x25, 0x0f, 0xcb, 0x68, 0x01, 0xe5, 0x13, 0x0f, 0x0c, 0x0f, - 0xcb, 0x85, 0xea, 0x2f, 0x04, 0x95, 0xdb, 0xef, 0x28, 0xde, 0x81, 0x07, 0x93, 0xac, 0x7a, 0x47, - 0x06, 0x39, 0xa1, 0xec, 0xe0, 0x2a, 0x3c, 0xbd, 0x21, 0xb2, 0x9f, 0x88, 0xc8, 0x08, 0xf9, 0x26, - 0x91, 0xc1, 0x89, 0x34, 0x31, 0xab, 0x9f, 0xb3, 0x38, 0x1b, 0xea, 0x16, 0xee, 0x41, 0xac, 0xb4, - 0x1e, 0x72, 0x0b, 0x78, 0x1b, 0xc8, 0x0d, 0xee, 0x7b, 0xd9, 0x92, 0xea, 0xb3, 0x2c, 0x17, 0xf7, - 0x5f, 0x75, 0xfb, 0xd4, 0xe9, 0xf5, 0xa9, 0x73, 0xdd, 0xa7, 0xe8, 0x5b, 0x4a, 0xd1, 0xcf, 0x94, - 0xa2, 0xab, 0x94, 0xa2, 0x6e, 0x4a, 0x51, 0x2f, 0xa5, 0xe8, 0x4f, 0x4a, 0xd1, 0xdf, 0x94, 0x3a, - 0xd7, 0x29, 0x45, 0x3f, 0x06, 0xd4, 0xe9, 0x0e, 0xa8, 0xd3, 0x1b, 0x50, 0xe7, 0xe3, 0xe8, 0x6d, - 0x69, 0x94, 0xec, 0x9b, 0xf1, 0xfc, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xde, 0x7d, 0x58, 0x3d, - 0x7d, 0x04, 0x00, 0x00, + // 565 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x54, 0x4f, 0x6f, 0x1a, 0x3f, + 0x10, 0xc5, 0x40, 0xf8, 0x25, 0x13, 0x48, 0xf8, 0x59, 0x6a, 0xe5, 0x52, 0x58, 0x6d, 0x69, 0x54, + 0xad, 0x50, 0x4b, 0xa4, 0xe4, 0x58, 0xf5, 0x50, 0x20, 0x8d, 0x90, 0x5a, 0x29, 0x5a, 0xd4, 0x1c, + 0x7a, 0x33, 0xbb, 0x0e, 0xb8, 0x2c, 0x76, 0xb4, 0xf6, 0xa6, 0xa5, 0xf7, 0xde, 0x7b, 0xe8, 0x97, + 0xe9, 0x37, 0xe8, 0x31, 0xc7, 0xf4, 0x56, 0xc1, 0x17, 0xa9, 0xd6, 0xc0, 0x86, 0x7f, 0x22, 0xa7, + 0x9d, 0x79, 0xf3, 0xe6, 0xcd, 0xdb, 0xb1, 0x65, 0x38, 0xa4, 0x6a, 0x24, 0xbc, 0x26, 0x0d, 0x82, + 0xfa, 0x75, 0x28, 0xb5, 0xc4, 0xb9, 0x9b, 0x61, 0x5f, 0x2a, 0x5d, 0x7a, 0xd5, 0xe3, 0xba, 0x1f, + 0x75, 0xeb, 0x9e, 0x1c, 0x1e, 0xf7, 0x64, 0x4f, 0x1e, 0x9b, 0x72, 0x37, 0xba, 0x32, 0x99, 0x49, + 0x4c, 0x34, 0x6d, 0xab, 0xfe, 0xcc, 0xc2, 0xa3, 0x0e, 0x0b, 0x39, 0x0d, 0xf8, 0x37, 0xda, 0x0d, + 0xd8, 0xdb, 0xb9, 0x2c, 0x7e, 0x0c, 0xb9, 0xf8, 0xdb, 0x6e, 0x11, 0x64, 0x23, 0x27, 0xef, 0xce, + 0x32, 0xfc, 0x1a, 0x72, 0x1d, 0x4d, 0x75, 0xa4, 0x48, 0xda, 0x46, 0xce, 0xc1, 0xc9, 0xf3, 0xfa, + 0x74, 0x72, 0x7d, 0xa3, 0xcc, 0x94, 0xea, 0xce, 0x5a, 0xf0, 0x05, 0x14, 0xce, 0xbe, 0x32, 0x2f, + 0xd2, 0x5c, 0x8a, 0x0f, 0xd2, 0x67, 0x24, 0x63, 0x34, 0x6a, 0x5b, 0x35, 0x96, 0x3a, 0xdc, 0x65, + 0x01, 0x6c, 0xc3, 0x7e, 0x8b, 0x29, 0xcd, 0x05, 0x8d, 0x21, 0xb2, 0x63, 0xbc, 0x2e, 0x42, 0x18, + 0x43, 0xb6, 0x45, 0x35, 0x25, 0x39, 0x53, 0x32, 0x31, 0x2e, 0xc1, 0xee, 0x39, 0x55, 0xef, 0xf9, + 0x90, 0x6b, 0xf2, 0x9f, 0x8d, 0x9c, 0xac, 0x9b, 0xe4, 0xb8, 0x0c, 0x7b, 0x71, 0x2c, 0xbd, 0x01, + 0xf3, 0xc9, 0xae, 0x29, 0xde, 0x03, 0xd8, 0x02, 0xb8, 0xa4, 0x41, 0xc4, 0x1a, 0x23, 0xcd, 0x14, + 0xd9, 0x33, 0x9a, 0x0b, 0x08, 0x76, 0xe0, 0xb0, 0x13, 0x79, 0x1e, 0x53, 0x2a, 0xb6, 0xde, 0xa5, + 0xde, 0x80, 0x80, 0x8d, 0x9c, 0x3d, 0x77, 0x15, 0xc6, 0x47, 0x50, 0x38, 0x0b, 0x43, 0x19, 0x26, + 0xbc, 0x7d, 0xc3, 0x5b, 0x06, 0x63, 0xbd, 0x79, 0xdc, 0x0c, 0xa4, 0x8a, 0x42, 0x46, 0xf2, 0x66, + 0xe8, 0x2a, 0x1c, 0xfb, 0x6e, 0x2b, 0xb3, 0xb4, 0xcb, 0x53, 0x52, 0xb0, 0x91, 0xb3, 0xeb, 0xde, + 0x03, 0xf8, 0x25, 0xfc, 0xdf, 0x4e, 0x66, 0x5f, 0x30, 0xe1, 0x73, 0xd1, 0x23, 0x07, 0x86, 0xb5, + 0x5e, 0xa8, 0xfe, 0x41, 0x50, 0xda, 0x78, 0x16, 0xe7, 0xa1, 0x8c, 0xae, 0xe3, 0xf5, 0x25, 0xae, + 0x91, 0x71, 0x9d, 0xe4, 0xcb, 0xeb, 0x4b, 0xaf, 0xae, 0xaf, 0x0a, 0xf9, 0x39, 0xd3, 0x1c, 0x4a, + 0xc6, 0xfc, 0xcb, 0x12, 0x16, 0xaf, 0xb8, 0xed, 0x33, 0xa1, 0xf9, 0x15, 0x67, 0x21, 0xc9, 0x1a, + 0xfd, 0x05, 0x04, 0xbf, 0x01, 0x48, 0xfc, 0x28, 0xb2, 0x63, 0x67, 0x9c, 0xfd, 0x93, 0xca, 0xd6, + 0x1b, 0xe4, 0x2e, 0x34, 0xd4, 0xbe, 0x23, 0x78, 0xba, 0xe5, 0xae, 0x62, 0x1b, 0xca, 0x1b, 0xcb, + 0xb3, 0xdd, 0x14, 0x53, 0xf8, 0x19, 0x54, 0x36, 0x8f, 0x61, 0x4a, 0x06, 0x37, 0xcc, 0x2f, 0xa2, + 0x2d, 0x94, 0xcf, 0xcc, 0xd3, 0xcc, 0x2f, 0xa6, 0x6b, 0xbf, 0x10, 0x54, 0x1f, 0xbe, 0xef, 0xb8, + 0x02, 0x4f, 0x16, 0x59, 0x9d, 0x91, 0xf0, 0x12, 0x42, 0x31, 0x85, 0x6b, 0xf0, 0x62, 0x4d, 0xa4, + 0x11, 0xf1, 0x40, 0x73, 0xf1, 0x2e, 0x12, 0x5e, 0x5b, 0xe8, 0x90, 0x76, 0xfa, 0x34, 0x8c, 0x4d, + 0x3d, 0xc0, 0x6d, 0x86, 0x52, 0xa9, 0x29, 0x37, 0x8d, 0xcb, 0x40, 0xd6, 0xb8, 0x1f, 0xc5, 0x40, + 0xc8, 0x2f, 0xa2, 0x98, 0x69, 0x1c, 0xfd, 0x1e, 0x5b, 0xe8, 0x76, 0x6c, 0xa1, 0xbb, 0xb1, 0x85, + 0xfe, 0x8e, 0x2d, 0xf4, 0x63, 0x62, 0xa5, 0x6e, 0x27, 0x56, 0xea, 0x6e, 0x62, 0xa5, 0x3e, 0xcd, + 0xde, 0xa2, 0x6e, 0xce, 0xbc, 0x31, 0xa7, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x35, 0x55, 0x47, + 0x36, 0xad, 0x04, 0x00, 0x00, } -func (x SerializableAsyncCallStatus) String() string { - s, ok := SerializableAsyncCallStatus_name[int32(x)] - if ok { - return s - } - return strconv.Itoa(int(x)) -} -func (x SerializableAsyncCallExecutionMode) String() string { - s, ok := SerializableAsyncCallExecutionMode_name[int32(x)] - if ok { - return s - } - return strconv.Itoa(int(x)) -} -func (this *SerializableAsyncCall) Equal(that interface{}) bool { - if that == nil { - return this == nil - } - - that1, ok := that.(*SerializableAsyncCall) - if !ok { - that2, ok := that.(SerializableAsyncCall) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - return this == nil - } else if this == nil { - return false - } - if !bytes.Equal(this.CallID, that1.CallID) { - return false - } - if this.Status != that1.Status { - return false - } - if this.ExecutionMode != that1.ExecutionMode { - return false - } - if !bytes.Equal(this.Destination, that1.Destination) { - return false - } - if !bytes.Equal(this.Data, that1.Data) { - return false - } - if this.GasLimit != that1.GasLimit { - return false - } - if this.GasLocked != that1.GasLocked { - return false - } - if !bytes.Equal(this.ValueBytes, that1.ValueBytes) { - return false - } - if this.SuccessCallback != that1.SuccessCallback { - return false - } - if this.ErrorCallback != that1.ErrorCallback { - return false - } - if !bytes.Equal(this.CallbackClosure, that1.CallbackClosure) { - return false - } - return true -} -func (this *SerializableAsyncCallGroup) Equal(that interface{}) bool { - if that == nil { - return this == nil - } - - that1, ok := that.(*SerializableAsyncCallGroup) - if !ok { - that2, ok := that.(SerializableAsyncCallGroup) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - return this == nil - } else if this == nil { - return false - } - if this.Callback != that1.Callback { - return false - } - if this.GasLocked != that1.GasLocked { - return false - } - if !bytes.Equal(this.CallbackData, that1.CallbackData) { - return false - } - if this.Identifier != that1.Identifier { - return false - } - if len(this.AsyncCalls) != len(that1.AsyncCalls) { - return false - } - for i := range this.AsyncCalls { - if !this.AsyncCalls[i].Equal(that1.AsyncCalls[i]) { - return false - } - } - return true -} -func (this *SerializableAsyncCall) GoString() string { - if this == nil { - return "nil" - } - s := make([]string, 0, 15) - s = append(s, "&vmhost.SerializableAsyncCall{") - s = append(s, "CallID: "+fmt.Sprintf("%#v", this.CallID)+",\n") - s = append(s, "Status: "+fmt.Sprintf("%#v", this.Status)+",\n") - s = append(s, "ExecutionMode: "+fmt.Sprintf("%#v", this.ExecutionMode)+",\n") - s = append(s, "Destination: "+fmt.Sprintf("%#v", this.Destination)+",\n") - s = append(s, "Data: "+fmt.Sprintf("%#v", this.Data)+",\n") - s = append(s, "GasLimit: "+fmt.Sprintf("%#v", this.GasLimit)+",\n") - s = append(s, "GasLocked: "+fmt.Sprintf("%#v", this.GasLocked)+",\n") - s = append(s, "ValueBytes: "+fmt.Sprintf("%#v", this.ValueBytes)+",\n") - s = append(s, "SuccessCallback: "+fmt.Sprintf("%#v", this.SuccessCallback)+",\n") - s = append(s, "ErrorCallback: "+fmt.Sprintf("%#v", this.ErrorCallback)+",\n") - s = append(s, "CallbackClosure: "+fmt.Sprintf("%#v", this.CallbackClosure)+",\n") - s = append(s, "}") - return strings.Join(s, "") -} -func (this *SerializableAsyncCallGroup) GoString() string { - if this == nil { - return "nil" - } - s := make([]string, 0, 9) - s = append(s, "&vmhost.SerializableAsyncCallGroup{") - s = append(s, "Callback: "+fmt.Sprintf("%#v", this.Callback)+",\n") - s = append(s, "GasLocked: "+fmt.Sprintf("%#v", this.GasLocked)+",\n") - s = append(s, "CallbackData: "+fmt.Sprintf("%#v", this.CallbackData)+",\n") - s = append(s, "Identifier: "+fmt.Sprintf("%#v", this.Identifier)+",\n") - if this.AsyncCalls != nil { - s = append(s, "AsyncCalls: "+fmt.Sprintf("%#v", this.AsyncCalls)+",\n") - } - s = append(s, "}") - return strings.Join(s, "") -} -func valueToGoStringAsyncCall(v interface{}, typ string) string { - rv := reflect.ValueOf(v) - if rv.IsNil() { - return "nil" - } - pv := reflect.Indirect(rv).Interface() - return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) -} func (m *SerializableAsyncCall) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -490,6 +359,26 @@ func (m *SerializableAsyncCall) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.IsCallbackPending { + i-- + if m.IsCallbackPending { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x70 + } + if m.IsAsyncV3 { + i-- + if m.IsAsyncV3 { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x68 + } if len(m.CallbackClosure) > 0 { i -= len(m.CallbackClosure) copy(dAtA[i:], m.CallbackClosure) @@ -682,6 +571,12 @@ func (m *SerializableAsyncCall) Size() (n int) { if l > 0 { n += 1 + l + sovAsyncCall(uint64(l)) } + if m.IsAsyncV3 { + n += 2 + } + if m.IsCallbackPending { + n += 2 + } return n } @@ -721,53 +616,6 @@ func sovAsyncCall(x uint64) (n int) { func sozAsyncCall(x uint64) (n int) { return sovAsyncCall(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } -func (this *SerializableAsyncCall) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&SerializableAsyncCall{`, - `CallID:` + fmt.Sprintf("%v", this.CallID) + `,`, - `Status:` + fmt.Sprintf("%v", this.Status) + `,`, - `ExecutionMode:` + fmt.Sprintf("%v", this.ExecutionMode) + `,`, - `Destination:` + fmt.Sprintf("%v", this.Destination) + `,`, - `Data:` + fmt.Sprintf("%v", this.Data) + `,`, - `GasLimit:` + fmt.Sprintf("%v", this.GasLimit) + `,`, - `GasLocked:` + fmt.Sprintf("%v", this.GasLocked) + `,`, - `ValueBytes:` + fmt.Sprintf("%v", this.ValueBytes) + `,`, - `SuccessCallback:` + fmt.Sprintf("%v", this.SuccessCallback) + `,`, - `ErrorCallback:` + fmt.Sprintf("%v", this.ErrorCallback) + `,`, - `CallbackClosure:` + fmt.Sprintf("%v", this.CallbackClosure) + `,`, - `}`, - }, "") - return s -} -func (this *SerializableAsyncCallGroup) String() string { - if this == nil { - return "nil" - } - repeatedStringForAsyncCalls := "[]*SerializableAsyncCall{" - for _, f := range this.AsyncCalls { - repeatedStringForAsyncCalls += strings.Replace(f.String(), "SerializableAsyncCall", "SerializableAsyncCall", 1) + "," - } - repeatedStringForAsyncCalls += "}" - s := strings.Join([]string{`&SerializableAsyncCallGroup{`, - `Callback:` + fmt.Sprintf("%v", this.Callback) + `,`, - `GasLocked:` + fmt.Sprintf("%v", this.GasLocked) + `,`, - `CallbackData:` + fmt.Sprintf("%v", this.CallbackData) + `,`, - `Identifier:` + fmt.Sprintf("%v", this.Identifier) + `,`, - `AsyncCalls:` + repeatedStringForAsyncCalls + `,`, - `}`, - }, "") - return s -} -func valueToStringAsyncCall(v interface{}) string { - rv := reflect.ValueOf(v) - if rv.IsNil() { - return "nil" - } - pv := reflect.Indirect(rv).Interface() - return fmt.Sprintf("*%v", pv) -} func (m *SerializableAsyncCall) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -1107,16 +955,53 @@ func (m *SerializableAsyncCall) Unmarshal(dAtA []byte) error { m.CallbackClosure = []byte{} } iNdEx = postIndex + case 13: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IsAsyncV3", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAsyncCall + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.IsAsyncV3 = bool(v != 0) + case 14: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IsCallbackPending", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAsyncCall + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.IsCallbackPending = bool(v != 0) default: iNdEx = preIndex skippy, err := skipAsyncCall(dAtA[iNdEx:]) if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAsyncCall - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAsyncCall } if (iNdEx + skippy) > l { @@ -1317,10 +1202,7 @@ func (m *SerializableAsyncCallGroup) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAsyncCall - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAsyncCall } if (iNdEx + skippy) > l { diff --git a/vmhost/asyncCall.proto b/vmhost/asyncCall.proto index f898bec26..a3b1ab908 100644 --- a/vmhost/asyncCall.proto +++ b/vmhost/asyncCall.proto @@ -32,6 +32,8 @@ message SerializableAsyncCall { string SuccessCallback = 10; string ErrorCallback = 11; bytes CallbackClosure = 12; + bool IsAsyncV3 = 13; + bool IsCallbackPending = 14; } message SerializableAsyncCallGroup { diff --git a/vmhost/contexts/asyncLocal.go b/vmhost/contexts/asyncLocal.go index 491577378..2c6918328 100644 --- a/vmhost/contexts/asyncLocal.go +++ b/vmhost/contexts/asyncLocal.go @@ -16,12 +16,24 @@ type lastTransferInfo struct { func (context *asyncContext) executeAsyncLocalCalls() error { localCalls := make([]*vmhost.AsyncCall, 0) + hasAnyRemoteCallbacks := false for _, group := range context.asyncCallGroups { for _, call := range group.AsyncCalls { if call.IsLocal() { localCalls = append(localCalls, call) } + + if call.IsRemote() && call.HasCallback() { + hasAnyRemoteCallbacks = true + } + } + } + + if hasAnyRemoteCallbacks { + currentCall := context.GetAsyncCallByCallID(context.GetCallID()).GetAsyncCall() + if currentCall != nil && currentCall.IsAsyncV3 { + currentCall.MarkSkippedCallback() } } @@ -78,29 +90,70 @@ func (context *asyncContext) executeAsyncLocalCall(asyncCall *vmhost.AsyncCall) asyncCall.UpdateStatus(vmOutput.ReturnCode) if isComplete { - callbackGasRemaining := uint64(0) - if asyncCall.HasCallback() { - // Restore gas locked while still on the caller instance; otherwise, the - // locked gas will appear to have been used twice by the caller instance. - isCallbackComplete, callbackVMOutput := context.ExecuteLocalCallbackAndFinishOutput(asyncCall, vmOutput, destinationCallInput, 0, err) - if callbackVMOutput == nil { - return vmhost.ErrAsyncNoOutputFromCallback - } + return context.executeAsyncCallbackAndComplete(asyncCall, vmOutput, destinationCallInput, err) + } - context.host.CompleteLogEntriesWithCallType(callbackVMOutput, vmhost.AsyncCallbackString) + return nil +} - if isCallbackComplete { - callbackGasRemaining = callbackVMOutput.GasRemaining - callbackVMOutput.GasRemaining = 0 +func (context *asyncContext) executePendingLocalAsyncCallbacks() error { + localCallsWithPendingCallbacks := make([]*vmhost.AsyncCall, 0) + for _, group := range context.asyncCallGroups { + for _, call := range group.AsyncCalls { + if call.IsLocal() && call.IsCallbackPending { + localCallsWithPendingCallbacks = append(localCallsWithPendingCallbacks, call) } } + } + + for _, call := range localCallsWithPendingCallbacks { + err := context.executePendingLocalAsyncCallback(call) + if err != nil { + return err + } + } - return context.completeChild(asyncCall.CallID, callbackGasRemaining) + return nil +} + +func (context *asyncContext) executePendingLocalAsyncCallback(asyncCall *vmhost.AsyncCall) error { + output := context.host.Output() + + destinationCallInput, err := context.createContractCallInput(asyncCall) + if err != nil { + logAsync.Trace("executePendingLocalAsyncCallback failed", "error", err) + return err } return nil } +func (context *asyncContext) executeAsyncCallbackAndComplete( + asyncCall *vmhost.AsyncCall, + destinationVMOutput *vmcommon.VMOutput, + destinationCallInput *vmcommon.ContractCallInput, + destinationErr error, +) error { + callbackGasRemaining := uint64(0) + if asyncCall.HasCallback() { + // Restore gas locked while still on the caller instance; otherwise, the + // locked gas will appear to have been used twice by the caller instance. + isCallbackComplete, callbackVMOutput := context.ExecuteLocalCallbackAndFinishOutput(asyncCall, destinationVMOutput, destinationCallInput, 0, destinationErr) + if callbackVMOutput == nil { + return vmhost.ErrAsyncNoOutputFromCallback + } + + context.host.CompleteLogEntriesWithCallType(callbackVMOutput, vmhost.AsyncCallbackString) + + if isCallbackComplete { + callbackGasRemaining = callbackVMOutput.GasRemaining + callbackVMOutput.GasRemaining = 0 + } + } + + return context.completeChild(asyncCall.CallID, callbackGasRemaining) +} + // ExecuteLocalCallbackAndFinishOutput executes the callback and finishes the output func (context *asyncContext) ExecuteLocalCallbackAndFinishOutput( asyncCall *vmhost.AsyncCall, diff --git a/vmhost/hostCore/execution.go b/vmhost/hostCore/execution.go index 0b87a401c..3c06cdcaf 100644 --- a/vmhost/hostCore/execution.go +++ b/vmhost/hostCore/execution.go @@ -1238,6 +1238,10 @@ func (host *vmHost) callSCMethodAsynchronousCallBack() error { return nil } + if asyncCall.IsCallbackPending { + return nil + } + async.SetCallbackParentCall(asyncCall) if asyncCall.HasCallback() { diff --git a/vmhost/vmhooks/baseOps.go b/vmhost/vmhooks/baseOps.go index 935f19185..b9b34f93e 100644 --- a/vmhost/vmhooks/baseOps.go +++ b/vmhost/vmhooks/baseOps.go @@ -1209,6 +1209,132 @@ func CreateAsyncCallWithTypedArgs(host vmhost.VMHost, return 0 } +// CreateAsyncV3Call VMHooks implementation. +// @autogenerate(VMHooks) +func (context *VMHooksImpl) CreateAsyncV3Call( + destOffset executor.MemPtr, + valueOffset executor.MemPtr, + dataOffset executor.MemPtr, + dataLength executor.MemLength, + successOffset executor.MemPtr, + successLength executor.MemLength, + errorOffset executor.MemPtr, + errorLength executor.MemLength, + gas int64, + extraGasForCallback int64, +) int32 { + host := context.GetVMHost() + return context.CreateAsyncV3CallWithHost( + host, + destOffset, + valueOffset, + dataOffset, + dataLength, + successOffset, + successLength, + errorOffset, + errorLength, + gas, + extraGasForCallback) +} + +// CreateAsyncV3CallWithHost - createAsyncV3Call with host instead of pointer +func (context *VMHooksImpl) CreateAsyncV3CallWithHost(host vmhost.VMHost, + destOffset executor.MemPtr, + valueOffset executor.MemPtr, + dataOffset executor.MemPtr, + dataLength executor.MemLength, + successOffset executor.MemPtr, + successLength executor.MemLength, + errorOffset executor.MemPtr, + errorLength executor.MemLength, + gas int64, + extraGasForCallback int64, +) int32 { + runtime := host.Runtime() + + calledSCAddress, err := context.MemLoad(destOffset, vmhost.AddressLen) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } + + value, err := context.MemLoad(valueOffset, vmhost.BalanceLen) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } + + data, err := context.MemLoad(dataOffset, dataLength) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } + + successFunc, err := context.MemLoad(successOffset, successLength) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } + + errorFunc, err := context.MemLoad(errorOffset, errorLength) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } + + return CreateAsyncCallV3WithTypedArgs(host, + calledSCAddress, + value, + data, + successFunc, + errorFunc, + gas, + extraGasForCallback, + nil) +} + +// CreateAsyncCallV3WithTypedArgs - createAsyncV3Call with arguments already read from memory +func CreateAsyncCallV3WithTypedArgs(host vmhost.VMHost, + calledSCAddress []byte, + value []byte, + data []byte, + successFunc []byte, + errorFunc []byte, + gas int64, + extraGasForCallback int64, + callbackClosure []byte) int32 { + + metering := host.Metering() + runtime := host.Runtime() + async := host.Async() + + metering.StartGasTracing(createAsyncCallName) + + gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateAsyncCall + metering.UseAndTraceGas(gasToUse) + + asyncCall := &vmhost.AsyncCall{ + Status: vmhost.AsyncCallPending, + Destination: calledSCAddress, + Data: data, + ValueBytes: value, + GasLimit: uint64(gas), + SuccessCallback: string(successFunc), + ErrorCallback: string(errorFunc), + GasLocked: uint64(extraGasForCallback), + CallbackClosure: callbackClosure, + IsAsyncV3: true, + } + + if asyncCall.HasDefinedAnyCallback() { + gasToUse := metering.GasSchedule().BaseOpsAPICost.SetAsyncCallback + metering.UseAndTraceGas(gasToUse) + } + + err := async.RegisterAsyncCall("", asyncCall) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } + + return 0 +} + // SetAsyncContextCallback VMHooks implementation. // @autogenerate(VMHooks) func (context *VMHooksImpl) SetAsyncContextCallback( diff --git a/wasmer/wasmerImportsCgo.go b/wasmer/wasmerImportsCgo.go index da92dbb44..4073a0f0a 100644 --- a/wasmer/wasmerImportsCgo.go +++ b/wasmer/wasmerImportsCgo.go @@ -32,6 +32,7 @@ package wasmer // extern int32_t v1_5_transferESDTNFTExecute(void* context, int32_t destOffset, int32_t tokenIDOffset, int32_t tokenIDLen, int32_t valueOffset, long long nonce, long long gasLimit, int32_t functionOffset, int32_t functionLength, int32_t numArguments, int32_t argumentsLengthOffset, int32_t dataOffset); // extern int32_t v1_5_multiTransferESDTNFTExecute(void* context, int32_t destOffset, int32_t numTokenTransfers, int32_t tokenTransfersArgsLengthOffset, int32_t tokenTransferDataOffset, long long gasLimit, int32_t functionOffset, int32_t functionLength, int32_t numArguments, int32_t argumentsLengthOffset, int32_t dataOffset); // extern int32_t v1_5_createAsyncCall(void* context, int32_t destOffset, int32_t valueOffset, int32_t dataOffset, int32_t dataLength, int32_t successOffset, int32_t successLength, int32_t errorOffset, int32_t errorLength, long long gas, long long extraGasForCallback); +// extern int32_t v1_5_createAsyncV3Call(void* context, int32_t destOffset, int32_t valueOffset, int32_t dataOffset, int32_t dataLength, int32_t successOffset, int32_t successLength, int32_t errorOffset, int32_t errorLength, long long gas, long long extraGasForCallback); // extern int32_t v1_5_setAsyncContextCallback(void* context, int32_t callback, int32_t callbackLength, int32_t data, int32_t dataLength, long long gas); // extern void v1_5_upgradeContract(void* context, int32_t destOffset, long long gasLimit, int32_t valueOffset, int32_t codeOffset, int32_t codeMetadataOffset, int32_t length, int32_t numArguments, int32_t argumentsLengthOffset, int32_t dataOffset); // extern void v1_5_upgradeFromSourceContract(void* context, int32_t destOffset, long long gasLimit, int32_t valueOffset, int32_t sourceContractAddressOffset, int32_t codeMetadataOffset, int32_t numArguments, int32_t argumentsLengthOffset, int32_t dataOffset); @@ -102,7 +103,7 @@ package wasmer // extern void v1_5_managedGetPrevBlockRandomSeed(void* context, int32_t resultHandle); // extern void v1_5_managedGetReturnData(void* context, int32_t resultID, int32_t resultHandle); // extern void v1_5_managedGetMultiESDTCallValue(void* context, int32_t multiCallValueHandle); -// extern void v1_5_managedGetBackTransfers(void* context, int32_t esdtTransfersValueHandle, int32_t callValueHandle); +// extern void v1_5_managedGetBackTransfers(void* context, int32_t esdtTransfersValueHandle, int32_t egldValueHandle); // extern void v1_5_managedGetESDTBalance(void* context, int32_t addressHandle, int32_t tokenIDHandle, long long nonce, int32_t valueHandle); // extern void v1_5_managedGetESDTTokenData(void* context, int32_t addressHandle, int32_t tokenIDHandle, long long nonce, int32_t valueHandle, int32_t propertiesHandle, int32_t hashHandle, int32_t nameHandle, int32_t attributesHandle, int32_t creatorHandle, int32_t royaltiesHandle, int32_t urisHandle); // extern void v1_5_managedAsyncCall(void* context, int32_t destHandle, int32_t valueHandle, int32_t functionHandle, int32_t argumentsHandle); @@ -382,6 +383,11 @@ func populateWasmerImports(imports *wasmerImports) error { return err } + err = imports.append("createAsyncV3Call", v1_5_createAsyncV3Call, C.v1_5_createAsyncV3Call) + if err != nil { + return err + } + err = imports.append("setAsyncContextCallback", v1_5_setAsyncContextCallback, C.v1_5_setAsyncContextCallback) if err != nil { return err @@ -1681,6 +1687,12 @@ func v1_5_createAsyncCall(context unsafe.Pointer, destOffset int32, valueOffset return vmHooks.CreateAsyncCall(executor.MemPtr(destOffset), executor.MemPtr(valueOffset), executor.MemPtr(dataOffset), dataLength, executor.MemPtr(successOffset), successLength, executor.MemPtr(errorOffset), errorLength, gas, extraGasForCallback) } +//export v1_5_createAsyncV3Call +func v1_5_createAsyncV3Call(context unsafe.Pointer, destOffset int32, valueOffset int32, dataOffset int32, dataLength int32, successOffset int32, successLength int32, errorOffset int32, errorLength int32, gas int64, extraGasForCallback int64) int32 { + vmHooks := getVMHooksFromContextRawPtr(context) + return vmHooks.CreateAsyncV3Call(executor.MemPtr(destOffset), executor.MemPtr(valueOffset), executor.MemPtr(dataOffset), dataLength, executor.MemPtr(successOffset), successLength, executor.MemPtr(errorOffset), errorLength, gas, extraGasForCallback) +} + //export v1_5_setAsyncContextCallback func v1_5_setAsyncContextCallback(context unsafe.Pointer, callback int32, callbackLength int32, data int32, dataLength int32, gas int64) int32 { vmHooks := getVMHooksFromContextRawPtr(context) @@ -2102,9 +2114,9 @@ func v1_5_managedGetMultiESDTCallValue(context unsafe.Pointer, multiCallValueHan } //export v1_5_managedGetBackTransfers -func v1_5_managedGetBackTransfers(context unsafe.Pointer, esdtTransfersValueHandle int32, callValueHandle int32) { +func v1_5_managedGetBackTransfers(context unsafe.Pointer, esdtTransfersValueHandle int32, egldValueHandle int32) { vmHooks := getVMHooksFromContextRawPtr(context) - vmHooks.ManagedGetBackTransfers(esdtTransfersValueHandle, callValueHandle) + vmHooks.ManagedGetBackTransfers(esdtTransfersValueHandle, egldValueHandle) } //export v1_5_managedGetESDTBalance diff --git a/wasmer2/wasmer2ImportsCgo.go b/wasmer2/wasmer2ImportsCgo.go index b24feb6ef..1df9731f9 100644 --- a/wasmer2/wasmer2ImportsCgo.go +++ b/wasmer2/wasmer2ImportsCgo.go @@ -32,6 +32,7 @@ package wasmer2 // extern int32_t w2_transferESDTNFTExecute(void* context, int32_t destOffset, int32_t tokenIDOffset, int32_t tokenIDLen, int32_t valueOffset, long long nonce, long long gasLimit, int32_t functionOffset, int32_t functionLength, int32_t numArguments, int32_t argumentsLengthOffset, int32_t dataOffset); // extern int32_t w2_multiTransferESDTNFTExecute(void* context, int32_t destOffset, int32_t numTokenTransfers, int32_t tokenTransfersArgsLengthOffset, int32_t tokenTransferDataOffset, long long gasLimit, int32_t functionOffset, int32_t functionLength, int32_t numArguments, int32_t argumentsLengthOffset, int32_t dataOffset); // extern int32_t w2_createAsyncCall(void* context, int32_t destOffset, int32_t valueOffset, int32_t dataOffset, int32_t dataLength, int32_t successOffset, int32_t successLength, int32_t errorOffset, int32_t errorLength, long long gas, long long extraGasForCallback); +// extern int32_t w2_createAsyncV3Call(void* context, int32_t destOffset, int32_t valueOffset, int32_t dataOffset, int32_t dataLength, int32_t successOffset, int32_t successLength, int32_t errorOffset, int32_t errorLength, long long gas, long long extraGasForCallback); // extern int32_t w2_setAsyncContextCallback(void* context, int32_t callback, int32_t callbackLength, int32_t data, int32_t dataLength, long long gas); // extern void w2_upgradeContract(void* context, int32_t destOffset, long long gasLimit, int32_t valueOffset, int32_t codeOffset, int32_t codeMetadataOffset, int32_t length, int32_t numArguments, int32_t argumentsLengthOffset, int32_t dataOffset); // extern void w2_upgradeFromSourceContract(void* context, int32_t destOffset, long long gasLimit, int32_t valueOffset, int32_t sourceContractAddressOffset, int32_t codeMetadataOffset, int32_t numArguments, int32_t argumentsLengthOffset, int32_t dataOffset); @@ -102,7 +103,7 @@ package wasmer2 // extern void w2_managedGetPrevBlockRandomSeed(void* context, int32_t resultHandle); // extern void w2_managedGetReturnData(void* context, int32_t resultID, int32_t resultHandle); // extern void w2_managedGetMultiESDTCallValue(void* context, int32_t multiCallValueHandle); -// extern void w2_managedGetBackTransfers(void* context, int32_t esdtTransfersValueHandle, int32_t callValueHandle); +// extern void w2_managedGetBackTransfers(void* context, int32_t esdtTransfersValueHandle, int32_t egldValueHandle); // extern void w2_managedGetESDTBalance(void* context, int32_t addressHandle, int32_t tokenIDHandle, long long nonce, int32_t valueHandle); // extern void w2_managedGetESDTTokenData(void* context, int32_t addressHandle, int32_t tokenIDHandle, long long nonce, int32_t valueHandle, int32_t propertiesHandle, int32_t hashHandle, int32_t nameHandle, int32_t attributesHandle, int32_t creatorHandle, int32_t royaltiesHandle, int32_t urisHandle); // extern void w2_managedAsyncCall(void* context, int32_t destHandle, int32_t valueHandle, int32_t functionHandle, int32_t argumentsHandle); @@ -298,6 +299,7 @@ func populateCgoFunctionPointers() *cWasmerVmHookPointers { transfer_esdt_nft_execute_func_ptr: funcPointer(C.w2_transferESDTNFTExecute), multi_transfer_esdt_nft_execute_func_ptr: funcPointer(C.w2_multiTransferESDTNFTExecute), create_async_call_func_ptr: funcPointer(C.w2_createAsyncCall), + create_async_v3_call_func_ptr: funcPointer(C.w2_createAsyncV3Call), set_async_context_callback_func_ptr: funcPointer(C.w2_setAsyncContextCallback), upgrade_contract_func_ptr: funcPointer(C.w2_upgradeContract), upgrade_from_source_contract_func_ptr: funcPointer(C.w2_upgradeFromSourceContract), @@ -661,6 +663,12 @@ func w2_createAsyncCall(context unsafe.Pointer, destOffset int32, valueOffset in return vmHooks.CreateAsyncCall(executor.MemPtr(destOffset), executor.MemPtr(valueOffset), executor.MemPtr(dataOffset), dataLength, executor.MemPtr(successOffset), successLength, executor.MemPtr(errorOffset), errorLength, gas, extraGasForCallback) } +//export w2_createAsyncV3Call +func w2_createAsyncV3Call(context unsafe.Pointer, destOffset int32, valueOffset int32, dataOffset int32, dataLength int32, successOffset int32, successLength int32, errorOffset int32, errorLength int32, gas int64, extraGasForCallback int64) int32 { + vmHooks := getVMHooksFromContextRawPtr(context) + return vmHooks.CreateAsyncV3Call(executor.MemPtr(destOffset), executor.MemPtr(valueOffset), executor.MemPtr(dataOffset), dataLength, executor.MemPtr(successOffset), successLength, executor.MemPtr(errorOffset), errorLength, gas, extraGasForCallback) +} + //export w2_setAsyncContextCallback func w2_setAsyncContextCallback(context unsafe.Pointer, callback int32, callbackLength int32, data int32, dataLength int32, gas int64) int32 { vmHooks := getVMHooksFromContextRawPtr(context) @@ -1082,9 +1090,9 @@ func w2_managedGetMultiESDTCallValue(context unsafe.Pointer, multiCallValueHandl } //export w2_managedGetBackTransfers -func w2_managedGetBackTransfers(context unsafe.Pointer, esdtTransfersValueHandle int32, callValueHandle int32) { +func w2_managedGetBackTransfers(context unsafe.Pointer, esdtTransfersValueHandle int32, egldValueHandle int32) { vmHooks := getVMHooksFromContextRawPtr(context) - vmHooks.ManagedGetBackTransfers(esdtTransfersValueHandle, callValueHandle) + vmHooks.ManagedGetBackTransfers(esdtTransfersValueHandle, egldValueHandle) } //export w2_managedGetESDTBalance diff --git a/wasmer2/wasmer2Names.go b/wasmer2/wasmer2Names.go index 7fa7c4d0b..1542da25d 100644 --- a/wasmer2/wasmer2Names.go +++ b/wasmer2/wasmer2Names.go @@ -30,6 +30,7 @@ var functionNames = map[string]struct{}{ "transferESDTNFTExecute": empty, "multiTransferESDTNFTExecute": empty, "createAsyncCall": empty, + "createAsyncV3Call": empty, "setAsyncContextCallback": empty, "upgradeContract": empty, "upgradeFromSourceContract": empty, From db0b7d8a90f0dfd5605bcf7b50550d5f14e81dd6 Mon Sep 17 00:00:00 2001 From: Laurentiu Ciobanu Date: Mon, 20 May 2024 14:49:42 +0000 Subject: [PATCH 13/14] store gas locked for pending callbacks --- Makefile | 3 + vmhost/asyncCall.go | 18 +- vmhost/asyncCall.pb.go | 406 +++++++++++++++++++++++++++------- vmhost/asyncCall.proto | 3 +- vmhost/contexts/asyncLocal.go | 34 +-- vmhost/hostCore/execution.go | 2 +- 6 files changed, 345 insertions(+), 121 deletions(-) diff --git a/Makefile b/Makefile index 39537590f..f944ffa2e 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,9 @@ clean: build: go build ./... +gen-async: + protoc -I=./vmhost -I=${GOPATH}/src -I=${GOPATH}/src/github.com/multiversx/protobuf/protobuf -I=${GOPATH}/src/github.com/gogo/protobuf --gogoslick_out=./vmhost ./vmhost/asyncCall.proto + vmserver: ifndef VMSERVER_PATH $(error VMSERVER_PATH is undefined) diff --git a/vmhost/asyncCall.go b/vmhost/asyncCall.go index 36d56240e..3cc9b4448 100644 --- a/vmhost/asyncCall.go +++ b/vmhost/asyncCall.go @@ -24,7 +24,9 @@ type AsyncCall struct { IsBuiltinFunctionCall bool IsAsyncV3 bool - IsCallbackPending bool + + HasPendingCallback bool + PendingCallbackGasLocked uint64 } // Clone creates a deep clone of the AsyncCall @@ -41,7 +43,8 @@ func (ac *AsyncCall) Clone() *AsyncCall { SuccessCallback: ac.SuccessCallback, ErrorCallback: ac.ErrorCallback, IsAsyncV3: ac.IsAsyncV3, - IsCallbackPending: ac.IsCallbackPending, + HasPendingCallback: ac.HasPendingCallback, + PendingCallbackGasLocked: ac.PendingCallbackGasLocked, } copy(clone.Destination, ac.Destination) @@ -110,8 +113,9 @@ func (ac *AsyncCall) HasDefinedAnyCallback() bool { } // MarkSkippedCallback this async call has skipped calling its callback -func (ac *AsyncCall) MarkSkippedCallback() { - ac.IsCallbackPending = true +func (ac *AsyncCall) MarkSkippedCallback(pendingGasLock uint64) { + ac.HasPendingCallback = true + ac.PendingCallbackGasLocked = pendingGasLock } // UpdateStatus sets the status of the async call depending on the provided ReturnCode @@ -156,7 +160,8 @@ func (ac *AsyncCall) toSerializable() *SerializableAsyncCall { ErrorCallback: ac.ErrorCallback, CallbackClosure: ac.CallbackClosure, IsAsyncV3: ac.IsAsyncV3, - IsCallbackPending: ac.IsCallbackPending, + HasPendingCallback: ac.HasPendingCallback, + PendingCallbackGasLocked: ac.PendingCallbackGasLocked, } } @@ -182,6 +187,7 @@ func (serAsyncCall *SerializableAsyncCall) fromSerializable() *AsyncCall { ErrorCallback: serAsyncCall.ErrorCallback, CallbackClosure: serAsyncCall.CallbackClosure, IsAsyncV3: serAsyncCall.IsAsyncV3, - IsCallbackPending: serAsyncCall.IsCallbackPending, + HasPendingCallback: serAsyncCall.HasPendingCallback, + PendingCallbackGasLocked: serAsyncCall.PendingCallbackGasLocked, } } diff --git a/vmhost/asyncCall.pb.go b/vmhost/asyncCall.pb.go index 3fbecdf6f..8aa8d0afc 100644 --- a/vmhost/asyncCall.pb.go +++ b/vmhost/asyncCall.pb.go @@ -4,12 +4,16 @@ package vmhost import ( + bytes "bytes" fmt "fmt" _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" io "io" math "math" math_bits "math/bits" + reflect "reflect" + strconv "strconv" + strings "strings" ) // Reference imports to suppress errors if they are not otherwise used. @@ -26,9 +30,9 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type SerializableAsyncCallStatus int32 const ( - SerializableAsyncCallStatus_SerializableAsyncCallPending SerializableAsyncCallStatus = 0 - SerializableAsyncCallStatus_SerializableAsyncCallResolved SerializableAsyncCallStatus = 1 - SerializableAsyncCallStatus_SerializableAsyncCallRejected SerializableAsyncCallStatus = 2 + SerializableAsyncCallPending SerializableAsyncCallStatus = 0 + SerializableAsyncCallResolved SerializableAsyncCallStatus = 1 + SerializableAsyncCallRejected SerializableAsyncCallStatus = 2 ) var SerializableAsyncCallStatus_name = map[int32]string{ @@ -43,10 +47,6 @@ var SerializableAsyncCallStatus_value = map[string]int32{ "SerializableAsyncCallRejected": 2, } -func (x SerializableAsyncCallStatus) String() string { - return proto.EnumName(SerializableAsyncCallStatus_name, int32(x)) -} - func (SerializableAsyncCallStatus) EnumDescriptor() ([]byte, []int) { return fileDescriptor_a0e9b586d6e1f667, []int{0} } @@ -54,10 +54,10 @@ func (SerializableAsyncCallStatus) EnumDescriptor() ([]byte, []int) { type SerializableAsyncCallExecutionMode int32 const ( - SerializableAsyncCallExecutionMode_SerializableSyncExecution SerializableAsyncCallExecutionMode = 0 - SerializableAsyncCallExecutionMode_SerializableAsyncBuiltinFuncIntraShard SerializableAsyncCallExecutionMode = 1 - SerializableAsyncCallExecutionMode_SerializableAsyncBuiltinFuncCrossShard SerializableAsyncCallExecutionMode = 2 - SerializableAsyncCallExecutionMode_SerializableAsyncUnknown SerializableAsyncCallExecutionMode = 3 + SerializableSyncExecution SerializableAsyncCallExecutionMode = 0 + SerializableAsyncBuiltinFuncIntraShard SerializableAsyncCallExecutionMode = 1 + SerializableAsyncBuiltinFuncCrossShard SerializableAsyncCallExecutionMode = 2 + SerializableAsyncUnknown SerializableAsyncCallExecutionMode = 3 ) var SerializableAsyncCallExecutionMode_name = map[int32]string{ @@ -74,33 +74,29 @@ var SerializableAsyncCallExecutionMode_value = map[string]int32{ "SerializableAsyncUnknown": 3, } -func (x SerializableAsyncCallExecutionMode) String() string { - return proto.EnumName(SerializableAsyncCallExecutionMode_name, int32(x)) -} - func (SerializableAsyncCallExecutionMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor_a0e9b586d6e1f667, []int{1} } type SerializableAsyncCall struct { - CallID []byte `protobuf:"bytes,1,opt,name=CallID,proto3" json:"CallID,omitempty"` - Status SerializableAsyncCallStatus `protobuf:"varint,2,opt,name=Status,proto3,enum=vmhost.SerializableAsyncCallStatus" json:"Status,omitempty"` - ExecutionMode SerializableAsyncCallExecutionMode `protobuf:"varint,3,opt,name=ExecutionMode,proto3,enum=vmhost.SerializableAsyncCallExecutionMode" json:"ExecutionMode,omitempty"` - Destination []byte `protobuf:"bytes,5,opt,name=Destination,proto3" json:"Destination,omitempty"` - Data []byte `protobuf:"bytes,6,opt,name=Data,proto3" json:"Data,omitempty"` - GasLimit uint64 `protobuf:"varint,7,opt,name=GasLimit,proto3" json:"GasLimit,omitempty"` - GasLocked uint64 `protobuf:"varint,8,opt,name=GasLocked,proto3" json:"GasLocked,omitempty"` - ValueBytes []byte `protobuf:"bytes,9,opt,name=ValueBytes,proto3" json:"ValueBytes,omitempty"` - SuccessCallback string `protobuf:"bytes,10,opt,name=SuccessCallback,proto3" json:"SuccessCallback,omitempty"` - ErrorCallback string `protobuf:"bytes,11,opt,name=ErrorCallback,proto3" json:"ErrorCallback,omitempty"` - CallbackClosure []byte `protobuf:"bytes,12,opt,name=CallbackClosure,proto3" json:"CallbackClosure,omitempty"` - IsAsyncV3 bool `protobuf:"varint,13,opt,name=IsAsyncV3,proto3" json:"IsAsyncV3,omitempty"` - IsCallbackPending bool `protobuf:"varint,14,opt,name=IsCallbackPending,proto3" json:"IsCallbackPending,omitempty"` + CallID []byte `protobuf:"bytes,1,opt,name=CallID,proto3" json:"CallID,omitempty"` + Status SerializableAsyncCallStatus `protobuf:"varint,2,opt,name=Status,proto3,enum=vmhost.SerializableAsyncCallStatus" json:"Status,omitempty"` + ExecutionMode SerializableAsyncCallExecutionMode `protobuf:"varint,3,opt,name=ExecutionMode,proto3,enum=vmhost.SerializableAsyncCallExecutionMode" json:"ExecutionMode,omitempty"` + Destination []byte `protobuf:"bytes,5,opt,name=Destination,proto3" json:"Destination,omitempty"` + Data []byte `protobuf:"bytes,6,opt,name=Data,proto3" json:"Data,omitempty"` + GasLimit uint64 `protobuf:"varint,7,opt,name=GasLimit,proto3" json:"GasLimit,omitempty"` + GasLocked uint64 `protobuf:"varint,8,opt,name=GasLocked,proto3" json:"GasLocked,omitempty"` + ValueBytes []byte `protobuf:"bytes,9,opt,name=ValueBytes,proto3" json:"ValueBytes,omitempty"` + SuccessCallback string `protobuf:"bytes,10,opt,name=SuccessCallback,proto3" json:"SuccessCallback,omitempty"` + ErrorCallback string `protobuf:"bytes,11,opt,name=ErrorCallback,proto3" json:"ErrorCallback,omitempty"` + CallbackClosure []byte `protobuf:"bytes,12,opt,name=CallbackClosure,proto3" json:"CallbackClosure,omitempty"` + IsAsyncV3 bool `protobuf:"varint,13,opt,name=IsAsyncV3,proto3" json:"IsAsyncV3,omitempty"` + HasPendingCallback bool `protobuf:"varint,14,opt,name=HasPendingCallback,proto3" json:"HasPendingCallback,omitempty"` + PendingCallbackGasLocked uint64 `protobuf:"varint,15,opt,name=PendingCallbackGasLocked,proto3" json:"PendingCallbackGasLocked,omitempty"` } -func (m *SerializableAsyncCall) Reset() { *m = SerializableAsyncCall{} } -func (m *SerializableAsyncCall) String() string { return proto.CompactTextString(m) } -func (*SerializableAsyncCall) ProtoMessage() {} +func (m *SerializableAsyncCall) Reset() { *m = SerializableAsyncCall{} } +func (*SerializableAsyncCall) ProtoMessage() {} func (*SerializableAsyncCall) Descriptor() ([]byte, []int) { return fileDescriptor_a0e9b586d6e1f667, []int{0} } @@ -138,14 +134,14 @@ func (m *SerializableAsyncCall) GetStatus() SerializableAsyncCallStatus { if m != nil { return m.Status } - return SerializableAsyncCallStatus_SerializableAsyncCallPending + return SerializableAsyncCallPending } func (m *SerializableAsyncCall) GetExecutionMode() SerializableAsyncCallExecutionMode { if m != nil { return m.ExecutionMode } - return SerializableAsyncCallExecutionMode_SerializableSyncExecution + return SerializableSyncExecution } func (m *SerializableAsyncCall) GetDestination() []byte { @@ -211,13 +207,20 @@ func (m *SerializableAsyncCall) GetIsAsyncV3() bool { return false } -func (m *SerializableAsyncCall) GetIsCallbackPending() bool { +func (m *SerializableAsyncCall) GetHasPendingCallback() bool { if m != nil { - return m.IsCallbackPending + return m.HasPendingCallback } return false } +func (m *SerializableAsyncCall) GetPendingCallbackGasLocked() uint64 { + if m != nil { + return m.PendingCallbackGasLocked + } + return 0 +} + type SerializableAsyncCallGroup struct { Callback string `protobuf:"bytes,1,opt,name=Callback,proto3" json:"Callback,omitempty"` GasLocked uint64 `protobuf:"varint,2,opt,name=GasLocked,proto3" json:"GasLocked,omitempty"` @@ -226,9 +229,8 @@ type SerializableAsyncCallGroup struct { AsyncCalls []*SerializableAsyncCall `protobuf:"bytes,5,rep,name=AsyncCalls,proto3" json:"AsyncCalls,omitempty"` } -func (m *SerializableAsyncCallGroup) Reset() { *m = SerializableAsyncCallGroup{} } -func (m *SerializableAsyncCallGroup) String() string { return proto.CompactTextString(m) } -func (*SerializableAsyncCallGroup) ProtoMessage() {} +func (m *SerializableAsyncCallGroup) Reset() { *m = SerializableAsyncCallGroup{} } +func (*SerializableAsyncCallGroup) ProtoMessage() {} func (*SerializableAsyncCallGroup) Descriptor() ([]byte, []int) { return fileDescriptor_a0e9b586d6e1f667, []int{1} } @@ -300,45 +302,212 @@ func init() { func init() { proto.RegisterFile("asyncCall.proto", fileDescriptor_a0e9b586d6e1f667) } var fileDescriptor_a0e9b586d6e1f667 = []byte{ - // 565 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x54, 0x4f, 0x6f, 0x1a, 0x3f, - 0x10, 0xc5, 0x40, 0xf8, 0x25, 0x13, 0x48, 0xf8, 0x59, 0x6a, 0xe5, 0x52, 0x58, 0x6d, 0x69, 0x54, - 0xad, 0x50, 0x4b, 0xa4, 0xe4, 0x58, 0xf5, 0x50, 0x20, 0x8d, 0x90, 0x5a, 0x29, 0x5a, 0xd4, 0x1c, - 0x7a, 0x33, 0xbb, 0x0e, 0xb8, 0x2c, 0x76, 0xb4, 0xf6, 0xa6, 0xa5, 0xf7, 0xde, 0x7b, 0xe8, 0x97, - 0xe9, 0x37, 0xe8, 0x31, 0xc7, 0xf4, 0x56, 0xc1, 0x17, 0xa9, 0xd6, 0xc0, 0x86, 0x7f, 0x22, 0xa7, - 0x9d, 0x79, 0xf3, 0xe6, 0xcd, 0xdb, 0xb1, 0x65, 0x38, 0xa4, 0x6a, 0x24, 0xbc, 0x26, 0x0d, 0x82, - 0xfa, 0x75, 0x28, 0xb5, 0xc4, 0xb9, 0x9b, 0x61, 0x5f, 0x2a, 0x5d, 0x7a, 0xd5, 0xe3, 0xba, 0x1f, - 0x75, 0xeb, 0x9e, 0x1c, 0x1e, 0xf7, 0x64, 0x4f, 0x1e, 0x9b, 0x72, 0x37, 0xba, 0x32, 0x99, 0x49, - 0x4c, 0x34, 0x6d, 0xab, 0xfe, 0xcc, 0xc2, 0xa3, 0x0e, 0x0b, 0x39, 0x0d, 0xf8, 0x37, 0xda, 0x0d, - 0xd8, 0xdb, 0xb9, 0x2c, 0x7e, 0x0c, 0xb9, 0xf8, 0xdb, 0x6e, 0x11, 0x64, 0x23, 0x27, 0xef, 0xce, - 0x32, 0xfc, 0x1a, 0x72, 0x1d, 0x4d, 0x75, 0xa4, 0x48, 0xda, 0x46, 0xce, 0xc1, 0xc9, 0xf3, 0xfa, - 0x74, 0x72, 0x7d, 0xa3, 0xcc, 0x94, 0xea, 0xce, 0x5a, 0xf0, 0x05, 0x14, 0xce, 0xbe, 0x32, 0x2f, - 0xd2, 0x5c, 0x8a, 0x0f, 0xd2, 0x67, 0x24, 0x63, 0x34, 0x6a, 0x5b, 0x35, 0x96, 0x3a, 0xdc, 0x65, - 0x01, 0x6c, 0xc3, 0x7e, 0x8b, 0x29, 0xcd, 0x05, 0x8d, 0x21, 0xb2, 0x63, 0xbc, 0x2e, 0x42, 0x18, - 0x43, 0xb6, 0x45, 0x35, 0x25, 0x39, 0x53, 0x32, 0x31, 0x2e, 0xc1, 0xee, 0x39, 0x55, 0xef, 0xf9, - 0x90, 0x6b, 0xf2, 0x9f, 0x8d, 0x9c, 0xac, 0x9b, 0xe4, 0xb8, 0x0c, 0x7b, 0x71, 0x2c, 0xbd, 0x01, - 0xf3, 0xc9, 0xae, 0x29, 0xde, 0x03, 0xd8, 0x02, 0xb8, 0xa4, 0x41, 0xc4, 0x1a, 0x23, 0xcd, 0x14, - 0xd9, 0x33, 0x9a, 0x0b, 0x08, 0x76, 0xe0, 0xb0, 0x13, 0x79, 0x1e, 0x53, 0x2a, 0xb6, 0xde, 0xa5, - 0xde, 0x80, 0x80, 0x8d, 0x9c, 0x3d, 0x77, 0x15, 0xc6, 0x47, 0x50, 0x38, 0x0b, 0x43, 0x19, 0x26, - 0xbc, 0x7d, 0xc3, 0x5b, 0x06, 0x63, 0xbd, 0x79, 0xdc, 0x0c, 0xa4, 0x8a, 0x42, 0x46, 0xf2, 0x66, - 0xe8, 0x2a, 0x1c, 0xfb, 0x6e, 0x2b, 0xb3, 0xb4, 0xcb, 0x53, 0x52, 0xb0, 0x91, 0xb3, 0xeb, 0xde, - 0x03, 0xf8, 0x25, 0xfc, 0xdf, 0x4e, 0x66, 0x5f, 0x30, 0xe1, 0x73, 0xd1, 0x23, 0x07, 0x86, 0xb5, - 0x5e, 0xa8, 0xfe, 0x41, 0x50, 0xda, 0x78, 0x16, 0xe7, 0xa1, 0x8c, 0xae, 0xe3, 0xf5, 0x25, 0xae, - 0x91, 0x71, 0x9d, 0xe4, 0xcb, 0xeb, 0x4b, 0xaf, 0xae, 0xaf, 0x0a, 0xf9, 0x39, 0xd3, 0x1c, 0x4a, - 0xc6, 0xfc, 0xcb, 0x12, 0x16, 0xaf, 0xb8, 0xed, 0x33, 0xa1, 0xf9, 0x15, 0x67, 0x21, 0xc9, 0x1a, - 0xfd, 0x05, 0x04, 0xbf, 0x01, 0x48, 0xfc, 0x28, 0xb2, 0x63, 0x67, 0x9c, 0xfd, 0x93, 0xca, 0xd6, - 0x1b, 0xe4, 0x2e, 0x34, 0xd4, 0xbe, 0x23, 0x78, 0xba, 0xe5, 0xae, 0x62, 0x1b, 0xca, 0x1b, 0xcb, - 0xb3, 0xdd, 0x14, 0x53, 0xf8, 0x19, 0x54, 0x36, 0x8f, 0x61, 0x4a, 0x06, 0x37, 0xcc, 0x2f, 0xa2, - 0x2d, 0x94, 0xcf, 0xcc, 0xd3, 0xcc, 0x2f, 0xa6, 0x6b, 0xbf, 0x10, 0x54, 0x1f, 0xbe, 0xef, 0xb8, - 0x02, 0x4f, 0x16, 0x59, 0x9d, 0x91, 0xf0, 0x12, 0x42, 0x31, 0x85, 0x6b, 0xf0, 0x62, 0x4d, 0xa4, - 0x11, 0xf1, 0x40, 0x73, 0xf1, 0x2e, 0x12, 0x5e, 0x5b, 0xe8, 0x90, 0x76, 0xfa, 0x34, 0x8c, 0x4d, - 0x3d, 0xc0, 0x6d, 0x86, 0x52, 0xa9, 0x29, 0x37, 0x8d, 0xcb, 0x40, 0xd6, 0xb8, 0x1f, 0xc5, 0x40, - 0xc8, 0x2f, 0xa2, 0x98, 0x69, 0x1c, 0xfd, 0x1e, 0x5b, 0xe8, 0x76, 0x6c, 0xa1, 0xbb, 0xb1, 0x85, - 0xfe, 0x8e, 0x2d, 0xf4, 0x63, 0x62, 0xa5, 0x6e, 0x27, 0x56, 0xea, 0x6e, 0x62, 0xa5, 0x3e, 0xcd, - 0xde, 0xa2, 0x6e, 0xce, 0xbc, 0x31, 0xa7, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x35, 0x55, 0x47, - 0x36, 0xad, 0x04, 0x00, 0x00, + // 608 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x54, 0xcd, 0x6e, 0x13, 0x3d, + 0x14, 0x1d, 0x27, 0x69, 0xbe, 0xf6, 0xf6, 0x2f, 0xb2, 0xf4, 0x21, 0x53, 0x5a, 0x6b, 0x08, 0x08, + 0x8d, 0x22, 0x91, 0x4a, 0xed, 0x0e, 0x84, 0x04, 0xfd, 0xa1, 0x44, 0x02, 0xa9, 0x9a, 0x88, 0x2e, + 0xd8, 0x39, 0x33, 0x6e, 0x6a, 0x3a, 0xb5, 0xab, 0xb1, 0xa7, 0x50, 0x56, 0x6c, 0xd8, 0xf3, 0x18, + 0xbc, 0x02, 0x6f, 0xc0, 0xb2, 0x62, 0x55, 0x76, 0x74, 0xb2, 0x61, 0xd9, 0x47, 0x40, 0xe3, 0x24, + 0x93, 0x9f, 0x86, 0x74, 0x95, 0x7b, 0xcf, 0x3d, 0xf7, 0xdc, 0x9b, 0x63, 0x8f, 0x61, 0x99, 0xe9, + 0x73, 0x19, 0x6c, 0xb3, 0x28, 0xaa, 0x9f, 0xc6, 0xca, 0x28, 0x5c, 0x3e, 0x3b, 0x39, 0x52, 0xda, + 0xac, 0x3c, 0x6e, 0x0b, 0x73, 0x94, 0xb4, 0xea, 0x81, 0x3a, 0x59, 0x6f, 0xab, 0xb6, 0x5a, 0xb7, + 0xe5, 0x56, 0x72, 0x68, 0x33, 0x9b, 0xd8, 0xa8, 0xdb, 0x56, 0xfd, 0x59, 0x82, 0xff, 0x9b, 0x3c, + 0x16, 0x2c, 0x12, 0x9f, 0x58, 0x2b, 0xe2, 0x2f, 0xfa, 0xb2, 0xf8, 0x0e, 0x94, 0xb3, 0xdf, 0xc6, + 0x0e, 0x41, 0x2e, 0xf2, 0x16, 0xfc, 0x5e, 0x86, 0x9f, 0x42, 0xb9, 0x69, 0x98, 0x49, 0x34, 0x29, + 0xb8, 0xc8, 0x5b, 0xda, 0x78, 0x50, 0xef, 0x4e, 0xae, 0x4f, 0x94, 0xe9, 0x52, 0xfd, 0x5e, 0x0b, + 0xde, 0x87, 0xc5, 0xdd, 0x8f, 0x3c, 0x48, 0x8c, 0x50, 0xf2, 0x8d, 0x0a, 0x39, 0x29, 0x5a, 0x8d, + 0xda, 0x54, 0x8d, 0x91, 0x0e, 0x7f, 0x54, 0x00, 0xbb, 0x30, 0xbf, 0xc3, 0xb5, 0x11, 0x92, 0x65, + 0x10, 0x99, 0xb1, 0xbb, 0x0e, 0x43, 0x18, 0x43, 0x69, 0x87, 0x19, 0x46, 0xca, 0xb6, 0x64, 0x63, + 0xbc, 0x02, 0xb3, 0x7b, 0x4c, 0xbf, 0x16, 0x27, 0xc2, 0x90, 0xff, 0x5c, 0xe4, 0x95, 0xfc, 0x3c, + 0xc7, 0xab, 0x30, 0x97, 0xc5, 0x2a, 0x38, 0xe6, 0x21, 0x99, 0xb5, 0xc5, 0x01, 0x80, 0x29, 0xc0, + 0x01, 0x8b, 0x12, 0xbe, 0x75, 0x6e, 0xb8, 0x26, 0x73, 0x56, 0x73, 0x08, 0xc1, 0x1e, 0x2c, 0x37, + 0x93, 0x20, 0xe0, 0x5a, 0x67, 0xab, 0xb7, 0x58, 0x70, 0x4c, 0xc0, 0x45, 0xde, 0x9c, 0x3f, 0x0e, + 0xe3, 0x87, 0xb0, 0xb8, 0x1b, 0xc7, 0x2a, 0xce, 0x79, 0xf3, 0x96, 0x37, 0x0a, 0x66, 0x7a, 0xfd, + 0x78, 0x3b, 0x52, 0x3a, 0x89, 0x39, 0x59, 0xb0, 0x43, 0xc7, 0xe1, 0x6c, 0xef, 0x86, 0xb6, 0xa6, + 0x1d, 0x6c, 0x92, 0x45, 0x17, 0x79, 0xb3, 0xfe, 0x00, 0xc0, 0x75, 0xc0, 0xaf, 0x98, 0xde, 0xe7, + 0x32, 0x14, 0xb2, 0x9d, 0x8f, 0x5c, 0xb2, 0xb4, 0x09, 0x15, 0xfc, 0x04, 0xc8, 0x18, 0x34, 0x30, + 0x65, 0xd9, 0x9a, 0xf2, 0xcf, 0x7a, 0xf5, 0x17, 0x82, 0x95, 0x89, 0x27, 0xb9, 0x17, 0xab, 0xe4, + 0x34, 0x33, 0x3f, 0x5f, 0x00, 0xd9, 0xff, 0x9c, 0xe7, 0xa3, 0xe6, 0x17, 0xc6, 0xcd, 0xaf, 0xc2, + 0x42, 0x9f, 0x69, 0x8f, 0xb4, 0x68, 0x9d, 0x18, 0xc1, 0xb2, 0x03, 0x6a, 0x84, 0x5c, 0x1a, 0x71, + 0x28, 0x78, 0x4c, 0x4a, 0x56, 0x7f, 0x08, 0xc1, 0xcf, 0x00, 0xf2, 0x7d, 0x34, 0x99, 0x71, 0x8b, + 0xde, 0xfc, 0xc6, 0xda, 0xd4, 0xfb, 0xe7, 0x0f, 0x35, 0xd4, 0xbe, 0x20, 0xb8, 0x37, 0xe5, 0xa6, + 0x63, 0x17, 0x56, 0x27, 0x96, 0x7b, 0x66, 0x55, 0x1c, 0x7c, 0x1f, 0xd6, 0x26, 0x8f, 0xe1, 0x5a, + 0x45, 0x67, 0x3c, 0xac, 0xa0, 0x29, 0x94, 0xf7, 0x3c, 0x30, 0x3c, 0xac, 0x14, 0x6a, 0xdf, 0x11, + 0x54, 0x6f, 0xff, 0x5a, 0xf0, 0x1a, 0xdc, 0x1d, 0x66, 0x35, 0xcf, 0x65, 0x90, 0x13, 0x2a, 0x0e, + 0xae, 0xc1, 0xa3, 0x1b, 0x22, 0x5b, 0x89, 0x88, 0x8c, 0x90, 0x2f, 0x13, 0x19, 0x34, 0xa4, 0x89, + 0x59, 0xf3, 0x88, 0xc5, 0xd9, 0x52, 0xb7, 0x70, 0xb7, 0x63, 0xa5, 0x75, 0x97, 0x5b, 0xc0, 0xab, + 0x40, 0x6e, 0x70, 0xdf, 0xca, 0x63, 0xa9, 0x3e, 0xc8, 0x4a, 0x71, 0xeb, 0xf9, 0xc5, 0x15, 0x75, + 0x2e, 0xaf, 0xa8, 0x73, 0x7d, 0x45, 0xd1, 0xe7, 0x94, 0xa2, 0x6f, 0x29, 0x45, 0x3f, 0x52, 0x8a, + 0x2e, 0x52, 0x8a, 0x2e, 0x53, 0x8a, 0x7e, 0xa7, 0x14, 0xfd, 0x49, 0xa9, 0x73, 0x9d, 0x52, 0xf4, + 0xb5, 0x43, 0x9d, 0x8b, 0x0e, 0x75, 0x2e, 0x3b, 0xd4, 0x79, 0xd7, 0x7b, 0xe5, 0x5a, 0x65, 0xfb, + 0x7a, 0x6d, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x15, 0xd8, 0x65, 0xd8, 0x07, 0x05, 0x00, 0x00, +} + +func (x SerializableAsyncCallStatus) String() string { + s, ok := SerializableAsyncCallStatus_name[int32(x)] + if ok { + return s + } + return strconv.Itoa(int(x)) +} +func (x SerializableAsyncCallExecutionMode) String() string { + s, ok := SerializableAsyncCallExecutionMode_name[int32(x)] + if ok { + return s + } + return strconv.Itoa(int(x)) +} +func (this *SerializableAsyncCall) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*SerializableAsyncCall) + if !ok { + that2, ok := that.(SerializableAsyncCall) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.CallID, that1.CallID) { + return false + } + if this.Status != that1.Status { + return false + } + if this.ExecutionMode != that1.ExecutionMode { + return false + } + if !bytes.Equal(this.Destination, that1.Destination) { + return false + } + if !bytes.Equal(this.Data, that1.Data) { + return false + } + if this.GasLimit != that1.GasLimit { + return false + } + if this.GasLocked != that1.GasLocked { + return false + } + if !bytes.Equal(this.ValueBytes, that1.ValueBytes) { + return false + } + if this.SuccessCallback != that1.SuccessCallback { + return false + } + if this.ErrorCallback != that1.ErrorCallback { + return false + } + if !bytes.Equal(this.CallbackClosure, that1.CallbackClosure) { + return false + } + if this.IsAsyncV3 != that1.IsAsyncV3 { + return false + } + if this.HasPendingCallback != that1.HasPendingCallback { + return false + } + if this.PendingCallbackGasLocked != that1.PendingCallbackGasLocked { + return false + } + return true } +func (this *SerializableAsyncCallGroup) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + that1, ok := that.(*SerializableAsyncCallGroup) + if !ok { + that2, ok := that.(SerializableAsyncCallGroup) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Callback != that1.Callback { + return false + } + if this.GasLocked != that1.GasLocked { + return false + } + if !bytes.Equal(this.CallbackData, that1.CallbackData) { + return false + } + if this.Identifier != that1.Identifier { + return false + } + if len(this.AsyncCalls) != len(that1.AsyncCalls) { + return false + } + for i := range this.AsyncCalls { + if !this.AsyncCalls[i].Equal(that1.AsyncCalls[i]) { + return false + } + } + return true +} +func (this *SerializableAsyncCall) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 18) + s = append(s, "&vmhost.SerializableAsyncCall{") + s = append(s, "CallID: "+fmt.Sprintf("%#v", this.CallID)+",\n") + s = append(s, "Status: "+fmt.Sprintf("%#v", this.Status)+",\n") + s = append(s, "ExecutionMode: "+fmt.Sprintf("%#v", this.ExecutionMode)+",\n") + s = append(s, "Destination: "+fmt.Sprintf("%#v", this.Destination)+",\n") + s = append(s, "Data: "+fmt.Sprintf("%#v", this.Data)+",\n") + s = append(s, "GasLimit: "+fmt.Sprintf("%#v", this.GasLimit)+",\n") + s = append(s, "GasLocked: "+fmt.Sprintf("%#v", this.GasLocked)+",\n") + s = append(s, "ValueBytes: "+fmt.Sprintf("%#v", this.ValueBytes)+",\n") + s = append(s, "SuccessCallback: "+fmt.Sprintf("%#v", this.SuccessCallback)+",\n") + s = append(s, "ErrorCallback: "+fmt.Sprintf("%#v", this.ErrorCallback)+",\n") + s = append(s, "CallbackClosure: "+fmt.Sprintf("%#v", this.CallbackClosure)+",\n") + s = append(s, "IsAsyncV3: "+fmt.Sprintf("%#v", this.IsAsyncV3)+",\n") + s = append(s, "HasPendingCallback: "+fmt.Sprintf("%#v", this.HasPendingCallback)+",\n") + s = append(s, "PendingCallbackGasLocked: "+fmt.Sprintf("%#v", this.PendingCallbackGasLocked)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *SerializableAsyncCallGroup) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 9) + s = append(s, "&vmhost.SerializableAsyncCallGroup{") + s = append(s, "Callback: "+fmt.Sprintf("%#v", this.Callback)+",\n") + s = append(s, "GasLocked: "+fmt.Sprintf("%#v", this.GasLocked)+",\n") + s = append(s, "CallbackData: "+fmt.Sprintf("%#v", this.CallbackData)+",\n") + s = append(s, "Identifier: "+fmt.Sprintf("%#v", this.Identifier)+",\n") + if this.AsyncCalls != nil { + s = append(s, "AsyncCalls: "+fmt.Sprintf("%#v", this.AsyncCalls)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func valueToGoStringAsyncCall(v interface{}, typ string) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) +} func (m *SerializableAsyncCall) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -359,9 +528,14 @@ func (m *SerializableAsyncCall) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.IsCallbackPending { + if m.PendingCallbackGasLocked != 0 { + i = encodeVarintAsyncCall(dAtA, i, uint64(m.PendingCallbackGasLocked)) i-- - if m.IsCallbackPending { + dAtA[i] = 0x78 + } + if m.HasPendingCallback { + i-- + if m.HasPendingCallback { dAtA[i] = 1 } else { dAtA[i] = 0 @@ -574,9 +748,12 @@ func (m *SerializableAsyncCall) Size() (n int) { if m.IsAsyncV3 { n += 2 } - if m.IsCallbackPending { + if m.HasPendingCallback { n += 2 } + if m.PendingCallbackGasLocked != 0 { + n += 1 + sovAsyncCall(uint64(m.PendingCallbackGasLocked)) + } return n } @@ -616,6 +793,56 @@ func sovAsyncCall(x uint64) (n int) { func sozAsyncCall(x uint64) (n int) { return sovAsyncCall(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } +func (this *SerializableAsyncCall) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&SerializableAsyncCall{`, + `CallID:` + fmt.Sprintf("%v", this.CallID) + `,`, + `Status:` + fmt.Sprintf("%v", this.Status) + `,`, + `ExecutionMode:` + fmt.Sprintf("%v", this.ExecutionMode) + `,`, + `Destination:` + fmt.Sprintf("%v", this.Destination) + `,`, + `Data:` + fmt.Sprintf("%v", this.Data) + `,`, + `GasLimit:` + fmt.Sprintf("%v", this.GasLimit) + `,`, + `GasLocked:` + fmt.Sprintf("%v", this.GasLocked) + `,`, + `ValueBytes:` + fmt.Sprintf("%v", this.ValueBytes) + `,`, + `SuccessCallback:` + fmt.Sprintf("%v", this.SuccessCallback) + `,`, + `ErrorCallback:` + fmt.Sprintf("%v", this.ErrorCallback) + `,`, + `CallbackClosure:` + fmt.Sprintf("%v", this.CallbackClosure) + `,`, + `IsAsyncV3:` + fmt.Sprintf("%v", this.IsAsyncV3) + `,`, + `HasPendingCallback:` + fmt.Sprintf("%v", this.HasPendingCallback) + `,`, + `PendingCallbackGasLocked:` + fmt.Sprintf("%v", this.PendingCallbackGasLocked) + `,`, + `}`, + }, "") + return s +} +func (this *SerializableAsyncCallGroup) String() string { + if this == nil { + return "nil" + } + repeatedStringForAsyncCalls := "[]*SerializableAsyncCall{" + for _, f := range this.AsyncCalls { + repeatedStringForAsyncCalls += strings.Replace(f.String(), "SerializableAsyncCall", "SerializableAsyncCall", 1) + "," + } + repeatedStringForAsyncCalls += "}" + s := strings.Join([]string{`&SerializableAsyncCallGroup{`, + `Callback:` + fmt.Sprintf("%v", this.Callback) + `,`, + `GasLocked:` + fmt.Sprintf("%v", this.GasLocked) + `,`, + `CallbackData:` + fmt.Sprintf("%v", this.CallbackData) + `,`, + `Identifier:` + fmt.Sprintf("%v", this.Identifier) + `,`, + `AsyncCalls:` + repeatedStringForAsyncCalls + `,`, + `}`, + }, "") + return s +} +func valueToStringAsyncCall(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} func (m *SerializableAsyncCall) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -977,7 +1204,7 @@ func (m *SerializableAsyncCall) Unmarshal(dAtA []byte) error { m.IsAsyncV3 = bool(v != 0) case 14: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field IsCallbackPending", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field HasPendingCallback", wireType) } var v int for shift := uint(0); ; shift += 7 { @@ -994,7 +1221,26 @@ func (m *SerializableAsyncCall) Unmarshal(dAtA []byte) error { break } } - m.IsCallbackPending = bool(v != 0) + m.HasPendingCallback = bool(v != 0) + case 15: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PendingCallbackGasLocked", wireType) + } + m.PendingCallbackGasLocked = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAsyncCall + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PendingCallbackGasLocked |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipAsyncCall(dAtA[iNdEx:]) diff --git a/vmhost/asyncCall.proto b/vmhost/asyncCall.proto index a3b1ab908..4fd6601ff 100644 --- a/vmhost/asyncCall.proto +++ b/vmhost/asyncCall.proto @@ -33,7 +33,8 @@ message SerializableAsyncCall { string ErrorCallback = 11; bytes CallbackClosure = 12; bool IsAsyncV3 = 13; - bool IsCallbackPending = 14; + bool HasPendingCallback = 14; + uint64 PendingCallbackGasLocked = 15; } message SerializableAsyncCallGroup { diff --git a/vmhost/contexts/asyncLocal.go b/vmhost/contexts/asyncLocal.go index 2c6918328..92929422b 100644 --- a/vmhost/contexts/asyncLocal.go +++ b/vmhost/contexts/asyncLocal.go @@ -33,7 +33,7 @@ func (context *asyncContext) executeAsyncLocalCalls() error { if hasAnyRemoteCallbacks { currentCall := context.GetAsyncCallByCallID(context.GetCallID()).GetAsyncCall() if currentCall != nil && currentCall.IsAsyncV3 { - currentCall.MarkSkippedCallback() + currentCall.MarkSkippedCallback(currentCall.GetGasLocked()) } } @@ -96,38 +96,6 @@ func (context *asyncContext) executeAsyncLocalCall(asyncCall *vmhost.AsyncCall) return nil } -func (context *asyncContext) executePendingLocalAsyncCallbacks() error { - localCallsWithPendingCallbacks := make([]*vmhost.AsyncCall, 0) - for _, group := range context.asyncCallGroups { - for _, call := range group.AsyncCalls { - if call.IsLocal() && call.IsCallbackPending { - localCallsWithPendingCallbacks = append(localCallsWithPendingCallbacks, call) - } - } - } - - for _, call := range localCallsWithPendingCallbacks { - err := context.executePendingLocalAsyncCallback(call) - if err != nil { - return err - } - } - - return nil -} - -func (context *asyncContext) executePendingLocalAsyncCallback(asyncCall *vmhost.AsyncCall) error { - output := context.host.Output() - - destinationCallInput, err := context.createContractCallInput(asyncCall) - if err != nil { - logAsync.Trace("executePendingLocalAsyncCallback failed", "error", err) - return err - } - - return nil -} - func (context *asyncContext) executeAsyncCallbackAndComplete( asyncCall *vmhost.AsyncCall, destinationVMOutput *vmcommon.VMOutput, diff --git a/vmhost/hostCore/execution.go b/vmhost/hostCore/execution.go index 3c06cdcaf..7b9778ead 100644 --- a/vmhost/hostCore/execution.go +++ b/vmhost/hostCore/execution.go @@ -1238,7 +1238,7 @@ func (host *vmHost) callSCMethodAsynchronousCallBack() error { return nil } - if asyncCall.IsCallbackPending { + if asyncCall.HasPendingCallback { return nil } From 510746fb5986a217673fe7d2e0804fab21b2d0a2 Mon Sep 17 00:00:00 2001 From: Laurentiu Ciobanu Date: Wed, 30 Oct 2024 06:55:58 +0000 Subject: [PATCH 14/14] libvmexeccapi merge fix --- wasmer2/libvmexeccapi.h | 1 + 1 file changed, 1 insertion(+) diff --git a/wasmer2/libvmexeccapi.h b/wasmer2/libvmexeccapi.h index 1152bc3e5..ff4aea320 100644 --- a/wasmer2/libvmexeccapi.h +++ b/wasmer2/libvmexeccapi.h @@ -59,6 +59,7 @@ typedef struct { int32_t (*transfer_esdt_nft_execute_func_ptr)(void *context, int32_t dest_offset, int32_t token_id_offset, int32_t token_id_len, int32_t value_offset, int64_t nonce, int64_t gas_limit, int32_t function_offset, int32_t function_length, int32_t num_arguments, int32_t arguments_length_offset, int32_t data_offset); int32_t (*multi_transfer_esdt_nft_execute_func_ptr)(void *context, int32_t dest_offset, int32_t num_token_transfers, int32_t token_transfers_args_length_offset, int32_t token_transfer_data_offset, int64_t gas_limit, int32_t function_offset, int32_t function_length, int32_t num_arguments, int32_t arguments_length_offset, int32_t data_offset); int32_t (*create_async_call_func_ptr)(void *context, int32_t dest_offset, int32_t value_offset, int32_t data_offset, int32_t data_length, int32_t success_offset, int32_t success_length, int32_t error_offset, int32_t error_length, int64_t gas, int64_t extra_gas_for_callback); + int32_t (*create_async_v3_call_func_ptr)(void *context, int32_t dest_offset, int32_t value_offset, int32_t data_offset, int32_t data_length, int32_t success_offset, int32_t success_length, int32_t error_offset, int32_t error_length, int64_t gas, int64_t extra_gas_for_callback); int32_t (*set_async_context_callback_func_ptr)(void *context, int32_t callback, int32_t callback_length, int32_t data, int32_t data_length, int64_t gas); void (*upgrade_contract_func_ptr)(void *context, int32_t dest_offset, int64_t gas_limit, int32_t value_offset, int32_t code_offset, int32_t code_metadata_offset, int32_t length, int32_t num_arguments, int32_t arguments_length_offset, int32_t data_offset); void (*upgrade_from_source_contract_func_ptr)(void *context, int32_t dest_offset, int64_t gas_limit, int32_t value_offset, int32_t source_contract_address_offset, int32_t code_metadata_offset, int32_t num_arguments, int32_t arguments_length_offset, int32_t data_offset);