forked from TrueCloudLab/neoneo-go
interop: strip full prefix in System.Storage.Find
This commit is contained in:
parent
933743ce87
commit
ffaae0f773
4 changed files with 34 additions and 24 deletions
|
@ -21,14 +21,16 @@ type Iterator struct {
|
||||||
m []stackitem.MapElement
|
m []stackitem.MapElement
|
||||||
opts int64
|
opts int64
|
||||||
index int
|
index int
|
||||||
|
prefixSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIterator creates a new Iterator with given options for a given map.
|
// NewIterator creates a new Iterator with given options for a given map.
|
||||||
func NewIterator(m *stackitem.Map, opts int64) *Iterator {
|
func NewIterator(m *stackitem.Map, prefix int, opts int64) *Iterator {
|
||||||
return &Iterator{
|
return &Iterator{
|
||||||
m: m.Value().([]stackitem.MapElement),
|
m: m.Value().([]stackitem.MapElement),
|
||||||
opts: opts,
|
opts: opts,
|
||||||
index: -1,
|
index: -1,
|
||||||
|
prefixSize: prefix,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +48,7 @@ func (s *Iterator) Next() bool {
|
||||||
func (s *Iterator) Value() stackitem.Item {
|
func (s *Iterator) Value() stackitem.Item {
|
||||||
key := s.m[s.index].Key.Value().([]byte)
|
key := s.m[s.index].Key.Value().([]byte)
|
||||||
if s.opts&FindRemovePrefix != 0 {
|
if s.opts&FindRemovePrefix != 0 {
|
||||||
key = key[1:]
|
key = key[s.prefixSize:]
|
||||||
}
|
}
|
||||||
if s.opts&FindKeysOnly != 0 {
|
if s.opts&FindKeysOnly != 0 {
|
||||||
return stackitem.NewByteArray(key)
|
return stackitem.NewByteArray(key)
|
||||||
|
|
|
@ -59,7 +59,7 @@ func storageFind(ic *interop.Context) error {
|
||||||
filteredMap.Value().([]stackitem.MapElement)[j].Key.Value().([]byte)) == -1
|
filteredMap.Value().([]stackitem.MapElement)[j].Key.Value().([]byte)) == -1
|
||||||
})
|
})
|
||||||
|
|
||||||
item := storage.NewIterator(filteredMap, opts)
|
item := storage.NewIterator(filteredMap, len(prefix), opts)
|
||||||
ic.VM.Estack().PushVal(stackitem.NewInterop(item))
|
ic.VM.Estack().PushVal(stackitem.NewInterop(item))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -49,7 +49,9 @@ func TestStorageFind(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
skeys := [][]byte{{0x01, 0x02}, {0x02, 0x01}, {0x01, 0x01},
|
skeys := [][]byte{{0x01, 0x02}, {0x02, 0x01}, {0x01, 0x01},
|
||||||
{0x04, 0x00}, {0x05, 0x00}, {0x06}, {0x07}, {0x08}}
|
{0x04, 0x00}, {0x05, 0x00}, {0x06}, {0x07}, {0x08},
|
||||||
|
{0x09, 0x12, 0x34}, {0x09, 0x12, 0x56},
|
||||||
|
}
|
||||||
items := []state.StorageItem{
|
items := []state.StorageItem{
|
||||||
[]byte{0x01, 0x02, 0x03, 0x04},
|
[]byte{0x01, 0x02, 0x03, 0x04},
|
||||||
[]byte{0x04, 0x03, 0x02, 0x01},
|
[]byte{0x04, 0x03, 0x02, 0x01},
|
||||||
|
@ -59,6 +61,8 @@ func TestStorageFind(t *testing.T) {
|
||||||
rawArr,
|
rawArr,
|
||||||
rawArr0,
|
rawArr0,
|
||||||
rawArr1,
|
rawArr1,
|
||||||
|
[]byte{111},
|
||||||
|
[]byte{222},
|
||||||
}
|
}
|
||||||
|
|
||||||
require.NoError(t, chain.contracts.Management.PutContractState(chain.dao, contractState))
|
require.NoError(t, chain.contracts.Management.PutContractState(chain.dao, contractState))
|
||||||
|
@ -70,9 +74,9 @@ func TestStorageFind(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
testFind := func(t *testing.T, prefix byte, opts int64, expected []stackitem.Item) {
|
testFind := func(t *testing.T, prefix []byte, opts int64, expected []stackitem.Item) {
|
||||||
v.Estack().PushVal(opts)
|
v.Estack().PushVal(opts)
|
||||||
v.Estack().PushVal([]byte{prefix})
|
v.Estack().PushVal(prefix)
|
||||||
v.Estack().PushVal(stackitem.NewInterop(&StorageContext{ID: id}))
|
v.Estack().PushVal(stackitem.NewInterop(&StorageContext{ID: id}))
|
||||||
|
|
||||||
err := storageFind(context)
|
err := storageFind(context)
|
||||||
|
@ -101,7 +105,7 @@ func TestStorageFind(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("normal invocation", func(t *testing.T) {
|
t.Run("normal invocation", func(t *testing.T) {
|
||||||
testFind(t, 0x01, istorage.FindDefault, []stackitem.Item{
|
testFind(t, []byte{0x01}, istorage.FindDefault, []stackitem.Item{
|
||||||
stackitem.NewStruct([]stackitem.Item{
|
stackitem.NewStruct([]stackitem.Item{
|
||||||
stackitem.NewByteArray(skeys[2]),
|
stackitem.NewByteArray(skeys[2]),
|
||||||
stackitem.NewByteArray(items[2]),
|
stackitem.NewByteArray(items[2]),
|
||||||
|
@ -114,25 +118,29 @@ func TestStorageFind(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("keys only", func(t *testing.T) {
|
t.Run("keys only", func(t *testing.T) {
|
||||||
testFind(t, 0x01, istorage.FindKeysOnly, []stackitem.Item{
|
testFind(t, []byte{0x01}, istorage.FindKeysOnly, []stackitem.Item{
|
||||||
stackitem.NewByteArray(skeys[2]),
|
stackitem.NewByteArray(skeys[2]),
|
||||||
stackitem.NewByteArray(skeys[0]),
|
stackitem.NewByteArray(skeys[0]),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
t.Run("remove prefix", func(t *testing.T) {
|
t.Run("remove prefix", func(t *testing.T) {
|
||||||
testFind(t, 0x01, istorage.FindKeysOnly|istorage.FindRemovePrefix, []stackitem.Item{
|
testFind(t, []byte{0x01}, istorage.FindKeysOnly|istorage.FindRemovePrefix, []stackitem.Item{
|
||||||
stackitem.NewByteArray(skeys[2][1:]),
|
stackitem.NewByteArray(skeys[2][1:]),
|
||||||
stackitem.NewByteArray(skeys[0][1:]),
|
stackitem.NewByteArray(skeys[0][1:]),
|
||||||
})
|
})
|
||||||
|
testFind(t, []byte{0x09, 0x12}, istorage.FindKeysOnly|istorage.FindRemovePrefix, []stackitem.Item{
|
||||||
|
stackitem.NewByteArray(skeys[8][2:]),
|
||||||
|
stackitem.NewByteArray(skeys[9][2:]),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
t.Run("values only", func(t *testing.T) {
|
t.Run("values only", func(t *testing.T) {
|
||||||
testFind(t, 0x01, istorage.FindValuesOnly, []stackitem.Item{
|
testFind(t, []byte{0x01}, istorage.FindValuesOnly, []stackitem.Item{
|
||||||
stackitem.NewByteArray(items[2]),
|
stackitem.NewByteArray(items[2]),
|
||||||
stackitem.NewByteArray(items[0]),
|
stackitem.NewByteArray(items[0]),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
t.Run("deserialize values", func(t *testing.T) {
|
t.Run("deserialize values", func(t *testing.T) {
|
||||||
testFind(t, 0x04, istorage.FindValuesOnly|istorage.FindDeserialize, []stackitem.Item{
|
testFind(t, []byte{0x04}, istorage.FindValuesOnly|istorage.FindDeserialize, []stackitem.Item{
|
||||||
stackitem.NewByteArray(items[3][2:]),
|
stackitem.NewByteArray(items[3][2:]),
|
||||||
})
|
})
|
||||||
t.Run("invalid", func(t *testing.T) {
|
t.Run("invalid", func(t *testing.T) {
|
||||||
|
@ -153,21 +161,21 @@ func TestStorageFind(t *testing.T) {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
t.Run("PickN", func(t *testing.T) {
|
t.Run("PickN", func(t *testing.T) {
|
||||||
testFind(t, 0x06, istorage.FindPick0|istorage.FindValuesOnly|istorage.FindDeserialize, arr[:1])
|
testFind(t, []byte{0x06}, istorage.FindPick0|istorage.FindValuesOnly|istorage.FindDeserialize, arr[:1])
|
||||||
testFind(t, 0x06, istorage.FindPick1|istorage.FindValuesOnly|istorage.FindDeserialize, arr[1:2])
|
testFind(t, []byte{0x06}, istorage.FindPick1|istorage.FindValuesOnly|istorage.FindDeserialize, arr[1:2])
|
||||||
// Array with 0 elements.
|
// Array with 0 elements.
|
||||||
testFind(t, 0x07, istorage.FindPick0|istorage.FindValuesOnly|istorage.FindDeserialize,
|
testFind(t, []byte{0x07}, istorage.FindPick0|istorage.FindValuesOnly|istorage.FindDeserialize,
|
||||||
[]stackitem.Item{nil})
|
[]stackitem.Item{nil})
|
||||||
// Array with 1 element.
|
// Array with 1 element.
|
||||||
testFind(t, 0x08, istorage.FindPick1|istorage.FindValuesOnly|istorage.FindDeserialize,
|
testFind(t, []byte{0x08}, istorage.FindPick1|istorage.FindValuesOnly|istorage.FindDeserialize,
|
||||||
[]stackitem.Item{nil})
|
[]stackitem.Item{nil})
|
||||||
// Not an array, but serialized ByteArray.
|
// Not an array, but serialized ByteArray.
|
||||||
testFind(t, 0x04, istorage.FindPick1|istorage.FindValuesOnly|istorage.FindDeserialize,
|
testFind(t, []byte{0x04}, istorage.FindPick1|istorage.FindValuesOnly|istorage.FindDeserialize,
|
||||||
[]stackitem.Item{nil})
|
[]stackitem.Item{nil})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("normal invocation, empty result", func(t *testing.T) {
|
t.Run("normal invocation, empty result", func(t *testing.T) {
|
||||||
testFind(t, 0x03, istorage.FindDefault, nil)
|
testFind(t, []byte{0x03}, istorage.FindDefault, nil)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("invalid options", func(t *testing.T) {
|
t.Run("invalid options", func(t *testing.T) {
|
||||||
|
|
|
@ -229,7 +229,7 @@ func (n *nonfungible) tokens(ic *interop.Context, args []stackitem.Item) stackit
|
||||||
return bytes.Compare(filteredMap.Value().([]stackitem.MapElement)[i].Key.Value().([]byte),
|
return bytes.Compare(filteredMap.Value().([]stackitem.MapElement)[i].Key.Value().([]byte),
|
||||||
filteredMap.Value().([]stackitem.MapElement)[j].Key.Value().([]byte)) == -1
|
filteredMap.Value().([]stackitem.MapElement)[j].Key.Value().([]byte)) == -1
|
||||||
})
|
})
|
||||||
iter := istorage.NewIterator(filteredMap, istorage.FindValuesOnly|istorage.FindDeserialize|istorage.FindPick1)
|
iter := istorage.NewIterator(filteredMap, 1, istorage.FindValuesOnly|istorage.FindDeserialize|istorage.FindPick1)
|
||||||
return stackitem.NewInterop(iter)
|
return stackitem.NewInterop(iter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue