From 8537293e1190ba647a708f68b4aedd09a448def2 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 17 Apr 2023 12:05:00 +0300 Subject: [PATCH] [#20] subnet: Drop contract Signed-off-by: Dmitrii Stepanov --- CHANGELOG.md | 2 + Makefile | 2 +- README.md | 2 - debian/control | 1 - subnet/config.yml | 23 -- subnet/doc.go | 37 --- subnet/subnet_contract.go | 559 -------------------------------------- tests/subnet_test.go | 330 ---------------------- 8 files changed, 3 insertions(+), 953 deletions(-) delete mode 100644 subnet/config.yml delete mode 100644 subnet/doc.go delete mode 100644 subnet/subnet_contract.go delete mode 100644 tests/subnet_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f601c3..ef924ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ Changelog for FrostFS Contract ### Added ### Changed ### Removed +- `subnet` contract (#20) + ### Updated ### Fixed ### Updating from v0.17.0 diff --git a/Makefile b/Makefile index 47720b4..b80cddc 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ all: sidechain mainnet sidechain: alphabet morph nns alphabet_sc = alphabet -morph_sc = audit balance container frostfsid netmap proxy reputation subnet +morph_sc = audit balance container frostfsid netmap proxy reputation mainnet_sc = frostfs processing nns_sc = nns diff --git a/README.md b/README.md index 5acb31b..004861f 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,6 @@ Sidechain contracts: - nns - proxy - reputation -- subnet # Getting started @@ -55,7 +54,6 @@ $ make all /home/user/go/bin/cli contract compile -i netmap -c netmap/config.yml -m netmap/config.json -o netmap/netmap_contract.nef /home/user/go/bin/cli contract compile -i proxy -c proxy/config.yml -m proxy/config.json -o proxy/proxy_contract.nef /home/user/go/bin/cli contract compile -i reputation -c reputation/config.yml -m reputation/config.json -o reputation/reputation_contract.nef -/home/user/go/bin/cli contract compile -i subnet -c subnet/config.yml -m subnet/config.json -o subnet/subnet_contract.nef /home/user/go/bin/cli contract compile -i nns -c nns/config.yml -m nns/config.json -o nns/nns_contract.nef /home/user/go/bin/cli contract compile -i frostfs -c frostfs/config.yml -m frostfs/config.json -o frostfs/frostfs_contract.nef /home/user/go/bin/cli contract compile -i processing -c processing/config.yml -m processing/config.json -o processing/processing_contract.nef diff --git a/debian/control b/debian/control index 3599cb0..942ae20 100644 --- a/debian/control +++ b/debian/control @@ -31,4 +31,3 @@ Description: FrostFS-Contract contains all FrostFS related contracts. - nns - proxy - reputation - - subnet diff --git a/subnet/config.yml b/subnet/config.yml deleted file mode 100644 index 8736d1d..0000000 --- a/subnet/config.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: "Subnet" -safemethods: ["version"] -permissions: - - methods: ["update"] -events: - - name: Put - parameters: - - name: id - type: ByteArray - - name: ownerKey - type: PublicKey - - name: info - type: ByteArray - - name: Delete - parameters: - - name: id - type: ByteArray - - name: RemoveNode - parameters: - - name: subnetID - type: ByteArray - - name: node - type: PublicKey diff --git a/subnet/doc.go b/subnet/doc.go deleted file mode 100644 index 1c8fdbc..0000000 --- a/subnet/doc.go +++ /dev/null @@ -1,37 +0,0 @@ -/* -Subnet contract is a contract deployed in FrostFS sidechain. - -Subnet contract stores and manages FrostFS subnetwork states. It allows registering -and deleting subnetworks, limiting access to them, and defining a list of the Storage -Nodes that can be included in them. - -# Contract notifications - -Put notification. This notification is produced when a new subnetwork is -registered by invoking Put method. - - Put - - name: id - type: ByteArray - - name: ownerKey - type: PublicKey - - name: info - type: ByteArray - -Delete notification. This notification is produced when some subnetwork is -deleted by invoking Delete method. - - Delete - - name: id - type: ByteArray - -RemoveNode notification. This notification is produced when some node is deleted -by invoking RemoveNode method. - - RemoveNode - - name: subnetID - type: ByteArray - - name: node - type: PublicKey -*/ -package subnet diff --git a/subnet/subnet_contract.go b/subnet/subnet_contract.go deleted file mode 100644 index c7bbd32..0000000 --- a/subnet/subnet_contract.go +++ /dev/null @@ -1,559 +0,0 @@ -package subnet - -import ( - "git.frostfs.info/TrueCloudLab/frostfs-contract/common" - "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/iterator" - "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/storage" -) - -const ( - // ErrInvalidSubnetID is thrown when subnet id is not a slice of 5 bytes. - ErrInvalidSubnetID = "invalid subnet ID" - // ErrInvalidGroupID is thrown when group id is not a slice of 5 bytes. - ErrInvalidGroupID = "invalid group ID" - // ErrInvalidOwner is thrown when owner has invalid format. - ErrInvalidOwner = "invalid owner" - // ErrInvalidAdmin is thrown when admin has invalid format. - ErrInvalidAdmin = "invalid administrator" - // ErrAlreadyExists is thrown when id already exists. - ErrAlreadyExists = "subnet id already exists" - // ErrNotExist is thrown when id doesn't exist. - ErrNotExist = "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" - // ErrAccessDenied is thrown when operation is denied for caller. - ErrAccessDenied = "access denied" -) - -const ( - nodeAdminPrefix = 'a' - infoPrefix = 'i' - clientAdminPrefix = 'm' - nodePrefix = 'n' - ownerPrefix = 'o' - userPrefix = 'u' - notaryDisabledKey = 'z' -) - -const ( - userIDSize = 27 - subnetIDSize = 5 - groupIDSize = 5 -) - -// _deploy function sets up initial list of inner ring public keys. -func _deploy(data interface{}, isUpdate bool) { - common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey) - - if isUpdate { - args := data.([]interface{}) - common.CheckVersion(args[len(args)-1].(int)) - return - } -} - -// Update method updates contract source code and manifest. It can be invoked -// only by committee. -func Update(script []byte, manifest []byte, data interface{}) { - if !common.HasUpdateAccess() { - panic("only committee can update contract") - } - - contract.Call(interop.Hash160(management.Hash), "update", contract.All, - script, manifest, common.AppendVersion(data)) - runtime.Log("subnet contract updated") -} - -// Put creates a new subnet with the specified owner and info. -func Put(id []byte, ownerKey interop.PublicKey, info []byte) { - // V2 format - if len(id) != subnetIDSize { - panic(ErrInvalidSubnetID) - } - if len(ownerKey) != interop.PublicKeyCompressedLen { - panic(ErrInvalidOwner) - } - - ctx := storage.GetContext() - stKey := append([]byte{ownerPrefix}, id...) - if storage.Get(ctx, stKey) != nil { - panic(ErrAlreadyExists) - } - - common.CheckOwnerWitness(ownerKey) - - common.CheckAlphabetWitness() - - storage.Put(ctx, stKey, ownerKey) - stKey[0] = infoPrefix - storage.Put(ctx, stKey, info) -} - -// Get returns info about the subnet with the specified id. -func Get(id []byte) []byte { - // V2 format - if len(id) != subnetIDSize { - panic(ErrInvalidSubnetID) - } - - ctx := storage.GetReadOnlyContext() - key := append([]byte{infoPrefix}, id...) - raw := storage.Get(ctx, key) - if raw == nil { - panic(ErrNotExist) - } - return raw.([]byte) -} - -// Delete deletes the subnet with the specified id. -func Delete(id []byte) { - // V2 format - if len(id) != subnetIDSize { - panic(ErrInvalidSubnetID) - } - - ctx := storage.GetContext() - key := append([]byte{ownerPrefix}, id...) - raw := storage.Get(ctx, key) - if raw == nil { - return - } - - owner := raw.([]byte) - common.CheckOwnerWitness(owner) - - storage.Delete(ctx, key) - - key[0] = infoPrefix - storage.Delete(ctx, key) - - key[0] = nodeAdminPrefix - deleteByPrefix(ctx, key) - - key[0] = nodePrefix - deleteByPrefix(ctx, key) - - key[0] = clientAdminPrefix - deleteByPrefix(ctx, key) - - key[0] = userPrefix - deleteByPrefix(ctx, key) - - runtime.Notify("Delete", id) -} - -// AddNodeAdmin adds a new node administrator to the specified subnetwork. -func AddNodeAdmin(subnetID []byte, adminKey interop.PublicKey) { - // V2 format - if len(subnetID) != subnetIDSize { - panic(ErrInvalidSubnetID) - } - - if len(adminKey) != interop.PublicKeyCompressedLen { - panic(ErrInvalidAdmin) - } - - ctx := storage.GetContext() - - stKey := append([]byte{ownerPrefix}, subnetID...) - - rawOwner := storage.Get(ctx, stKey) - if rawOwner == nil { - panic(ErrNotExist) - } - - owner := rawOwner.([]byte) - common.CheckOwnerWitness(owner) - - stKey[0] = nodeAdminPrefix - - if keyInList(ctx, adminKey, stKey) { - return - } - - putKeyInList(ctx, adminKey, stKey) -} - -// RemoveNodeAdmin removes node administrator from the specified subnetwork. -// Must be called by the subnet owner only. -func RemoveNodeAdmin(subnetID []byte, adminKey interop.PublicKey) { - // V2 format - if len(subnetID) != subnetIDSize { - panic(ErrInvalidSubnetID) - } - - if len(adminKey) != interop.PublicKeyCompressedLen { - panic(ErrInvalidAdmin) - } - - ctx := storage.GetContext() - - stKey := append([]byte{ownerPrefix}, subnetID...) - - rawOwner := storage.Get(ctx, stKey) - if rawOwner == nil { - panic(ErrNotExist) - } - - owner := rawOwner.([]byte) - common.CheckOwnerWitness(owner) - - stKey[0] = nodeAdminPrefix - - if !keyInList(ctx, adminKey, stKey) { - return - } - - deleteKeyFromList(ctx, adminKey, stKey) -} - -// AddNode adds a node to the specified subnetwork. -// Must be called by the subnet's owner or the node administrator -// only. -func AddNode(subnetID []byte, node interop.PublicKey) { - // V2 format - if len(subnetID) != subnetIDSize { - panic(ErrInvalidSubnetID) - } - - if len(node) != interop.PublicKeyCompressedLen { - panic(ErrInvalidNode) - } - - ctx := storage.GetContext() - - stKey := append([]byte{ownerPrefix}, subnetID...) - - rawOwner := storage.Get(ctx, stKey) - if rawOwner == nil { - panic(ErrNotExist) - } - - stKey[0] = nodeAdminPrefix - - owner := rawOwner.([]byte) - - if !calledByOwnerOrAdmin(ctx, owner, stKey) { - panic(ErrAccessDenied) - } - - stKey[0] = nodePrefix - - if keyInList(ctx, node, stKey) { - return - } - - putKeyInList(ctx, node, stKey) -} - -// RemoveNode removes a node from the specified subnetwork. -// Must be called by the subnet's owner or the node administrator -// only. -func RemoveNode(subnetID []byte, node interop.PublicKey) { - // V2 format - if len(subnetID) != subnetIDSize { - panic(ErrInvalidSubnetID) - } - - if len(node) != interop.PublicKeyCompressedLen { - panic(ErrInvalidNode) - } - - ctx := storage.GetContext() - - stKey := append([]byte{ownerPrefix}, subnetID...) - - rawOwner := storage.Get(ctx, stKey) - if rawOwner == nil { - panic(ErrNotExist) - } - - stKey[0] = nodeAdminPrefix - - owner := rawOwner.([]byte) - - if !calledByOwnerOrAdmin(ctx, owner, stKey) { - panic(ErrAccessDenied) - } - - stKey[0] = nodePrefix - - if !keyInList(ctx, node, stKey) { - return - } - - storage.Delete(ctx, append(stKey, node...)) - - runtime.Notify("RemoveNode", subnetID, node) -} - -// NodeAllowed checks if a node is included in the -// specified subnet. -func NodeAllowed(subnetID []byte, node interop.PublicKey) bool { - // V2 format - if len(subnetID) != subnetIDSize { - panic(ErrInvalidSubnetID) - } - - if len(node) != interop.PublicKeyCompressedLen { - panic(ErrInvalidNode) - } - - ctx := storage.GetReadOnlyContext() - - stKey := append([]byte{ownerPrefix}, subnetID...) - - rawOwner := storage.Get(ctx, stKey) - if rawOwner == nil { - panic(ErrNotExist) - } - - stKey[0] = nodePrefix - - return storage.Get(ctx, append(stKey, node...)) != nil -} - -// AddClientAdmin adds a new client administrator of the specified group in the specified subnetwork. -// Must be called by the owner only. -func AddClientAdmin(subnetID []byte, groupID []byte, adminPublicKey interop.PublicKey) { - // V2 format - if len(subnetID) != subnetIDSize { - panic(ErrInvalidSubnetID) - } - - // V2 format - if len(groupID) != groupIDSize { - panic(ErrInvalidGroupID) - } - - if len(adminPublicKey) != interop.PublicKeyCompressedLen { - panic(ErrInvalidAdmin) - } - - ctx := storage.GetContext() - - stKey := append([]byte{ownerPrefix}, subnetID...) - - rawOwner := storage.Get(ctx, stKey) - if rawOwner == nil { - panic(ErrNotExist) - } - - owner := rawOwner.([]byte) - common.CheckOwnerWitness(owner) - - stKey[0] = clientAdminPrefix - stKey = append(stKey, groupID...) - - if keyInList(ctx, adminPublicKey, stKey) { - return - } - - putKeyInList(ctx, adminPublicKey, stKey) -} - -// RemoveClientAdmin removes client administrator from the -// specified group in the specified subnetwork. -// Must be called by the owner only. -func RemoveClientAdmin(subnetID []byte, groupID []byte, adminPublicKey interop.PublicKey) { - // V2 format - if len(subnetID) != subnetIDSize { - panic(ErrInvalidSubnetID) - } - - // V2 format - if len(groupID) != groupIDSize { - panic(ErrInvalidGroupID) - } - - if len(adminPublicKey) != interop.PublicKeyCompressedLen { - panic(ErrInvalidAdmin) - } - - ctx := storage.GetContext() - - stKey := append([]byte{ownerPrefix}, subnetID...) - - rawOwner := storage.Get(ctx, stKey) - if rawOwner == nil { - panic(ErrNotExist) - } - - owner := rawOwner.([]byte) - common.CheckOwnerWitness(owner) - - stKey[0] = clientAdminPrefix - stKey = append(stKey, groupID...) - - if !keyInList(ctx, adminPublicKey, stKey) { - return - } - - 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) { - // V2 format - if len(subnetID) != subnetIDSize { - panic(ErrInvalidSubnetID) - } - - // V2 format - if len(userID) != userIDSize { - panic(ErrInvalidUser) - } - - // V2 format - if len(groupID) != groupIDSize { - panic(ErrInvalidGroupID) - } - - ctx := storage.GetContext() - - stKey := append([]byte{ownerPrefix}, subnetID...) - - rawOwner := storage.Get(ctx, stKey) - if rawOwner == nil { - panic(ErrNotExist) - } - - stKey[0] = clientAdminPrefix - stKey = append(stKey, groupID...) - - owner := rawOwner.([]byte) - - if !calledByOwnerOrAdmin(ctx, owner, stKey) { - panic(ErrAccessDenied) - } - - stKey[0] = userPrefix - - if keyInList(ctx, userID, stKey) { - return - } - - putKeyInList(ctx, userID, stKey) -} - -// RemoveUser removes a user from the specified subnetwork and group. -// Must be called by the owner or the group's admin only. -func RemoveUser(subnetID []byte, groupID []byte, userID []byte) { - // V2 format - if len(subnetID) != subnetIDSize { - panic(ErrInvalidSubnetID) - } - - // V2 format - if len(groupID) != groupIDSize { - panic(ErrInvalidGroupID) - } - - // V2 format - if len(userID) != userIDSize { - panic(ErrInvalidUser) - } - - ctx := storage.GetContext() - - stKey := append([]byte{ownerPrefix}, subnetID...) - - rawOwner := storage.Get(ctx, stKey) - if rawOwner == nil { - panic(ErrNotExist) - } - - stKey[0] = clientAdminPrefix - stKey = append(stKey, groupID...) - - owner := rawOwner.([]byte) - - if !calledByOwnerOrAdmin(ctx, owner, stKey) { - panic(ErrAccessDenied) - } - - stKey[0] = userPrefix - - if !keyInList(ctx, userID, stKey) { - return - } - - deleteKeyFromList(ctx, userID, stKey) -} - -// UserAllowed returns bool that indicates if a node is included in the -// specified subnet. -func UserAllowed(subnetID []byte, user []byte) bool { - // V2 format - if len(subnetID) != subnetIDSize { - panic(ErrInvalidSubnetID) - } - - ctx := storage.GetContext() - - stKey := append([]byte{ownerPrefix}, subnetID...) - if storage.Get(ctx, stKey) == nil { - panic(ErrNotExist) - } - - stKey[0] = userPrefix - prefixLen := len(stKey) + groupIDSize - - iter := storage.Find(ctx, stKey, storage.KeysOnly) - for iterator.Next(iter) { - key := iterator.Value(iter).([]byte) - if common.BytesEqual(user, key[prefixLen:]) { - return true - } - } - - return false -} - -// Version returns the version of the contract. -func Version() int { - return common.Version -} - -func keyInList(ctx storage.Context, searchedKey interop.PublicKey, prefix []byte) bool { - return storage.Get(ctx, append(prefix, searchedKey...)) != nil -} - -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...)) -} - -func deleteByPrefix(ctx storage.Context, prefix []byte) { - iter := storage.Find(ctx, prefix, storage.KeysOnly) - for iterator.Next(iter) { - k := iterator.Value(iter).([]byte) - storage.Delete(ctx, k) - } -} - -func calledByOwnerOrAdmin(ctx storage.Context, owner []byte, adminPrefix []byte) bool { - if runtime.CheckWitness(owner) { - return true - } - - iter := storage.Find(ctx, adminPrefix, storage.KeysOnly|storage.RemovePrefix) - for iterator.Next(iter) { - key := iterator.Value(iter).([]byte) - if runtime.CheckWitness(key) { - return true - } - } - - return false -} diff --git a/tests/subnet_test.go b/tests/subnet_test.go deleted file mode 100644 index afea2bd..0000000 --- a/tests/subnet_test.go +++ /dev/null @@ -1,330 +0,0 @@ -package tests - -import ( - "encoding/binary" - "path" - "testing" - - "git.frostfs.info/TrueCloudLab/frostfs-contract/common" - "git.frostfs.info/TrueCloudLab/frostfs-contract/subnet" - "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" -) - -const subnetPath = "../subnet" - -func deploySubnetContract(t *testing.T, e *neotest.Executor) util.Uint160 { - c := neotest.CompileFile(t, e.CommitteeHash, subnetPath, path.Join(subnetPath, "config.yml")) - args := []interface{}{false} - e.DeployContract(t, c, args) - return c.Hash -} - -func newSubnetInvoker(t *testing.T) *neotest.ContractInvoker { - e := newExecutor(t) - h := deploySubnetContract(t, e) - return e.CommitteeInvoker(h) -} - -func TestSubnet_Version(t *testing.T) { - e := newSubnetInvoker(t) - e.Invoke(t, common.Version, "version") -} - -func TestSubnet_Put(t *testing.T) { - e := newSubnetInvoker(t) - - acc := e.NewAccount(t) - pub, ok := vm.ParseSignatureContract(acc.Script()) - require.True(t, ok) - - id := make([]byte, 5) - binary.LittleEndian.PutUint32(id, 123) - info := randomBytes(10) - - e.InvokeFail(t, common.ErrWitnessFailed, "put", id, pub, info) - - cAcc := e.WithSigners(acc) - cAcc.InvokeFail(t, common.ErrAlphabetWitnessFailed, "put", id, pub, info) - - cBoth := e.WithSigners(e.Committee, acc) - cBoth.InvokeFail(t, subnet.ErrInvalidSubnetID, "put", []byte{1, 2, 3}, pub, info) - cBoth.InvokeFail(t, subnet.ErrInvalidOwner, "put", id, pub[10:], info) - cBoth.Invoke(t, stackitem.Null{}, "put", id, pub, info) - cAcc.Invoke(t, stackitem.NewBuffer(info), "get", id) - cBoth.InvokeFail(t, subnet.ErrAlreadyExists, "put", id, pub, info) -} - -func TestSubnet_Delete(t *testing.T) { - e := newSubnetInvoker(t) - - id, owner := createSubnet(t, e) - - e.InvokeFail(t, common.ErrWitnessFailed, "delete", id) - - cAcc := e.WithSigners(owner) - cAcc.InvokeFail(t, subnet.ErrInvalidSubnetID, "delete", []byte{1, 1, 1, 1}) - cAcc.Invoke(t, stackitem.Null{}, "delete", []byte{1, 1, 1, 1, 1}) - cAcc.Invoke(t, stackitem.Null{}, "delete", id) - cAcc.InvokeFail(t, subnet.ErrNotExist, "get", id) -} - -func TestSubnet_AddNodeAdmin(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 = "addNodeAdmin" - - e.InvokeFail(t, subnet.ErrInvalidSubnetID, method, []byte{0, 0, 0, 0}, admPub) - e.InvokeFail(t, subnet.ErrInvalidAdmin, method, id, admPub[1:]) - e.InvokeFail(t, subnet.ErrNotExist, method, []byte{0, 0, 0, 0, 0}, admPub) - - cAdm := e.WithSigners(adm) - cAdm.InvokeFail(t, common.ErrOwnerWitnessFailed, method, id, admPub) - - cOwner := e.WithSigners(owner) - cOwner.Invoke(t, stackitem.Null{}, method, id, admPub) - - cOwner.Invoke(t, stackitem.Null{}, method, id, admPub) -} - -func TestSubnet_RemoveNodeAdmin(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 = "removeNodeAdmin" - - e.InvokeFail(t, subnet.ErrInvalidSubnetID, method, []byte{0, 0, 0, 0}, admPub) - e.InvokeFail(t, subnet.ErrInvalidAdmin, method, id, admPub[1:]) - e.InvokeFail(t, subnet.ErrNotExist, method, []byte{0, 0, 0, 0, 0}, admPub) - - cAdm := e.WithSigners(adm) - cAdm.InvokeFail(t, common.ErrOwnerWitnessFailed, method, id, admPub) - - cOwner := e.WithSigners(owner) - - cOwner.Invoke(t, stackitem.Null{}, method, id, admPub) - cOwner.Invoke(t, stackitem.Null{}, "addNodeAdmin", id, admPub) - cOwner.Invoke(t, stackitem.Null{}, method, id, admPub) - cOwner.Invoke(t, stackitem.Null{}, method, id, admPub) -} - -func TestSubnet_AddNode(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 = "addNode" - - cOwn := e.WithSigners(owner) - cOwn.InvokeFail(t, subnet.ErrInvalidSubnetID, method, []byte{0, 0, 0, 0}, nodePub) - cOwn.InvokeFail(t, subnet.ErrInvalidNode, method, id, nodePub[1:]) - cOwn.InvokeFail(t, subnet.ErrNotExist, method, []byte{0, 0, 0, 0, 0}, nodePub) - - cOwn.Invoke(t, stackitem.Null{}, method, id, nodePub) - cOwn.Invoke(t, stackitem.Null{}, method, id, nodePub) -} - -func TestSubnet_RemoveNode(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) - - adm := e.NewAccount(t) - admPub, ok := vm.ParseSignatureContract(adm.Script()) - require.True(t, ok) - - const method = "removeNode" - - cOwn := e.WithSigners(owner) - cOwn.InvokeFail(t, subnet.ErrInvalidSubnetID, method, []byte{0, 0, 0, 0}, nodePub) - cOwn.InvokeFail(t, subnet.ErrInvalidNode, method, id, nodePub[1:]) - cOwn.InvokeFail(t, subnet.ErrNotExist, method, []byte{0, 0, 0, 0, 0}, nodePub) - cOwn.Invoke(t, stackitem.Null{}, method, id, nodePub) - - cOwn.Invoke(t, stackitem.Null{}, "addNode", id, nodePub) - cOwn.Invoke(t, stackitem.Null{}, method, id, nodePub) - - cAdm := cOwn.WithSigners(adm) - - cOwn.Invoke(t, stackitem.Null{}, "addNodeAdmin", id, admPub) - cAdm.Invoke(t, stackitem.Null{}, 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, subnet.ErrInvalidSubnetID, method, []byte{0, 0, 0, 0}, nodePub) - cOwn.InvokeFail(t, subnet.ErrInvalidNode, method, id, nodePub[1:]) - cOwn.InvokeFail(t, subnet.ErrNotExist, method, []byte{0, 0, 0, 0, 0}, nodePub) - 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 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(5) - - cOwn := e.WithSigners(owner) - cOwn.InvokeFail(t, subnet.ErrInvalidSubnetID, method, []byte{0, 0, 0, 0}, groupId, admPub) - cOwn.InvokeFail(t, subnet.ErrInvalidAdmin, method, id, groupId, admPub[1:]) - cOwn.InvokeFail(t, subnet.ErrNotExist, method, []byte{0, 0, 0, 0, 0}, groupId, admPub) - cOwn.Invoke(t, stackitem.Null{}, method, id, groupId, admPub) - cOwn.Invoke(t, stackitem.Null{}, method, id, groupId, admPub) -} - -func TestSubnet_RemoveClientAdmin(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 = "removeClientAdmin" - - groupId := randomBytes(5) - - cOwn := e.WithSigners(owner) - cOwn.InvokeFail(t, subnet.ErrInvalidSubnetID, method, []byte{0, 0, 0, 0}, groupId, admPub) - cOwn.InvokeFail(t, subnet.ErrInvalidAdmin, method, id, groupId, admPub[1:]) - cOwn.InvokeFail(t, subnet.ErrNotExist, method, []byte{0, 0, 0, 0, 0}, groupId, admPub) - cOwn.Invoke(t, stackitem.Null{}, method, id, groupId, admPub) - cOwn.Invoke(t, stackitem.Null{}, "addClientAdmin", id, groupId, admPub) - 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(5) - - const method = "addUser" - - cOwn := e.WithSigners(owner) - cOwn.InvokeFail(t, subnet.ErrInvalidSubnetID, method, []byte{0, 0, 0, 0}, groupId, user) - cOwn.InvokeFail(t, subnet.ErrNotExist, method, []byte{0, 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.Invoke(t, stackitem.Null{}, method, id, groupId, user) -} - -func TestSubnet_RemoveUser(t *testing.T) { - e := newSubnetInvoker(t) - - id, owner := createSubnet(t, e) - - groupId := randomBytes(5) - user := randomBytes(27) - - adm := e.NewAccount(t) - admPub, ok := vm.ParseSignatureContract(adm.Script()) - require.True(t, ok) - - const method = "removeUser" - - cOwn := e.WithSigners(owner) - cOwn.InvokeFail(t, subnet.ErrInvalidSubnetID, method, []byte{0, 0, 0, 0}, groupId, user) - cOwn.InvokeFail(t, subnet.ErrNotExist, method, []byte{0, 0, 0, 0, 0}, groupId, user) - - cOwn.Invoke(t, stackitem.Null{}, method, id, groupId, user) - cOwn.Invoke(t, stackitem.Null{}, "addUser", id, groupId, user) - cOwn.Invoke(t, stackitem.Null{}, method, id, groupId, user) - - cAdm := cOwn.WithSigners(adm) - - cOwn.Invoke(t, stackitem.Null{}, "addClientAdmin", id, groupId, admPub) - cAdm.Invoke(t, stackitem.Null{}, method, id, groupId, user) -} - -func TestSubnet_UserAllowed(t *testing.T) { - e := newSubnetInvoker(t) - - id, owner := createSubnet(t, e) - - groupId := randomBytes(5) - - user := randomBytes(27) - - const method = "userAllowed" - - cOwn := e.WithSigners(owner) - cOwn.InvokeFail(t, subnet.ErrNotExist, method, []byte{0, 0, 0, 0, 0}, user) - - cOwn.Invoke(t, stackitem.NewBool(false), method, id, user) - cOwn.Invoke(t, stackitem.Null{}, "addUser", id, groupId, user) - cOwn.Invoke(t, stackitem.NewBool(true), method, id, user) -} - -func createSubnet(t *testing.T, e *neotest.ContractInvoker) (id []byte, owner neotest.Signer) { - var ( - ok bool - pub []byte - ) - - owner = e.NewAccount(t) - pub, ok = vm.ParseSignatureContract(owner.Script()) - require.True(t, ok) - - id = make([]byte, 5) - binary.LittleEndian.PutUint32(id, 123) - info := randomBytes(10) - - cBoth := e.WithSigners(e.Committee, owner) - cBoth.Invoke(t, stackitem.Null{}, "put", id, pub, info) - - return -}