Support IteratorChainsByPrefix method #70
4 changed files with 49 additions and 1 deletions
|
@ -4,4 +4,5 @@ safemethods:
|
|||
- "listChains"
|
||||
- "getChain"
|
||||
- "listChainsByPrefix"
|
||||
- "version"
|
||||
- "iteratorChainsByPrefix"
|
||||
- "version"
|
|
@ -150,3 +150,9 @@ func ListChainsByPrefix(entity Kind, entityName string, prefix []byte) [][]byte
|
|||
|
||||
return result
|
||||
}
|
||||
|
||||
func IteratorChainsByPrefix(entity Kind, entityName string, prefix []byte) iterator.Iterator {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
keyPrefix := storageKey(entity, entityName, prefix)
|
||||
return storage.Find(ctx, keyPrefix, storage.ValuesOnly)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
package ape
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
|
||||
|
@ -15,6 +16,9 @@ import (
|
|||
// Invoker is used by ContractReader to call various safe methods.
|
||||
type Invoker interface {
|
||||
Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error)
|
||||
CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error)
|
||||
TerminateSession(sessionID uuid.UUID) error
|
||||
TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error)
|
||||
}
|
||||
|
||||
// Actor is used by Contract to call state-changing methods.
|
||||
|
@ -62,6 +66,20 @@ func (c *ContractReader) GetChain(entity *big.Int, entityName string, name []byt
|
|||
return unwrap.Bytes(c.invoker.Call(c.hash, "getChain", entity, entityName, name))
|
||||
}
|
||||
|
||||
// IteratorChainsByPrefix invokes `iteratorChainsByPrefix` method of contract.
|
||||
func (c *ContractReader) IteratorChainsByPrefix(entity *big.Int, entityName string, prefix []byte) (uuid.UUID, result.Iterator, error) {
|
||||
return unwrap.SessionIterator(c.invoker.Call(c.hash, "iteratorChainsByPrefix", entity, entityName, prefix))
|
||||
}
|
||||
|
||||
// IteratorChainsByPrefixExpanded is similar to IteratorChainsByPrefix (uses the same contract
|
||||
// method), but can be useful if the server used doesn't support sessions and
|
||||
// doesn't expand iterators. It creates a script that will get the specified
|
||||
// number of result items from the iterator right in the VM and return them to
|
||||
// you. It's only limited by VM stack and GAS available for RPC invocations.
|
||||
func (c *ContractReader) IteratorChainsByPrefixExpanded(entity *big.Int, entityName string, prefix []byte, _numOfIteratorItems int) ([]stackitem.Item, error) {
|
||||
return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "iteratorChainsByPrefix", _numOfIteratorItems, entity, entityName, prefix))
|
||||
}
|
||||
|
||||
// ListChains invokes `listChains` method of contract.
|
||||
func (c *ContractReader) ListChains(namespace string, container string, name []byte) ([]stackitem.Item, error) {
|
||||
return unwrap.Array(c.invoker.Call(c.hash, "listChains", namespace, container, name))
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/policy"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/storage"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
|
@ -56,6 +57,9 @@ func TestPolicy(t *testing.T) {
|
|||
checkChainsByPrefix(t, e, policy.Container, "cnr1", "", [][]byte{p2, p33})
|
||||
checkChainsByPrefix(t, e, policy.IAM, "", "", nil)
|
||||
|
||||
checkChainsIteratorByPrefix(t, e, policy.Container, "cnr1", "ingress:myrule3", [][]byte{p33})
|
||||
checkChainsIteratorByPrefix(t, e, policy.Container, "cnr1", "ingress", [][]byte{p2, p33})
|
||||
|
||||
t.Run("removal", func(t *testing.T) {
|
||||
t.Run("wrong name", func(t *testing.T) {
|
||||
e.Invoke(t, stackitem.Null{}, "removeChain", policy.Namespace, "mynamespace", "ingress")
|
||||
|
@ -103,6 +107,25 @@ func checkChainsByPrefix(t *testing.T, e *neotest.ContractInvoker, kind byte, en
|
|||
checksChainsOnStack(t, s, expected)
|
||||
}
|
||||
|
||||
func checkChainsIteratorByPrefix(t *testing.T, e *neotest.ContractInvoker, kind byte, entityName, prefix string, expected [][]byte) {
|
||||
s, err := e.TestInvoke(t, "iteratorChainsByPrefix", kind, entityName, prefix)
|
||||
require.NoError(t, err)
|
||||
|
||||
if s.Len() == 0 {
|
||||
t.Fatal("Stack is empty")
|
||||
}
|
||||
|
||||
iteratorItem := s.Pop().Value().(*storage.Iterator)
|
||||
policys := iteratorToArray(iteratorItem)
|
||||
require.Equal(t, len(expected), len(policys))
|
||||
|
||||
for i := range expected {
|
||||
bytesPolicy, err := policys[i].TryBytes()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected[i], bytesPolicy)
|
||||
}
|
||||
}
|
||||
|
||||
func checksChainsOnStack(t *testing.T, s *vm.Stack, expected [][]byte) {
|
||||
require.Equal(t, 1, s.Len())
|
||||
|
||||
|
|
Loading…
Reference in a new issue