forked from TrueCloudLab/frostfs-contract
[#174] subnet: Add AddNodeAdmin
method
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
parent
b02a5c2d40
commit
df6cc4f8b7
2 changed files with 77 additions and 0 deletions
|
@ -3,9 +3,11 @@ package subnet
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop"
|
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/interop/iterator"
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,12 +16,18 @@ const (
|
||||||
ErrInvalidSubnetID = "invalid subnet ID"
|
ErrInvalidSubnetID = "invalid subnet ID"
|
||||||
// ErrInvalidOwner is thrown when owner has invalid format.
|
// ErrInvalidOwner is thrown when owner has invalid format.
|
||||||
ErrInvalidOwner = "invalid owner"
|
ErrInvalidOwner = "invalid owner"
|
||||||
|
// ErrInvalidAdmin is thrown when admin has invalid format.
|
||||||
|
ErrInvalidAdmin = "invalid administrator"
|
||||||
// ErrAlreadyExists is thrown when id already exists.
|
// ErrAlreadyExists is thrown when id already exists.
|
||||||
ErrAlreadyExists = "subnet id already exists"
|
ErrAlreadyExists = "subnet id already exists"
|
||||||
// ErrNotExist is thrown when id doesn't exist.
|
// ErrNotExist is thrown when id doesn't exist.
|
||||||
ErrNotExist = "subnet id doesn't exist"
|
ErrNotExist = "subnet id doesn't exist"
|
||||||
|
|
||||||
ownerPrefix = 'o'
|
ownerPrefix = 'o'
|
||||||
|
nodeAdminPrefix = 'a'
|
||||||
|
clientAdminPrefix = 'm'
|
||||||
|
nodePrefix = 'n'
|
||||||
|
user = 'u'
|
||||||
infoPrefix = 'i'
|
infoPrefix = 'i'
|
||||||
notaryDisabledKey = 'z'
|
notaryDisabledKey = 'z'
|
||||||
)
|
)
|
||||||
|
@ -131,6 +139,40 @@ func Delete(id []byte) {
|
||||||
storage.Delete(ctx, key)
|
storage.Delete(ctx, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddNodeAdmin adds new node administrator to the specified subnetwork.
|
||||||
|
func AddNodeAdmin(subnetID []byte, adminKey interop.PublicKey) {
|
||||||
|
if len(adminKey) != interop.PublicKeyCompressedLen {
|
||||||
|
panic("addNodeAdmin: " + ErrInvalidAdmin)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := storage.GetContext()
|
||||||
|
|
||||||
|
stKey := append([]byte{ownerPrefix}, subnetID...)
|
||||||
|
|
||||||
|
rawOwner := storage.Get(ctx, stKey)
|
||||||
|
if rawOwner == nil {
|
||||||
|
panic("addNodeAdmin: " + ErrNotExist)
|
||||||
|
}
|
||||||
|
|
||||||
|
owner := rawOwner.([]byte)
|
||||||
|
if !runtime.CheckWitness(owner) {
|
||||||
|
panic("addNodeAdmin: owner witness check failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
stKey[0] = nodeAdminPrefix
|
||||||
|
prefixLen := len(stKey)
|
||||||
|
|
||||||
|
iter := storage.Find(ctx, stKey, storage.KeysOnly)
|
||||||
|
for iterator.Next(iter) {
|
||||||
|
key := iterator.Value(iter).([]byte)
|
||||||
|
if util.Equals(string(key[prefixLen:]), string(adminKey)) {
|
||||||
|
panic("addNodeAdmin: node admin has already been added")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
storage.Put(ctx, append(stKey, adminKey...), []byte{1})
|
||||||
|
}
|
||||||
|
|
||||||
// Version returns version of the contract.
|
// Version returns version of the contract.
|
||||||
func Version() int {
|
func Version() int {
|
||||||
return common.Version
|
return common.Version
|
||||||
|
|
|
@ -80,3 +80,38 @@ func TestSubnet_Delete(t *testing.T) {
|
||||||
cAcc.InvokeFail(t, subnet.ErrNotExist, "get", id)
|
cAcc.InvokeFail(t, subnet.ErrNotExist, "get", id)
|
||||||
cAcc.InvokeFail(t, subnet.ErrNotExist, "delete", id)
|
cAcc.InvokeFail(t, subnet.ErrNotExist, "delete", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSubnet_AddNodeAdmin(t *testing.T) {
|
||||||
|
e := newSubnetInvoker(t)
|
||||||
|
|
||||||
|
owner := e.NewAccount(t)
|
||||||
|
pub, ok := vm.ParseSignatureContract(owner.Script())
|
||||||
|
require.True(t, ok)
|
||||||
|
|
||||||
|
id := make([]byte, 4)
|
||||||
|
binary.LittleEndian.PutUint32(id, 123)
|
||||||
|
info := randomBytes(10)
|
||||||
|
|
||||||
|
cBoth := e.WithSigners(e.Committee, owner)
|
||||||
|
cBoth.Invoke(t, stackitem.Null{}, "put", id, pub, info)
|
||||||
|
|
||||||
|
adm := e.NewAccount(t)
|
||||||
|
admPub, ok := vm.ParseSignatureContract(adm.Script())
|
||||||
|
require.True(t, ok)
|
||||||
|
|
||||||
|
const (
|
||||||
|
method = "addNodeAdmin"
|
||||||
|
errSeparator = ": "
|
||||||
|
)
|
||||||
|
|
||||||
|
e.InvokeFail(t, method+errSeparator+subnet.ErrInvalidAdmin, method, id, admPub[1:])
|
||||||
|
e.InvokeFail(t, method+errSeparator+subnet.ErrNotExist, method, []byte{0, 0, 0, 0}, admPub)
|
||||||
|
|
||||||
|
cAdm := e.WithSigners(adm)
|
||||||
|
cAdm.InvokeFail(t, method+errSeparator+"owner witness check failed", method, id, admPub)
|
||||||
|
|
||||||
|
cOwner := e.WithSigners(owner)
|
||||||
|
cOwner.Invoke(t, stackitem.Null{}, method, id, admPub)
|
||||||
|
|
||||||
|
cOwner.InvokeFail(t, method+errSeparator+"node admin has already been added", method, id, admPub)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue