diff --git a/pkg/core/interop/enumerator/interop.go b/pkg/core/interop/enumerator/interop.go index ecd90efadd..6265d74d1f 100644 --- a/pkg/core/interop/enumerator/interop.go +++ b/pkg/core/interop/enumerator/interop.go @@ -10,7 +10,7 @@ func Concat(_ *interop.Context, v *vm.VM) error { return vm.EnumeratorConcat(v) } -// Create creates an enumerator from an array-like stack item. +// Create creates an enumerator from an array-like or bytearray-like stack item. func Create(_ *interop.Context, v *vm.VM) error { return vm.EnumeratorCreate(v) } diff --git a/pkg/interop/enumerator/enumerator.go b/pkg/interop/enumerator/enumerator.go index ca52f4dcc8..5581538a88 100644 --- a/pkg/interop/enumerator/enumerator.go +++ b/pkg/interop/enumerator/enumerator.go @@ -9,11 +9,11 @@ package enumerator // or structures that have values with no explicit keys. type Enumerator struct{} -// Create creates a new enumerator from the given items (slice or structure). -// New enumerator points at index -1 of its items, so the user of it has to -// advance it first with Next. This function uses `System.Enumerator.Create` -// syscall. -func Create(items []interface{}) Enumerator { +// Create creates a new enumerator from the given items (slice, structure, byte +// array and integer or boolean converted to byte array). New enumerator points +// at index -1 of its items, so the user of it has to advance it first with Next. +// This function uses `System.Enumerator.Create` syscall. +func Create(items interface{}) Enumerator { return Enumerator{} } diff --git a/pkg/vm/interop.go b/pkg/vm/interop.go index 2c6259334c..78e1db225e 100644 --- a/pkg/vm/interop.go +++ b/pkg/vm/interop.go @@ -126,12 +126,25 @@ func init() { // EnumeratorCreate handles syscall System.Enumerator.Create. func EnumeratorCreate(v *VM) error { - data := v.Estack().Pop().Array() - v.Estack().Push(&Element{ - value: stackitem.NewInterop(&arrayWrapper{ + var interop interface{} + switch t := v.Estack().Pop().value.(type) { + case *stackitem.Array, *stackitem.Struct: + interop = &arrayWrapper{ + index: -1, + value: t.Value().([]stackitem.Item), + } + default: + data, err := t.TryBytes() + if err != nil { + return fmt.Errorf("can not create enumerator from type %s: %v", t.Type(), err) + } + interop = &byteArrayWrapper{ index: -1, value: data, - }), + } + } + v.Estack().Push(&Element{ + value: stackitem.NewInterop(interop), }) return nil diff --git a/pkg/vm/interop_iterators.go b/pkg/vm/interop_iterators.go index 473acf65c0..b29de47e33 100644 --- a/pkg/vm/interop_iterators.go +++ b/pkg/vm/interop_iterators.go @@ -1,6 +1,8 @@ package vm import ( + "math/big" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) @@ -15,6 +17,11 @@ type ( value []stackitem.Item } + byteArrayWrapper struct { + index int + value []byte + } + concatEnum struct { current enumerator second enumerator @@ -63,6 +70,23 @@ func (a *arrayWrapper) Key() stackitem.Item { return stackitem.Make(a.index) } +func (a *byteArrayWrapper) Next() bool { + if next := a.index + 1; next < len(a.value) { + a.index = next + return true + } + + return false +} + +func (a *byteArrayWrapper) Value() stackitem.Item { + return stackitem.NewBigInteger(big.NewInt(int64(a.value[a.index]))) +} + +func (a *byteArrayWrapper) Key() stackitem.Item { + return stackitem.Make(a.index) +} + func (c *concatEnum) Next() bool { if c.current.Next() { return true