vm: remove iterator/enumerator Concat API

Follow neo-project/neo#2170.
This commit is contained in:
Evgeniy Stratonikov 2021-01-12 11:42:09 +03:00 committed by Roman Khimov
parent e36e71ffbd
commit d04b000748
12 changed files with 2 additions and 167 deletions

View file

@ -36,13 +36,11 @@ var syscalls = map[string]map[string]string{
"SHA256": interopnames.NeoCryptoSHA256,
},
"enumerator": {
"Concat": interopnames.SystemEnumeratorConcat,
"Create": interopnames.SystemEnumeratorCreate,
"Next": interopnames.SystemEnumeratorNext,
"Value": interopnames.SystemEnumeratorValue,
},
"iterator": {
"Concat": interopnames.SystemIteratorConcat,
"Create": interopnames.SystemIteratorCreate,
"Key": interopnames.SystemIteratorKey,
"Keys": interopnames.SystemIteratorKeys,

View file

@ -5,11 +5,6 @@ import (
"github.com/nspcc-dev/neo-go/pkg/vm"
)
// Concat concatenates 2 enumerators into a single one.
func Concat(ic *interop.Context) error {
return vm.EnumeratorConcat(ic.VM)
}
// Create creates an enumerator from an array-like or bytearray-like stack item.
func Create(ic *interop.Context) error {
return vm.EnumeratorCreate(ic.VM)

View file

@ -13,11 +13,8 @@ import (
func TestEnumerator(t *testing.T) {
ic := &interop.Context{VM: vm.New()}
full := []byte{4, 8, 15}
ic.VM.Estack().PushVal(full[2:])
ic.VM.Estack().PushVal(full)
require.NoError(t, Create(ic))
ic.VM.Estack().PushVal(full[:2])
require.NoError(t, Create(ic))
require.NoError(t, Concat(ic))
res := ic.VM.Estack().Pop().Item()
for i := range full {

View file

@ -26,11 +26,9 @@ const (
SystemContractGetCallFlags = "System.Contract.GetCallFlags"
SystemContractNativeOnPersist = "System.Contract.NativeOnPersist"
SystemContractNativePostPersist = "System.Contract.NativePostPersist"
SystemEnumeratorConcat = "System.Enumerator.Concat"
SystemEnumeratorCreate = "System.Enumerator.Create"
SystemEnumeratorNext = "System.Enumerator.Next"
SystemEnumeratorValue = "System.Enumerator.Value"
SystemIteratorConcat = "System.Iterator.Concat"
SystemIteratorCreate = "System.Iterator.Create"
SystemIteratorKey = "System.Iterator.Key"
SystemIteratorKeys = "System.Iterator.Keys"
@ -91,11 +89,9 @@ var names = []string{
SystemContractGetCallFlags,
SystemContractNativeOnPersist,
SystemContractNativePostPersist,
SystemEnumeratorConcat,
SystemEnumeratorCreate,
SystemEnumeratorNext,
SystemEnumeratorValue,
SystemIteratorConcat,
SystemIteratorCreate,
SystemIteratorKey,
SystemIteratorKeys,

View file

@ -5,11 +5,6 @@ import (
"github.com/nspcc-dev/neo-go/pkg/vm"
)
// Concat concatenates 2 iterators into a single one.
func Concat(ic *interop.Context) error {
return vm.IteratorConcat(ic.VM)
}
// Create creates an iterator from array-like or map stack item.
func Create(ic *interop.Context) error {
return vm.IteratorCreate(ic.VM)

View file

@ -13,11 +13,8 @@ import (
func TestIterator(t *testing.T) {
ic := &interop.Context{VM: vm.New()}
full := []byte{4, 8, 15}
ic.VM.Estack().PushVal(full[2:])
ic.VM.Estack().PushVal(full)
require.NoError(t, Create(ic))
ic.VM.Estack().PushVal(full[:2])
require.NoError(t, Create(ic))
require.NoError(t, Concat(ic))
res := ic.VM.Estack().Pop().Item()
ic.VM.Estack().PushVal(res)

View file

@ -58,11 +58,9 @@ var systemInterops = []interop.Function{
{Name: interopnames.SystemContractGetCallFlags, Func: contractGetCallFlags, Price: 1 << 10},
{Name: interopnames.SystemContractNativeOnPersist, Func: native.OnPersist, Price: 0, RequiredFlags: callflag.WriteStates},
{Name: interopnames.SystemContractNativePostPersist, Func: native.PostPersist, Price: 0, RequiredFlags: callflag.WriteStates},
{Name: interopnames.SystemEnumeratorConcat, Func: enumerator.Concat, Price: 1 << 4, ParamCount: 2},
{Name: interopnames.SystemEnumeratorCreate, Func: enumerator.Create, Price: 1 << 4, ParamCount: 1},
{Name: interopnames.SystemEnumeratorNext, Func: enumerator.Next, Price: 1 << 15, ParamCount: 1},
{Name: interopnames.SystemEnumeratorValue, Func: enumerator.Value, Price: 1 << 4, ParamCount: 1},
{Name: interopnames.SystemIteratorConcat, Func: iterator.Concat, Price: 1 << 4, ParamCount: 2},
{Name: interopnames.SystemIteratorCreate, Func: iterator.Create, Price: 1 << 4, ParamCount: 1},
{Name: interopnames.SystemIteratorKey, Func: iterator.Key, Price: 1 << 4, ParamCount: 1},
{Name: interopnames.SystemIteratorKeys, Func: iterator.Keys, Price: 1 << 4, ParamCount: 1},

View file

@ -30,12 +30,3 @@ func Next(e Enumerator) bool {
func Value(e Enumerator) interface{} {
return nil
}
// Concat concatenates two given enumerators returning one that will range on
// a first and then continue with b. Enumerator positions are not reset for a
// and b, so if any of them was already advanced by Next the resulting
// Enumerator will point at this new position and never go back to previous
// values. This function uses `System.Enumerator.Concat` syscall.
func Concat(a, b Enumerator) Enumerator {
return Enumerator{}
}

View file

@ -19,17 +19,6 @@ func Create(items interface{}) Iterator {
return Iterator{}
}
// Concat concatenates two given iterators returning one that will range on
// a first and then continue with b. Iterator positions are not reset for a
// and b, so if any of them was already advanced by Next the resulting
// Iterator will point at this new position and never go back to previous
// key-value pairs. Concatenated iterators also remain completely independent
// in results they return, so if both contain the same key you'll receive this
// key twice when iterating. This function uses `System.Iterator.Concat` syscall.
func Concat(a, b Iterator) Iterator {
return Iterator{}
}
// Key returns iterator's key at current position. It's only valid to call after
// successful Next call. This function uses `System.Iterator.Key` syscall.
func Key(it Iterator) interface{} {

View file

@ -31,14 +31,10 @@ var defaultVMInterops = []interopIDFuncPrice{
Func: EnumeratorCreate, Price: 1 << 4},
{ID: interopnames.ToID([]byte(interopnames.SystemEnumeratorNext)),
Func: EnumeratorNext, Price: 1 << 15},
{ID: interopnames.ToID([]byte(interopnames.SystemEnumeratorConcat)),
Func: EnumeratorConcat, Price: 1 << 4},
{ID: interopnames.ToID([]byte(interopnames.SystemEnumeratorValue)),
Func: EnumeratorValue, Price: 1 << 4},
{ID: interopnames.ToID([]byte(interopnames.SystemIteratorCreate)),
Func: IteratorCreate, Price: 1 << 4},
{ID: interopnames.ToID([]byte(interopnames.SystemIteratorConcat)),
Func: IteratorConcat, Price: 1 << 4},
{ID: interopnames.ToID([]byte(interopnames.SystemIteratorKey)),
Func: IteratorKey, Price: 1 << 4},
{ID: interopnames.ToID([]byte(interopnames.SystemIteratorKeys)),
@ -160,23 +156,6 @@ func EnumeratorValue(v *VM) error {
return nil
}
// EnumeratorConcat handles syscall System.Enumerator.Concat.
func EnumeratorConcat(v *VM) error {
iop1 := v.Estack().Pop().Interop()
arr1 := iop1.Value().(enumerator)
iop2 := v.Estack().Pop().Interop()
arr2 := iop2.Value().(enumerator)
v.Estack().Push(&Element{
value: stackitem.NewInterop(&concatEnum{
current: arr1,
second: arr2,
}),
})
return nil
}
// IteratorCreate handles syscall System.Iterator.Create.
func IteratorCreate(v *VM) error {
data := v.Estack().Pop()
@ -212,23 +191,6 @@ func NewMapIterator(m *stackitem.Map) *stackitem.Interop {
})
}
// IteratorConcat handles syscall System.Iterator.Concat.
func IteratorConcat(v *VM) error {
iop1 := v.Estack().Pop().Interop()
iter1 := iop1.Value().(iterator)
iop2 := v.Estack().Pop().Interop()
iter2 := iop2.Value().(iterator)
v.Estack().Push(&Element{value: stackitem.NewInterop(
&concatIter{
current: iter1,
second: iter2,
},
)})
return nil
}
// IteratorKey handles syscall System.Iterator.Key.
func IteratorKey(v *VM) error {
iop := v.estack.Pop().Interop()

View file

@ -22,10 +22,6 @@ type (
value []byte
}
concatEnum struct {
current enumerator
second enumerator
}
)
type (
@ -39,11 +35,6 @@ type (
m []stackitem.MapElement
}
concatIter struct {
current iterator
second iterator
}
keysWrapper struct {
iter iterator
}
@ -87,36 +78,6 @@ func (a *byteArrayWrapper) Key() stackitem.Item {
return stackitem.Make(a.index)
}
func (c *concatEnum) Next() bool {
if c.current.Next() {
return true
}
c.current = c.second
return c.current.Next()
}
func (c *concatEnum) Value() stackitem.Item {
return c.current.Value()
}
func (i *concatIter) Next() bool {
if i.current.Next() {
return true
}
i.current = i.second
return i.second.Next()
}
func (i *concatIter) Value() stackitem.Item {
return i.current.Value()
}
func (i *concatIter) Key() stackitem.Item {
return i.current.Key()
}
func (m *mapWrapper) Next() bool {
if next := m.index + 1; next < len(m.m) {
m.index = next

View file

@ -545,50 +545,6 @@ func TestIteratorCreate(t *testing.T) {
})
}
func testIterableConcat(t *testing.T, typ string) {
isIter := typ == "Iterator"
prog := getSyscallProg("System." + typ + ".Create")
prog = append(prog, byte(opcode.SWAP))
prog = append(prog, getSyscallProg("System."+typ+".Create")...)
prog = append(prog, getSyscallProg("System."+typ+".Concat")...)
prog = append(prog, getEnumeratorProg(3, isIter)...)
vm := load(prog)
arr := []stackitem.Item{
stackitem.NewBool(false),
stackitem.NewBigInteger(big.NewInt(123)),
stackitem.NewMap(),
}
vm.estack.Push(&Element{value: stackitem.NewArray(arr[:1])})
vm.estack.Push(&Element{value: stackitem.NewArray(arr[1:])})
runVM(t, vm)
if isIter {
// Yes, this is how iterators are concatenated in reference VM
// https://github.com/neo-project/neo/blob/master-2.x/neo.UnitTests/UT_ConcatenatedIterator.cs#L54
checkEnumeratorStack(t, vm, []stackitem.Item{
stackitem.Make(1), arr[2], stackitem.NewBool(true),
stackitem.Make(0), arr[1], stackitem.NewBool(true),
stackitem.Make(0), arr[0], stackitem.NewBool(true),
})
} else {
checkEnumeratorStack(t, vm, []stackitem.Item{
arr[2], stackitem.NewBool(true),
arr[1], stackitem.NewBool(true),
arr[0], stackitem.NewBool(true),
})
}
}
func TestEnumeratorConcat(t *testing.T) {
testIterableConcat(t, "Enumerator")
}
func TestIteratorConcat(t *testing.T) {
testIterableConcat(t, "Iterator")
}
func TestIteratorKeys(t *testing.T) {
prog := getSyscallProg(interopnames.SystemIteratorCreate)
prog = append(prog, getSyscallProg(interopnames.SystemIteratorKeys)...)