forked from TrueCloudLab/neoneo-go
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",
|
"GetEntryScriptHash": "System.Runtime.GetEntryScriptHash",
|
||||||
"GetExecutingScriptHash": "System.Runtime.GetExecutingScriptHash",
|
"GetExecutingScriptHash": "System.Runtime.GetExecutingScriptHash",
|
||||||
"GetNotifications": "System.Runtime.GetNotifications",
|
"GetNotifications": "System.Runtime.GetNotifications",
|
||||||
|
"GetInvocationCounter": "System.Runtime.GetInvocationCounter",
|
||||||
|
|
||||||
"GasLeft": "System.Runtime.GasLeft",
|
"GasLeft": "System.Runtime.GasLeft",
|
||||||
"GetTrigger": "System.Runtime.GetTrigger",
|
"GetTrigger": "System.Runtime.GetTrigger",
|
||||||
|
|
|
@ -30,6 +30,7 @@ type Context struct {
|
||||||
DAO *dao.Cached
|
DAO *dao.Cached
|
||||||
Notifications []state.NotificationEvent
|
Notifications []state.NotificationEvent
|
||||||
Log *zap.Logger
|
Log *zap.Logger
|
||||||
|
Invocations map[util.Uint160]int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewContext returns new interop context.
|
// NewContext returns new interop context.
|
||||||
|
@ -45,6 +46,7 @@ func NewContext(trigger trigger.Type, bc blockchainer.Blockchainer, d dao.DAO, n
|
||||||
DAO: dao,
|
DAO: dao,
|
||||||
Notifications: nes,
|
Notifications: nes,
|
||||||
Log: log,
|
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)
|
v.Estack().PushVal(arr)
|
||||||
return nil
|
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")
|
return errors.New("disallowed method call")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ic.Invocations[u]++
|
||||||
v.LoadScriptWithHash(cs.Script, u, v.Context().GetCallFlags()&f)
|
v.LoadScriptWithHash(cs.Script, u, v.Context().GetCallFlags()&f)
|
||||||
v.Estack().PushVal(args)
|
v.Estack().PushVal(args)
|
||||||
v.Estack().PushVal(method)
|
v.Estack().PushVal(method)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/nspcc-dev/dbft/crypto"
|
"github.com/nspcc-dev/dbft/crypto"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
|
"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/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/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"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])
|
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.GetCallingScriptHash", Func: engineGetCallingScriptHash, Price: 400},
|
||||||
{Name: "System.Runtime.GetEntryScriptHash", Func: engineGetEntryScriptHash, Price: 400},
|
{Name: "System.Runtime.GetEntryScriptHash", Func: engineGetEntryScriptHash, Price: 400},
|
||||||
{Name: "System.Runtime.GetExecutingScriptHash", Func: engineGetExecutingScriptHash, 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.GetScriptContainer", Func: engineGetScriptContainer, Price: 250},
|
||||||
{Name: "System.Runtime.GetTime", Func: runtimeGetTime, Price: 250,
|
{Name: "System.Runtime.GetTime", Func: runtimeGetTime, Price: 250,
|
||||||
AllowedTriggers: trigger.Application},
|
AllowedTriggers: trigger.Application},
|
||||||
|
|
|
@ -68,3 +68,9 @@ func GasLeft() int64 {
|
||||||
func GetNotifications(h []byte) [][]interface{} {
|
func GetNotifications(h []byte) [][]interface{} {
|
||||||
return nil
|
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