[#174] subnet: Add NodeAllowed method

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
Pavel Karpy 2021-11-22 21:59:49 +03:00 committed by LeL
parent 4b47bfadcd
commit b5db977e62
2 changed files with 47 additions and 6 deletions

View file

@ -7,7 +7,6 @@ import (
"github.com/nspcc-dev/neo-go/pkg/interop/native/management" "github.com/nspcc-dev/neo-go/pkg/interop/native/management"
"github.com/nspcc-dev/neo-go/pkg/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
"github.com/nspcc-dev/neo-go/pkg/interop/storage" "github.com/nspcc-dev/neo-go/pkg/interop/storage"
"github.com/nspcc-dev/neo-go/pkg/interop/util"
"github.com/nspcc-dev/neofs-contract/common" "github.com/nspcc-dev/neofs-contract/common"
) )
@ -18,6 +17,8 @@ const (
ErrInvalidOwner = "invalid owner" ErrInvalidOwner = "invalid owner"
// ErrInvalidAdmin is thrown when admin has invalid format. // ErrInvalidAdmin is thrown when admin has invalid format.
ErrInvalidAdmin = "invalid administrator" ErrInvalidAdmin = "invalid administrator"
// ErrInvalidNode is thrown when node has invalid format.
ErrInvalidNode = "invalid node key"
// ErrAlreadyExists is thrown when id already exists. // ErrAlreadyExists is thrown when id already exists.
ErrAlreadyExists = "subnet id already exists" ErrAlreadyExists = "subnet id already exists"
// ErrSubNotExist is thrown when id doesn't exist. // ErrSubNotExist is thrown when id doesn't exist.
@ -214,7 +215,7 @@ func RemoveNodeAdmin(subnetID []byte, adminKey interop.PublicKey) {
// only. // only.
func AddNode(subnetID []byte, node interop.PublicKey) { func AddNode(subnetID []byte, node interop.PublicKey) {
if len(node) != interop.PublicKeyCompressedLen { if len(node) != interop.PublicKeyCompressedLen {
panic("addNode: " + ErrInvalidAdmin) panic("addNode: " + ErrInvalidNode)
} }
ctx := storage.GetContext() ctx := storage.GetContext()
@ -261,7 +262,7 @@ func AddNode(subnetID []byte, node interop.PublicKey) {
// only. // only.
func RemoveNode(subnetID []byte, node interop.PublicKey) { func RemoveNode(subnetID []byte, node interop.PublicKey) {
if len(node) != interop.PublicKeyCompressedLen { if len(node) != interop.PublicKeyCompressedLen {
panic("removeNode: " + ErrInvalidAdmin) panic("removeNode: " + ErrInvalidNode)
} }
ctx := storage.GetContext() ctx := storage.GetContext()
@ -305,6 +306,27 @@ func RemoveNode(subnetID []byte, node interop.PublicKey) {
runtime.Notify("NodeRemove", subnetID, node) runtime.Notify("NodeRemove", subnetID, node)
} }
// NodeAllowed checks if node is included in the
// specified subnet or not.
func NodeAllowed(subnetID []byte, node interop.PublicKey) bool {
if len(node) != interop.PublicKeyCompressedLen {
panic("nodeAllowed: " + ErrInvalidNode)
}
ctx := storage.GetReadOnlyContext()
stKey := append([]byte{ownerPrefix}, subnetID...)
rawOwner := storage.Get(ctx, stKey)
if rawOwner == nil {
panic("nodeAllowed: " + ErrSubNotExist)
}
stKey[0] = nodePrefix
return storage.Get(ctx, append(stKey, node...)) != nil
}
// Version returns version of the contract. // Version returns version of the contract.
func Version() int { func Version() int {
return common.Version return common.Version
@ -316,7 +338,7 @@ func keyInList(ctx storage.Context, searchedKey interop.PublicKey, prefix []byte
iter := storage.Find(ctx, prefix, storage.KeysOnly) iter := storage.Find(ctx, prefix, storage.KeysOnly)
for iterator.Next(iter) { for iterator.Next(iter) {
key := iterator.Value(iter).([]byte) key := iterator.Value(iter).([]byte)
if util.Equals(string(key[prefixLen:]), string(searchedKey)) { if common.BytesEqual(key[prefixLen:], searchedKey) {
return true return true
} }
} }

View file

@ -136,7 +136,7 @@ func TestSubnet_AddNode(t *testing.T) {
const method = "addNode" const method = "addNode"
cOwn := e.WithSigners(owner) cOwn := e.WithSigners(owner)
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrInvalidAdmin, method, id, nodePub[1:]) cOwn.InvokeFail(t, method+errSeparator+subnet.ErrInvalidNode, method, id, nodePub[1:])
cOwn.Invoke(t, stackitem.Null{}, method, id, nodePub) cOwn.Invoke(t, stackitem.Null{}, method, id, nodePub)
cOwn.InvokeFail(t, method+errSeparator+"node has already been added", method, id, nodePub) cOwn.InvokeFail(t, method+errSeparator+"node has already been added", method, id, nodePub)
@ -158,7 +158,7 @@ func TestSubnet_RemoveNode(t *testing.T) {
const method = "removeNode" const method = "removeNode"
cOwn := e.WithSigners(owner) cOwn := e.WithSigners(owner)
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrInvalidAdmin, method, id, nodePub[1:]) cOwn.InvokeFail(t, method+errSeparator+subnet.ErrInvalidNode, method, id, nodePub[1:])
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrNodeNotExist, method, id, nodePub) cOwn.InvokeFail(t, method+errSeparator+subnet.ErrNodeNotExist, method, id, nodePub)
cOwn.Invoke(t, stackitem.Null{}, "addNode", id, nodePub) cOwn.Invoke(t, stackitem.Null{}, "addNode", id, nodePub)
@ -170,6 +170,25 @@ func TestSubnet_RemoveNode(t *testing.T) {
cAdm.InvokeFail(t, method+errSeparator+subnet.ErrNodeNotExist, method, id, nodePub) cAdm.InvokeFail(t, method+errSeparator+subnet.ErrNodeNotExist, method, id, nodePub)
} }
func TestSubnet_NodeAllowed(t *testing.T) {
e := newSubnetInvoker(t)
id, owner := createSubnet(t, e)
node := e.NewAccount(t)
nodePub, ok := vm.ParseSignatureContract(node.Script())
require.True(t, ok)
const method = "nodeAllowed"
cOwn := e.WithSigners(owner)
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrInvalidNode, method, id, nodePub[1:])
cOwn.Invoke(t, stackitem.NewBool(false), method, id, nodePub)
cOwn.Invoke(t, stackitem.Null{}, "addNode", id, nodePub)
cOwn.Invoke(t, stackitem.NewBool(true), method, id, nodePub)
}
func createSubnet(t *testing.T, e *neotest.ContractInvoker) (id []byte, owner neotest.Signer) { func createSubnet(t *testing.T, e *neotest.ContractInvoker) (id []byte, owner neotest.Signer) {
var ( var (
ok bool ok bool