core: implement System.Runtime.GetInvocationCounter syscall
This commit is contained in:
parent
75e597f880
commit
3762ebdd08
7 changed files with 39 additions and 0 deletions
|
@ -29,6 +29,7 @@ var syscalls = map[string]map[string]string{
|
|||
"GetEntryScriptHash": "System.Runtime.GetEntryScriptHash",
|
||||
"GetExecutingScriptHash": "System.Runtime.GetExecutingScriptHash",
|
||||
"GetNotifications": "System.Runtime.GetNotifications",
|
||||
"GetInvocationCounter": "System.Runtime.GetInvocationCounter",
|
||||
|
||||
"GasLeft": "System.Runtime.GasLeft",
|
||||
"GetTrigger": "System.Runtime.GetTrigger",
|
||||
|
|
|
@ -30,6 +30,7 @@ type Context struct {
|
|||
DAO *dao.Cached
|
||||
Notifications []state.NotificationEvent
|
||||
Log *zap.Logger
|
||||
Invocations map[util.Uint160]int
|
||||
}
|
||||
|
||||
// NewContext returns new interop context.
|
||||
|
@ -45,6 +46,7 @@ func NewContext(trigger trigger.Type, bc blockchainer.Blockchainer, d dao.DAO, n
|
|||
DAO: dao,
|
||||
Notifications: nes,
|
||||
Log: log,
|
||||
Invocations: make(map[util.Uint160]int),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,3 +49,13 @@ func GetNotifications(ic *interop.Context, v *vm.VM) error {
|
|||
v.Estack().PushVal(arr)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetInvocationCounter returns how many times current contract was invoked during current tx execution.
|
||||
func GetInvocationCounter(ic *interop.Context, v *vm.VM) error {
|
||||
count, ok := ic.Invocations[v.GetCurrentScriptHash()]
|
||||
if !ok {
|
||||
return errors.New("current contract wasn't invoked from others")
|
||||
}
|
||||
v.Estack().PushVal(count)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -443,6 +443,7 @@ func contractCallExInternal(ic *interop.Context, v *vm.VM, h []byte, method stac
|
|||
return errors.New("disallowed method call")
|
||||
}
|
||||
}
|
||||
ic.Invocations[u]++
|
||||
v.LoadScriptWithHash(cs.Script, u, v.Context().GetCallFlags()&f)
|
||||
v.Estack().PushVal(args)
|
||||
v.Estack().PushVal(method)
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/nspcc-dev/dbft/crypto"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||
|
@ -244,3 +245,20 @@ func TestRuntimeGetNotifications(t *testing.T) {
|
|||
require.Equal(t, ic.Notifications[1].Item, elem[1])
|
||||
})
|
||||
}
|
||||
|
||||
func TestRuntimeGetInvocationCounter(t *testing.T) {
|
||||
v, ic, chain := createVM(t)
|
||||
defer chain.Close()
|
||||
|
||||
ic.Invocations[hash.Hash160([]byte{2})] = 42
|
||||
|
||||
t.Run("Zero", func(t *testing.T) {
|
||||
v.LoadScript([]byte{1})
|
||||
require.Error(t, runtime.GetInvocationCounter(ic, v))
|
||||
})
|
||||
t.Run("NonZero", func(t *testing.T) {
|
||||
v.LoadScript([]byte{2})
|
||||
require.NoError(t, runtime.GetInvocationCounter(ic, v))
|
||||
require.EqualValues(t, 42, v.Estack().Pop().BigInt().Int64())
|
||||
})
|
||||
}
|
||||
|
|
|
@ -111,6 +111,7 @@ var systemInterops = []interop.Function{
|
|||
{Name: "System.Runtime.GetCallingScriptHash", Func: engineGetCallingScriptHash, Price: 400},
|
||||
{Name: "System.Runtime.GetEntryScriptHash", Func: engineGetEntryScriptHash, Price: 400},
|
||||
{Name: "System.Runtime.GetExecutingScriptHash", Func: engineGetExecutingScriptHash, Price: 400},
|
||||
{Name: "System.Runtime.GetInvocationCounter", Func: runtime.GetInvocationCounter, Price: 400},
|
||||
{Name: "System.Runtime.GetScriptContainer", Func: engineGetScriptContainer, Price: 250},
|
||||
{Name: "System.Runtime.GetTime", Func: runtimeGetTime, Price: 250,
|
||||
AllowedTriggers: trigger.Application},
|
||||
|
|
|
@ -68,3 +68,9 @@ func GasLeft() int64 {
|
|||
func GetNotifications(h []byte) [][]interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetInvocationCounter returns how many times current contract was invoked during current tx execution.
|
||||
// This function uses `System.Runtime.GetInvocationCounter` syscall.
|
||||
func GetInvocationCounter() int {
|
||||
return 0
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue