forked from TrueCloudLab/neoneo-go
core: implement System.Runtime.GetNotifications syscall
This commit is contained in:
parent
afd8f3b87a
commit
75e597f880
4 changed files with 84 additions and 0 deletions
|
@ -28,6 +28,7 @@ var syscalls = map[string]map[string]string{
|
|||
"GetCallingScriptHash": "System.Runtime.GetCallingScriptHash",
|
||||
"GetEntryScriptHash": "System.Runtime.GetEntryScriptHash",
|
||||
"GetExecutingScriptHash": "System.Runtime.GetExecutingScriptHash",
|
||||
"GetNotifications": "System.Runtime.GetNotifications",
|
||||
|
||||
"GasLeft": "System.Runtime.GasLeft",
|
||||
"GetTrigger": "System.Runtime.GetTrigger",
|
||||
|
|
|
@ -2,7 +2,11 @@ package runtime
|
|||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// GasLeft returns remaining amount of GAS.
|
||||
|
@ -10,3 +14,38 @@ func GasLeft(_ *interop.Context, v *vm.VM) error {
|
|||
v.Estack().PushVal(int64(v.GasLimit - v.GasConsumed()))
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetNotifications returns notifications emitted by current contract execution.
|
||||
func GetNotifications(ic *interop.Context, v *vm.VM) error {
|
||||
item := v.Estack().Pop().Item()
|
||||
notifications := ic.Notifications
|
||||
if _, ok := item.(stackitem.Null); !ok {
|
||||
b, err := item.TryBytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u, err := util.Uint160DecodeBytesBE(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
notifications = []state.NotificationEvent{}
|
||||
for i := range ic.Notifications {
|
||||
if ic.Notifications[i].ScriptHash.Equals(u) {
|
||||
notifications = append(notifications, ic.Notifications[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(notifications) > vm.MaxStackSize {
|
||||
return errors.New("too many notifications")
|
||||
}
|
||||
arr := stackitem.NewArray(make([]stackitem.Item, 0, len(notifications)))
|
||||
for i := range notifications {
|
||||
ev := stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewByteArray(notifications[i].ScriptHash.BytesBE()),
|
||||
notifications[i].Item,
|
||||
})
|
||||
arr.Append(ev)
|
||||
}
|
||||
v.Estack().PushVal(arr)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -208,3 +208,39 @@ func TestRuntimeGasLeft(t *testing.T) {
|
|||
require.NoError(t, runtime.GasLeft(ic, v))
|
||||
require.EqualValues(t, 42, v.Estack().Pop().BigInt().Int64())
|
||||
}
|
||||
|
||||
func TestRuntimeGetNotifications(t *testing.T) {
|
||||
v, ic, chain := createVM(t)
|
||||
defer chain.Close()
|
||||
|
||||
ic.Notifications = []state.NotificationEvent{
|
||||
{ScriptHash: util.Uint160{1}, Item: stackitem.NewByteArray([]byte{11})},
|
||||
{ScriptHash: util.Uint160{2}, Item: stackitem.NewByteArray([]byte{22})},
|
||||
{ScriptHash: util.Uint160{1}, Item: stackitem.NewByteArray([]byte{33})},
|
||||
}
|
||||
|
||||
t.Run("NoFilter", func(t *testing.T) {
|
||||
v.Estack().PushVal(stackitem.Null{})
|
||||
require.NoError(t, runtime.GetNotifications(ic, v))
|
||||
|
||||
arr := v.Estack().Pop().Array()
|
||||
require.Equal(t, len(ic.Notifications), len(arr))
|
||||
for i := range arr {
|
||||
elem := arr[i].Value().([]stackitem.Item)
|
||||
require.Equal(t, ic.Notifications[i].ScriptHash.BytesBE(), elem[0].Value())
|
||||
require.Equal(t, ic.Notifications[i].Item, elem[1])
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("WithFilter", func(t *testing.T) {
|
||||
h := util.Uint160{2}.BytesBE()
|
||||
v.Estack().PushVal(h)
|
||||
require.NoError(t, runtime.GetNotifications(ic, v))
|
||||
|
||||
arr := v.Estack().Pop().Array()
|
||||
require.Equal(t, 1, len(arr))
|
||||
elem := arr[0].Value().([]stackitem.Item)
|
||||
require.Equal(t, h, elem[0].Value())
|
||||
require.Equal(t, ic.Notifications[1].Item, elem[1])
|
||||
})
|
||||
}
|
||||
|
|
|
@ -60,3 +60,11 @@ func Verification() byte {
|
|||
func GasLeft() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetNotifications returns notifications emitted by contract h.
|
||||
// 'nil' literal means no filtering. It returns slice consisting of following elements:
|
||||
// [ scripthash of notification's contract , emitted item ].
|
||||
// This function uses `System.Runtime.GetNotifications` syscall.
|
||||
func GetNotifications(h []byte) [][]interface{} {
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue