Skip to content

Commit

Permalink
Merge pull request #161 from ElrondNetwork/callback-out-of-gas-fix
Browse files Browse the repository at this point in the history
Fix panic in async out-of-gas case
  • Loading branch information
camilbancioiu authored Sep 3, 2020
2 parents 1ab9d35 + aff5f6e commit 3fc5a8d
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 2 deletions.
6 changes: 6 additions & 0 deletions arwen/host/asyncCall.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,12 @@ func (host *vmHost) processCallbackVMOutput(callbackVMOutput *vmcommon.VMOutput,
output := host.Output()

runtime.GetVMInput().GasProvided = 0

if callbackVMOutput == nil {
callbackVMOutput = output.CreateVMOutputInCaseOfError(callBackErr)
}

output.SetReturnMessage(callbackVMOutput.ReturnMessage)
output.Finish([]byte(callbackVMOutput.ReturnCode.String()))
output.Finish([]byte(runtime.GetCurrentTxHash()))

Expand Down
26 changes: 26 additions & 0 deletions arwen/host/execution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"testing"

"github.com/ElrondNetwork/arwen-wasm-vm/arwen"
"github.com/ElrondNetwork/arwen-wasm-vm/config"
"github.com/ElrondNetwork/arwen-wasm-vm/mock"
vmcommon "github.com/ElrondNetwork/elrond-vm-common"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -1091,6 +1092,31 @@ func TestExecution_AsyncCall_BuiltinFails(t *testing.T) {
require.Equal(t, [][]byte{[]byte("hello"), {4}}, vmOutput.ReturnData)
}

func TestExecution_AsyncCall_CallBackFailsBeforeExecution(t *testing.T) {
config.AsyncCallbackGasLockForTests = uint64(2)

code := GetTestSCCode("async-call-builtin", "../../")
scBalance := big.NewInt(1000)

host, stubBlockchainHook := DefaultTestArwenForCall(t, code, scBalance)
stubBlockchainHook.ProcessBuiltInFunctionCalled = dummyProcessBuiltInFunction
host.protocolBuiltinFunctions = getDummyBuiltinFunctionNames()

input := DefaultTestContractCallInput()
input.RecipientAddr = parentAddress
input.Function = "performAsyncCallToBuiltin"
input.Arguments = [][]byte{{1}}
input.GasProvided = 1000000
input.CurrentTxHash = []byte("txhash")

vmOutput, err := host.RunSmartContractCall(input)
require.Nil(t, err)

require.NotNil(t, vmOutput)
require.Equal(t, vmcommon.Ok, vmOutput.ReturnCode)
require.Equal(t, [][]byte{[]byte("hello"), []byte("out of gas"), []byte("txhash")}, vmOutput.ReturnData)
}

func TestExecution_CreateNewContract_Success(t *testing.T) {
parentCode := GetTestSCCode("deployer", "../../")
childCode := GetTestSCCode("init-correct", "../../")
Expand Down
2 changes: 2 additions & 0 deletions arwen/host/execution_vmoutputs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,8 @@ func expectedVMOutput_AsyncCall_CallBackFails(parentCode []byte, childCode []byt
AddFinishData(vmOutput, []byte("user error"))
AddFinishData(vmOutput, []byte("txhash"))

vmOutput.ReturnMessage = "callBack error"

return vmOutput
}

Expand Down
9 changes: 8 additions & 1 deletion arwen/host/testInitializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ var userAddress = []byte("userAccount.....................")
var parentAddress = []byte("parentSC........................")
var childAddress = []byte("childSC.........................")

var CustomGasSchedule = config.GasScheduleMap(nil)

// GetSCCode retrieves the bytecode of a WASM module from a file
func GetSCCode(fileName string) []byte {
code, err := ioutil.ReadFile(filepath.Clean(fileName))
Expand Down Expand Up @@ -101,10 +103,15 @@ func DefaultTestArwenForTwoSCs(t *testing.T, parentCode []byte, childCode []byte
}

func DefaultTestArwen(tb testing.TB, blockchain vmcommon.BlockchainHook, crypto vmcommon.CryptoHook) (*vmHost, error) {
gasSchedule := CustomGasSchedule
if gasSchedule == nil {
gasSchedule = config.MakeGasMapForTests()
}

host, err := NewArwenVM(blockchain, crypto, &arwen.VMHostParameters{
VMType: defaultVMType,
BlockGasLimit: uint64(1000),
GasSchedule: config.MakeGasMapForTests(),
GasSchedule: gasSchedule,
ProtocolBuiltinFunctions: make(vmcommon.FunctionNames),
ElrondProtectedKeyPrefix: []byte("ELROND"),
})
Expand Down
3 changes: 2 additions & 1 deletion config/gasSchedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import (
)

const GasValueForTests = 1
const AsyncCallbackGasLockForTests = 100_000

var AsyncCallbackGasLockForTests = uint64(100_000)

// GasScheduleMap (alias) is the map for gas schedule
type GasScheduleMap = map[string]map[string]uint64
Expand Down

0 comments on commit 3fc5a8d

Please sign in to comment.