[#174] subnet: Add `AddUser` method

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
enable-notary-in-public-chains
Pavel Karpy 2021-11-23 13:56:56 +03:00 committed by LeL
parent cc7d98d45e
commit 9a05e213eb
2 changed files with 82 additions and 3 deletions

View File

@ -21,6 +21,8 @@ const (
ErrAlreadyExists = "subnet id already exists"
// ErrSubNotExist is thrown when id doesn't exist.
ErrSubNotExist = "subnet id doesn't exist"
// ErrInvalidUser is thrown when user has invalid format.
ErrInvalidUser = "invalid user"
// ErrInvalidNode is thrown when node has invalid format.
ErrInvalidNode = "invalid node key"
// ErrNodeAdmNotExist is thrown when node admin is not found.
@ -34,15 +36,19 @@ const (
errCheckWitnessFailed = "owner witness check failed"
ownerPrefix = 'o'
nodeAdminPrefix = 'a'
infoPrefix = 'i'
clientAdminPrefix = 'm'
nodePrefix = 'n'
user = 'u'
infoPrefix = 'i'
ownerPrefix = 'o'
userPrefix = 'u'
notaryDisabledKey = 'z'
)
const (
userIDSize = 27
)
// _deploy function sets up initial list of inner ring public keys.
func _deploy(data interface{}, isUpdate bool) {
if isUpdate {
@ -391,6 +397,54 @@ func RemoveClientAdmin(subnetID []byte, groupID []byte, adminPublicKey interop.P
deleteKeyFromList(ctx, adminPublicKey, stKey)
}
// AddUser adds user to the specified subnetwork and group.
// Must be called by the owner or the group's admin only.
func AddUser(subnetID []byte, groupID []byte, userID []byte) {
if len(userID) != userIDSize {
panic("addUser: " + ErrInvalidUser)
}
ctx := storage.GetContext()
stKey := append([]byte{ownerPrefix}, subnetID...)
rawOwner := storage.Get(ctx, stKey)
if rawOwner == nil {
panic("addUser: " + ErrSubNotExist)
}
stKey = append(stKey, groupID...)
prefixLen := len(stKey)
owner := rawOwner.([]byte)
if !runtime.CheckWitness(owner) {
var hasAccess bool
stKey[0] = clientAdminPrefix
iter := storage.Find(ctx, stKey, storage.KeysOnly)
for iterator.Next(iter) {
key := iterator.Value(iter).([]byte)
if runtime.CheckWitness(key[prefixLen:]) {
hasAccess = true
break
}
}
if !hasAccess {
panic("addUser: " + ErrAccessDenied)
}
}
stKey[0] = userPrefix
if keyInList(ctx, userID, stKey) {
panic("addUser: user has already been added")
}
putKeyInList(ctx, userID, stKey)
}
// Version returns version of the contract.
func Version() int {
return common.Version

View File

@ -233,6 +233,31 @@ func TestSubnet_RemoveClientAdmin(t *testing.T) {
cOwn.Invoke(t, stackitem.Null{}, method, id, groupId, admPub)
}
func TestSubnet_AddUser(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)
user := randomBytes(27)
groupId := randomBytes(8)
const method = "addUser"
cOwn := e.WithSigners(owner)
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrSubNotExist, method, []byte{0, 0, 0, 0}, groupId, user)
cOwn.Invoke(t, stackitem.Null{}, "addClientAdmin", id, groupId, admPub)
cAdm := e.WithSigners(adm)
cAdm.Invoke(t, stackitem.Null{}, method, id, groupId, user)
cOwn.InvokeFail(t, method+errSeparator+"user has already been added", method, id, groupId, user)
}
func createSubnet(t *testing.T, e *neotest.ContractInvoker) (id []byte, owner neotest.Signer) {
var (
ok bool