[#174] subnet: Add AddClientAdmin
method
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
parent
b5db977e62
commit
0d45d83450
2 changed files with 72 additions and 21 deletions
|
@ -17,12 +17,12 @@ 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.
|
||||||
ErrSubNotExist = "subnet id doesn't exist"
|
ErrSubNotExist = "subnet id doesn't exist"
|
||||||
|
// ErrInvalidNode is thrown when node has invalid format.
|
||||||
|
ErrInvalidNode = "invalid node key"
|
||||||
// ErrNodeAdmNotExist is thrown when node admin is not found.
|
// ErrNodeAdmNotExist is thrown when node admin is not found.
|
||||||
ErrNodeAdmNotExist = "node admin not found"
|
ErrNodeAdmNotExist = "node admin not found"
|
||||||
// ErrNodeNotExist is thrown when node is not found.
|
// ErrNodeNotExist is thrown when node is not found.
|
||||||
|
@ -176,7 +176,7 @@ func AddNodeAdmin(subnetID []byte, adminKey interop.PublicKey) {
|
||||||
panic("addNodeAdmin: node admin has already been added")
|
panic("addNodeAdmin: node admin has already been added")
|
||||||
}
|
}
|
||||||
|
|
||||||
storage.Put(ctx, append(stKey, adminKey...), []byte{1})
|
putKeyInList(ctx, adminKey, stKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveNodeAdmin removes node administrator from the specified subnetwork.
|
// RemoveNodeAdmin removes node administrator from the specified subnetwork.
|
||||||
|
@ -188,9 +188,9 @@ func RemoveNodeAdmin(subnetID []byte, adminKey interop.PublicKey) {
|
||||||
|
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
|
||||||
stOwnerKey := append([]byte{ownerPrefix}, subnetID...)
|
stKey := append([]byte{ownerPrefix}, subnetID...)
|
||||||
|
|
||||||
rawOwner := storage.Get(ctx, stOwnerKey)
|
rawOwner := storage.Get(ctx, stKey)
|
||||||
if rawOwner == nil {
|
if rawOwner == nil {
|
||||||
panic("removeNodeAdmin: " + ErrSubNotExist)
|
panic("removeNodeAdmin: " + ErrSubNotExist)
|
||||||
}
|
}
|
||||||
|
@ -200,14 +200,13 @@ func RemoveNodeAdmin(subnetID []byte, adminKey interop.PublicKey) {
|
||||||
panic("removeNodeAdmin: " + errCheckWitnessFailed)
|
panic("removeNodeAdmin: " + errCheckWitnessFailed)
|
||||||
}
|
}
|
||||||
|
|
||||||
stOwnerKey[0] = nodeAdminPrefix
|
stKey[0] = nodeAdminPrefix
|
||||||
stNodeAdmKey := append(stOwnerKey, adminKey...)
|
|
||||||
|
|
||||||
if storage.Get(ctx, stNodeAdmKey) == nil {
|
if !keyInList(ctx, adminKey, stKey) {
|
||||||
panic("removeNodeAdmin: " + ErrNodeAdmNotExist)
|
panic("removeNodeAdmin: " + ErrNodeAdmNotExist)
|
||||||
}
|
}
|
||||||
|
|
||||||
storage.Delete(ctx, stNodeAdmKey)
|
deleteKeyFromList(ctx, adminKey, stKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddNode adds node to the specified subnetwork.
|
// AddNode adds node to the specified subnetwork.
|
||||||
|
@ -254,7 +253,7 @@ func AddNode(subnetID []byte, node interop.PublicKey) {
|
||||||
panic("addNode: node has already been added")
|
panic("addNode: node has already been added")
|
||||||
}
|
}
|
||||||
|
|
||||||
storage.Put(ctx, append(stKey, node...), []byte{1})
|
putKeyInList(ctx, node, stKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveNode removes node from the specified subnetwork.
|
// RemoveNode removes node from the specified subnetwork.
|
||||||
|
@ -327,21 +326,50 @@ func NodeAllowed(subnetID []byte, node interop.PublicKey) bool {
|
||||||
return storage.Get(ctx, append(stKey, node...)) != nil
|
return storage.Get(ctx, append(stKey, node...)) != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddClientAdmin adds new client administrator of the specified group in the specified subnetwork.
|
||||||
|
// Must be called by owner only.
|
||||||
|
func AddClientAdmin(subnetID []byte, groupID []byte, adminPublicKey interop.PublicKey) {
|
||||||
|
if len(adminPublicKey) != interop.PublicKeyCompressedLen {
|
||||||
|
panic("addClientAdmin: " + ErrInvalidAdmin)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := storage.GetContext()
|
||||||
|
|
||||||
|
stKey := append([]byte{ownerPrefix}, subnetID...)
|
||||||
|
|
||||||
|
rawOwner := storage.Get(ctx, stKey)
|
||||||
|
if rawOwner == nil {
|
||||||
|
panic("addClientAdmin: " + ErrSubNotExist)
|
||||||
|
}
|
||||||
|
|
||||||
|
owner := rawOwner.([]byte)
|
||||||
|
if !runtime.CheckWitness(owner) {
|
||||||
|
panic("addClientAdmin: " + errCheckWitnessFailed)
|
||||||
|
}
|
||||||
|
|
||||||
|
stKey[0] = clientAdminPrefix
|
||||||
|
stKey = append(stKey, groupID...)
|
||||||
|
|
||||||
|
if keyInList(ctx, adminPublicKey, stKey) {
|
||||||
|
panic("addClientAdmin: client admin has already been added")
|
||||||
|
}
|
||||||
|
|
||||||
|
putKeyInList(ctx, adminPublicKey, stKey)
|
||||||
|
}
|
||||||
|
|
||||||
// Version returns version of the contract.
|
// Version returns version of the contract.
|
||||||
func Version() int {
|
func Version() int {
|
||||||
return common.Version
|
return common.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
func keyInList(ctx storage.Context, searchedKey interop.PublicKey, prefix []byte) bool {
|
func keyInList(ctx storage.Context, searchedKey interop.PublicKey, prefix []byte) bool {
|
||||||
prefixLen := len(prefix)
|
return storage.Get(ctx, append(prefix, searchedKey...)) != nil
|
||||||
|
|
||||||
iter := storage.Find(ctx, prefix, storage.KeysOnly)
|
|
||||||
for iterator.Next(iter) {
|
|
||||||
key := iterator.Value(iter).([]byte)
|
|
||||||
if common.BytesEqual(key[prefixLen:], searchedKey) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
func putKeyInList(ctx storage.Context, keyToPut interop.PublicKey, prefix []byte) {
|
||||||
|
storage.Put(ctx, append(prefix, keyToPut...), []byte{1})
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteKeyFromList(ctx storage.Context, keyToDelete interop.PublicKey, prefix []byte) {
|
||||||
|
storage.Delete(ctx, append(prefix, keyToDelete...))
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,6 +137,7 @@ func TestSubnet_AddNode(t *testing.T) {
|
||||||
|
|
||||||
cOwn := e.WithSigners(owner)
|
cOwn := e.WithSigners(owner)
|
||||||
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrInvalidNode, method, id, nodePub[1:])
|
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrInvalidNode, method, id, nodePub[1:])
|
||||||
|
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrSubNotExist, method, []byte{0, 0, 0, 0}, nodePub)
|
||||||
|
|
||||||
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)
|
||||||
|
@ -159,6 +160,7 @@ func TestSubnet_RemoveNode(t *testing.T) {
|
||||||
|
|
||||||
cOwn := e.WithSigners(owner)
|
cOwn := e.WithSigners(owner)
|
||||||
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrInvalidNode, method, id, nodePub[1:])
|
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrInvalidNode, method, id, nodePub[1:])
|
||||||
|
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrSubNotExist, method, []byte{0, 0, 0, 0}, nodePub)
|
||||||
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)
|
||||||
|
@ -183,12 +185,33 @@ func TestSubnet_NodeAllowed(t *testing.T) {
|
||||||
|
|
||||||
cOwn := e.WithSigners(owner)
|
cOwn := e.WithSigners(owner)
|
||||||
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrInvalidNode, method, id, nodePub[1:])
|
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrInvalidNode, method, id, nodePub[1:])
|
||||||
|
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrSubNotExist, method, []byte{0, 0, 0, 0}, nodePub)
|
||||||
cOwn.Invoke(t, stackitem.NewBool(false), method, id, nodePub)
|
cOwn.Invoke(t, stackitem.NewBool(false), method, id, nodePub)
|
||||||
|
|
||||||
cOwn.Invoke(t, stackitem.Null{}, "addNode", id, nodePub)
|
cOwn.Invoke(t, stackitem.Null{}, "addNode", id, nodePub)
|
||||||
cOwn.Invoke(t, stackitem.NewBool(true), method, id, nodePub)
|
cOwn.Invoke(t, stackitem.NewBool(true), method, id, nodePub)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSubnet_AddClientAdmin(t *testing.T) {
|
||||||
|
e := newSubnetInvoker(t)
|
||||||
|
|
||||||
|
id, owner := createSubnet(t, e)
|
||||||
|
|
||||||
|
adm := e.NewAccount(t)
|
||||||
|
admPub, ok := vm.ParseSignatureContract(adm.Script())
|
||||||
|
require.True(t, ok)
|
||||||
|
|
||||||
|
const method = "addClientAdmin"
|
||||||
|
|
||||||
|
groupId := randomBytes(8)
|
||||||
|
|
||||||
|
cOwn := e.WithSigners(owner)
|
||||||
|
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrInvalidAdmin, method, id, groupId, admPub[1:])
|
||||||
|
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrSubNotExist, method, []byte{0, 0, 0, 0}, groupId, admPub)
|
||||||
|
cOwn.Invoke(t, stackitem.Null{}, method, id, groupId, admPub)
|
||||||
|
cOwn.InvokeFail(t, method+errSeparator+"client admin has already been added", method, id, groupId, admPub)
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
|
|
Loading…
Reference in a new issue