From 5cc34f98e94cb44f5b0308322a9dbb1b1b259501 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Fri, 17 Nov 2023 11:06:08 +0300 Subject: [PATCH] [#51] policy: Support Get and ListByPrefix methods Signed-off-by: Denis Kirillov --- policy/config.yml | 2 +- policy/policy_contract.go | 26 ++++++++++++++++++++++++++ rpcclient/policy/client.go | 10 ++++++++++ tests/policy_test.go | 25 +++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/policy/config.yml b/policy/config.yml index 4b43ec9..b9a62f8 100644 --- a/policy/config.yml +++ b/policy/config.yml @@ -1,2 +1,2 @@ name: "APE" -safemethods: ["listChains"] +safemethods: ["listChains","getChain","listChainsByPrefix"] diff --git a/policy/policy_contract.go b/policy/policy_contract.go index c3fc80e..dc1a71f 100644 --- a/policy/policy_contract.go +++ b/policy/policy_contract.go @@ -35,6 +35,17 @@ func AddChain(entity Kind, entityName, name string, chain []byte) { storage.Put(ctx, key, chain) } +func GetChain(entity Kind, entityName, name string) []byte { + ctx := storage.GetReadOnlyContext() + key := storageKey(entity, entityName, name) + data := storage.Get(ctx, key).([]byte) + if data == nil { + panic("not found") + } + + return data +} + func RemoveChain(entity Kind, entityName string, name string) { common.CheckAlphabetWitness() @@ -77,3 +88,18 @@ func ListChains(namespace, container, name string) [][]byte { return result } + +// ListChainsByPrefix list all chains for the provided kind and entity by prefix. +func ListChainsByPrefix(entity Kind, entityName, prefix string) [][]byte { + ctx := storage.GetReadOnlyContext() + + result := [][]byte{} + + keyPrefix := storageKey(entity, entityName, prefix) + it := storage.Find(ctx, keyPrefix, storage.ValuesOnly) + for iterator.Next(it) { + result = append(result, iterator.Value(it).([]byte)) + } + + return result +} diff --git a/rpcclient/policy/client.go b/rpcclient/policy/client.go index 1c48c99..8ca373b 100644 --- a/rpcclient/policy/client.go +++ b/rpcclient/policy/client.go @@ -52,11 +52,21 @@ func New(actor Actor, hash util.Uint160) *Contract { return &Contract{ContractReader{actor, hash}, actor, hash} } +// GetChain invokes `getChain` method of contract. +func (c *ContractReader) GetChain(entity *big.Int, entityName string, name string) ([]byte, error) { + return unwrap.Bytes(c.invoker.Call(c.hash, "getChain", entity, entityName, name)) +} + // ListChains invokes `listChains` method of contract. func (c *ContractReader) ListChains(namespace string, container string, name string) ([]stackitem.Item, error) { return unwrap.Array(c.invoker.Call(c.hash, "listChains", namespace, container, name)) } +// ListChainsByPrefix invokes `listChainsByPrefix` method of contract. +func (c *ContractReader) ListChainsByPrefix(entity *big.Int, entityName string, prefix string) ([]stackitem.Item, error) { + return unwrap.Array(c.invoker.Call(c.hash, "listChainsByPrefix", entity, entityName, prefix)) +} + // AddChain creates a transaction invoking `addChain` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. diff --git a/tests/policy_test.go b/tests/policy_test.go index 10a74db..56a41b8 100644 --- a/tests/policy_test.go +++ b/tests/policy_test.go @@ -1,12 +1,14 @@ package tests import ( + "bytes" "path" "testing" "git.frostfs.info/TrueCloudLab/frostfs-contract/policy" "github.com/nspcc-dev/neo-go/pkg/neotest" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/require" ) @@ -49,7 +51,10 @@ func TestPolicy(t *testing.T) { checkChains(t, e, "mynamespace", "cnr1", "ingress", [][]byte{p1, p2, p3}) e.Invoke(t, stackitem.Null{}, "addChain", policy.Container, "cnr1", "ingress:myrule3", p33) + checkChain(t, e, policy.Container, "cnr1", "ingress:myrule3", p33) checkChains(t, e, "mynamespace", "cnr1", "ingress", [][]byte{p1, p2, p33}) // Override chain. + checkChainsByPrefix(t, e, policy.Container, "cnr1", "", [][]byte{p2, p33}) + checkChainsByPrefix(t, e, policy.IAM, "", "", nil) t.Run("removal", func(t *testing.T) { t.Run("wrong name", func(t *testing.T) { @@ -70,6 +75,18 @@ func TestPolicy(t *testing.T) { func checkChains(t *testing.T, e *neotest.ContractInvoker, namespace, container, name string, expected [][]byte) { s, err := e.TestInvoke(t, "listChains", namespace, container, name) require.NoError(t, err) + + checksChainsOnStack(t, s, expected) +} + +func checkChainsByPrefix(t *testing.T, e *neotest.ContractInvoker, kind byte, entityName, prefix string, expected [][]byte) { + s, err := e.TestInvoke(t, "listChainsByPrefix", kind, entityName, prefix) + require.NoError(t, err) + + checksChainsOnStack(t, s, expected) +} + +func checksChainsOnStack(t *testing.T, s *vm.Stack, expected [][]byte) { require.Equal(t, 1, s.Len()) if len(expected) == 0 { @@ -89,3 +106,11 @@ func checkChains(t *testing.T, e *neotest.ContractInvoker, namespace, container, require.ElementsMatch(t, expected, actual) } + +func checkChain(t *testing.T, e *neotest.ContractInvoker, kind byte, entityName, name string, expected []byte) { + s, err := e.TestInvoke(t, "getChain", kind, entityName, name) + require.NoError(t, err) + require.Equal(t, 1, s.Len()) + + require.True(t, bytes.Equal(expected, s.Pop().Bytes())) +}