From 8fb67615f8793853be84db98188b7f85f5ad0515 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 29 May 2020 11:02:26 +0300 Subject: [PATCH] core: sort results of Storage.Find and NEO.getRegisterValidators Closes #909 We need to match elements order with C# implementation. --- pkg/core/interop_neo.go | 16 +++++++++------- pkg/core/interop_neo_test.go | 28 +++++++++++++++++++++++++++- pkg/core/native/native_neo.go | 2 ++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/pkg/core/interop_neo.go b/pkg/core/interop_neo.go index b5bfea395..74b5e364e 100644 --- a/pkg/core/interop_neo.go +++ b/pkg/core/interop_neo.go @@ -1,10 +1,11 @@ package core import ( + "bytes" "errors" "fmt" "math" - "strings" + "sort" "github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/interop/runtime" @@ -422,19 +423,20 @@ func storageFind(ic *interop.Context, v *vm.VM) error { if err != nil { return err } - prefix := string(v.Estack().Pop().Bytes()) - siMap, err := ic.DAO.GetStorageItems(stc.ScriptHash) + prefix := v.Estack().Pop().Bytes() + siMap, err := ic.DAO.GetStorageItemsWithPrefix(stc.ScriptHash, prefix) if err != nil { return err } filteredMap := vm.NewMapItem() for k, v := range siMap { - if strings.HasPrefix(k, prefix) { - filteredMap.Add(vm.NewByteArrayItem([]byte(k)), - vm.NewByteArrayItem(v.Value)) - } + filteredMap.Add(vm.NewByteArrayItem(append(prefix, []byte(k)...)), vm.NewByteArrayItem(v.Value)) } + sort.Slice(filteredMap.Value().([]vm.MapElement), func(i, j int) bool { + return bytes.Compare(filteredMap.Value().([]vm.MapElement)[i].Key.Value().([]byte), + filteredMap.Value().([]vm.MapElement)[j].Key.Value().([]byte)) == -1 + }) item := vm.NewMapIterator(filteredMap) v.Estack().PushVal(item) diff --git a/pkg/core/interop_neo_test.go b/pkg/core/interop_neo_test.go index 24835af64..e9ec0b2fe 100644 --- a/pkg/core/interop_neo_test.go +++ b/pkg/core/interop_neo_test.go @@ -51,7 +51,7 @@ func TestStorageFind(t *testing.T) { v, contractState, context, chain := createVMAndContractState(t) defer chain.Close() - skeys := [][]byte{{0x01, 0x02}, {0x02, 0x01}} + skeys := [][]byte{{0x01, 0x02}, {0x02, 0x01}, {0x01, 0x01}} items := []*state.StorageItem{ { Value: []byte{0x01, 0x02, 0x03, 0x04}, @@ -59,6 +59,9 @@ func TestStorageFind(t *testing.T) { { Value: []byte{0x04, 0x03, 0x02, 0x01}, }, + { + Value: []byte{0x03, 0x04, 0x05, 0x06}, + }, } require.NoError(t, context.DAO.PutContractState(contractState)) @@ -83,6 +86,18 @@ func TestStorageFind(t *testing.T) { require.NoError(t, enumerator.Next(context, v)) require.True(t, v.Estack().Pop().Bool()) + v.Estack().PushVal(iter) + require.NoError(t, iterator.Key(context, v)) + require.Equal(t, []byte{0x01, 0x01}, v.Estack().Pop().Bytes()) + + v.Estack().PushVal(iter) + require.NoError(t, enumerator.Value(context, v)) + require.Equal(t, []byte{0x03, 0x04, 0x05, 0x06}, v.Estack().Pop().Bytes()) + + v.Estack().PushVal(iter) + require.NoError(t, enumerator.Next(context, v)) + require.True(t, v.Estack().Pop().Bool()) + v.Estack().PushVal(iter) require.NoError(t, iterator.Key(context, v)) require.Equal(t, []byte{0x01, 0x02}, v.Estack().Pop().Bytes()) @@ -96,6 +111,17 @@ func TestStorageFind(t *testing.T) { require.False(t, v.Estack().Pop().Bool()) }) + t.Run("normal invocation, empty result", func(t *testing.T) { + v.Estack().PushVal([]byte{0x03}) + v.Estack().PushVal(vm.NewInteropItem(&StorageContext{ScriptHash: scriptHash})) + + err := storageFind(context, v) + require.NoError(t, err) + + require.NoError(t, enumerator.Next(context, v)) + require.False(t, v.Estack().Pop().Bool()) + }) + t.Run("invalid type for StorageContext", func(t *testing.T) { v.Estack().PushVal([]byte{0x01}) v.Estack().PushVal(vm.NewInteropItem(nil)) diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index 67bc5b832..aca59e0fb 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -3,6 +3,7 @@ package native import ( "math/big" "sort" + "strings" "github.com/nspcc-dev/neo-go/pkg/core/blockchainer" "github.com/nspcc-dev/neo-go/pkg/core/dao" @@ -344,6 +345,7 @@ func (n *NEO) getRegisteredValidators(d dao.DAO) ([]keyWithVotes, error) { } arr = append(arr, keyWithVotes{key, &votes.Balance}) } + sort.Slice(arr, func(i, j int) bool { return strings.Compare(arr[i].Key, arr[j].Key) == -1 }) return arr, nil }