mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-27 15:42:54 +00:00
parent
e36e71ffbd
commit
d04b000748
12 changed files with 2 additions and 167 deletions
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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{}
|
||||
}
|
||||
|
|
|
@ -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{} {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)...)
|
||||
|
|
Loading…
Reference in a new issue