From 7b713762be8262f63a4756b8ddf608862d141d08 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Fri, 19 Nov 2021 17:02:53 +0300 Subject: [PATCH] vm: do not increment invocation counter in Call Everywhere it matters (and that's callExFromNative() now) it's incremented already, so when we're doing Call() at the same time (and it's done to invoke `_initialize` method) we're effectively double-incrementing it. --- pkg/core/interop_system_test.go | 24 +++++++++++++++++++++--- pkg/vm/vm.go | 4 +--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/pkg/core/interop_system_test.go b/pkg/core/interop_system_test.go index 4ee1c63da..185955440 100644 --- a/pkg/core/interop_system_test.go +++ b/pkg/core/interop_system_test.go @@ -229,21 +229,31 @@ func TestRuntimeGetNotifications(t *testing.T) { } func TestRuntimeGetInvocationCounter(t *testing.T) { - v, ic, _ := createVM(t) + v, ic, bc := createVM(t) + + cs, _ := getTestContractState(bc) + require.NoError(t, bc.contracts.Management.PutContractState(ic.DAO, cs)) ic.VM.Invocations[hash.Hash160([]byte{2})] = 42 t.Run("No invocations", func(t *testing.T) { - v.LoadScript([]byte{1}) + v.Load([]byte{1}) // do not return an error in this case. require.NoError(t, runtime.GetInvocationCounter(ic)) require.EqualValues(t, 1, v.Estack().Pop().BigInt().Int64()) }) t.Run("NonZero", func(t *testing.T) { - v.LoadScript([]byte{2}) + v.Load([]byte{2}) require.NoError(t, runtime.GetInvocationCounter(ic)) require.EqualValues(t, 42, v.Estack().Pop().BigInt().Int64()) }) + t.Run("Contract", func(t *testing.T) { + w := io.NewBufBinWriter() + emit.AppCall(w.BinWriter, cs.Hash, "invocCounter", callflag.All) + v.LoadWithFlags(w.Bytes(), callflag.All) + require.NoError(t, v.Run()) + require.EqualValues(t, 1, v.Estack().Pop().BigInt().Int64()) + }) } func TestStoragePut(t *testing.T) { @@ -756,6 +766,9 @@ func getTestContractState(bc *Blockchain) (*state.Contract, *state.Contract) { burnGasOff := w.Len() emit.Syscall(w.BinWriter, interopnames.SystemRuntimeBurnGas) emit.Opcodes(w.BinWriter, opcode.RET) + invocCounterOff := w.Len() + emit.Syscall(w.BinWriter, interopnames.SystemRuntimeGetInvocationCounter) + emit.Opcodes(w.BinWriter, opcode.RET) script := w.Bytes() h := hash.Hash160(script) @@ -925,6 +938,11 @@ func getTestContractState(bc *Blockchain) (*state.Contract, *state.Contract) { }, ReturnType: smartcontract.VoidType, }, + { + Name: "invocCounter", + Offset: invocCounterOff, + ReturnType: smartcontract.IntegerType, + }, } m.Permissions = make([]manifest.Permission, 2) m.Permissions[0].Contract.Type = manifest.PermissionHash diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 4732f02b7..84bb6ada0 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -1556,11 +1556,9 @@ func (v *VM) throw(item stackitem.Item) { v.handleException() } -// Call calls method by offset. It pushes new context to the invocation stack -// and increments invocation counter for the corresponding context script hash. +// Call calls method by offset using new execution context. func (v *VM) Call(ctx *Context, offset int) { v.call(ctx, offset) - v.Invocations[ctx.ScriptHash()]++ } // call is an internal representation of Call, which does not