[#249] node: Drop subnet from IR and morph

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
Dmitrii Stepanov 2023-04-14 13:47:08 +03:00
parent d757d881d0
commit f07d4158f5
41 changed files with 55 additions and 1935 deletions

View file

@ -32,8 +32,6 @@ const (
NNSNetmapContractName = "netmap.frostfs"
// NNSProxyContractName is a name of the proxy contract in NNS.
NNSProxyContractName = "proxy.frostfs"
// NNSSubnetworkContractName is a name of the subnet contract in NNS.
NNSSubnetworkContractName = "subnet.frostfs"
// NNSGroupKeyName is a name for the FrostFS group key record in NNS.
NNSGroupKeyName = "group.frostfs"
)

View file

@ -1,87 +0,0 @@
package morphsubnet
import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
// ManageAdminsPrm groups parameters of administer methods of Subnet contract.
//
// Zero value adds node admin. Subnet, key and group must be specified via setters.
type ManageAdminsPrm struct {
// remove or add admin
rm bool
// client or node admin
client bool
subnet []byte
admin []byte
group []byte
}
// SetRemove marks admin to be removed. By default, admin is added.
func (x *ManageAdminsPrm) SetRemove() {
x.rm = true
}
// SetClient switches to client admin. By default, node admin is modified.
func (x *ManageAdminsPrm) SetClient() {
x.client = true
}
// SetSubnet sets identifier of the subnet in a binary FrostFS API protocol format.
func (x *ManageAdminsPrm) SetSubnet(id []byte) {
x.subnet = id
}
// SetAdmin sets admin's public key in a binary format.
func (x *ManageAdminsPrm) SetAdmin(key []byte) {
x.admin = key
}
// SetGroup sets identifier of the client group in a binary FrostFS API protocol format.
// Makes sense only for client admins (see ManageAdminsPrm.SetClient).
func (x *ManageAdminsPrm) SetGroup(id []byte) {
x.group = id
}
// ManageAdminsRes groups the resulting values of node administer methods of Subnet contract.
type ManageAdminsRes struct{}
// ManageAdmins manages admin list of the FrostFS subnet through Subnet contract calls.
func (x Client) ManageAdmins(prm ManageAdminsPrm) (*ManageAdminsPrm, error) {
var method string
args := make([]any, 1, 3)
args[0] = prm.subnet
if prm.client {
args = append(args, prm.group, prm.admin)
if prm.rm {
method = removeClientAdminMethod
} else {
method = addClientAdminMethod
}
} else {
args = append(args, prm.admin)
if prm.rm {
method = removeNodeAdminMethod
} else {
method = addNodeAdminMethod
}
}
var prmInvoke client.InvokePrm
prmInvoke.SetMethod(method)
prmInvoke.SetArgs(args...)
err := x.client.Invoke(prmInvoke)
if err != nil {
return nil, err
}
return new(ManageAdminsPrm), nil
}

View file

@ -1,108 +0,0 @@
package morphsubnet
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
"github.com/nspcc-dev/neo-go/pkg/util"
)
// Client represents Subnet contract client.
//
// Client should be preliminary initialized (see Init method).
type Client struct {
client *client.StaticClient
}
// InitPrm groups parameters of Client's initialization.
type InitPrm struct {
base *client.Client
addr util.Uint160
modeSet bool
mode Mode
}
const (
deleteMethod = "delete"
getMethod = "get"
putMethod = "put"
removeClientAdminMethod = "removeClientAdmin"
addClientAdminMethod = "addClientAdmin"
userAllowedMethod = "userAllowed"
removeUserMethod = "removeUser"
addUserMethod = "addUser"
removeNodeAdminMethod = "removeNodeAdmin"
addNodeAdminMethod = "addNodeAdmin"
nodeAllowedMethod = "nodeAllowed"
removeNodeMethod = "removeNode"
addNodeMethod = "addNode"
)
// SetBaseClient sets basic morph client.
func (x *InitPrm) SetBaseClient(base *client.Client) {
x.base = base
}
// SetContractAddress sets address of Subnet contract in FrostFS sidechain.
func (x *InitPrm) SetContractAddress(addr util.Uint160) {
x.addr = addr
}
// Mode regulates client work mode.
type Mode uint8
const (
_ Mode = iota
// NonNotary makes client to work in non-notary environment.
NonNotary
// NotaryAlphabet makes client to use its internal key for signing the notary requests.
NotaryAlphabet
// NotaryNonAlphabet makes client to not use its internal key for signing the notary requests.
NotaryNonAlphabet
)
// SetMode makes client to work with non-notary sidechain.
// By default, NonNotary is used.
func (x *InitPrm) SetMode(mode Mode) {
x.modeSet = true
x.mode = mode
}
// Init initializes client with specified parameters.
//
// Base client must be set.
func (x *Client) Init(prm InitPrm) error {
if prm.base == nil {
panic("missing base morph client")
}
if !prm.modeSet {
prm.mode = NonNotary
}
var opts []client.StaticClientOption
switch prm.mode {
default:
panic(fmt.Sprintf("invalid work mode %d", prm.mode))
case NonNotary:
case NotaryNonAlphabet:
opts = []client.StaticClientOption{client.TryNotary()}
case NotaryAlphabet:
opts = []client.StaticClientOption{client.TryNotary(), client.AsAlphabet()}
}
var err error
x.client, err = client.NewStatic(prm.base, prm.addr, 0, opts...)
return err
}

View file

@ -1,114 +0,0 @@
package morphsubnet
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
)
// UserAllowedPrm groups parameters of UserAllowed method of Subnet contract.
type UserAllowedPrm struct {
args [2]any
}
// SetID sets identifier of the subnet in a binary FrostFS API protocol format.
func (x *UserAllowedPrm) SetID(id []byte) {
x.args[0] = id
}
// SetClient sets owner ID of the client that is being checked in a binary FrostFS API protocol format.
func (x *UserAllowedPrm) SetClient(id []byte) {
x.args[1] = id
}
// UserAllowedRes groups the resulting values of UserAllowed method of Subnet contract.
type UserAllowedRes struct {
result bool
}
// Allowed returns true iff the client is allowed to create containers in the subnet.
func (x UserAllowedRes) Allowed() bool {
return x.result
}
// UserAllowed checks if the user has access to the subnetwork.
func (x *Client) UserAllowed(prm UserAllowedPrm) (*UserAllowedRes, error) {
args := client.TestInvokePrm{}
args.SetMethod(userAllowedMethod)
args.SetArgs(prm.args[:]...)
res, err := x.client.TestInvoke(args)
if err != nil {
return nil, fmt.Errorf("could not make test invoke: %w", err)
}
if len(res) == 0 {
return nil, errEmptyResponse
}
result, err := client.BoolFromStackItem(res[0])
if err != nil {
return nil, err
}
return &UserAllowedRes{
result: result,
}, nil
}
// ManageClientsPrm groups parameters of client management in Subnet contract.
//
// Zero value adds subnet client. Subnet, group and client ID must be specified via setters.
type ManageClientsPrm struct {
// remove or add client
rm bool
args [3]any
}
// SetRemove marks client to be removed. By default, client is added.
func (x *ManageClientsPrm) SetRemove() {
x.rm = true
}
// SetSubnet sets identifier of the subnet in a binary FrostFS API protocol format.
func (x *ManageClientsPrm) SetSubnet(id []byte) {
x.args[0] = id
}
// SetGroup sets identifier of the client group in a binary FrostFS API protocol format.
func (x *ManageClientsPrm) SetGroup(id []byte) {
x.args[1] = id
}
// SetClient sets client's user ID in a binary FrostFS API protocol format.
func (x *ManageClientsPrm) SetClient(id []byte) {
x.args[2] = id
}
// ManageClientsRes groups the resulting values of client management methods of Subnet contract.
type ManageClientsRes struct{}
// ManageClients manages client list of the FrostFS subnet through Subnet contract calls.
func (x Client) ManageClients(prm ManageClientsPrm) (*ManageClientsRes, error) {
var method string
if prm.rm {
method = removeUserMethod
} else {
method = addUserMethod
}
var prmInvoke client.InvokePrm
prmInvoke.SetMethod(method)
prmInvoke.SetArgs(prm.args[:]...)
err := x.client.Invoke(prmInvoke)
if err != nil {
return nil, err
}
return new(ManageClientsRes), nil
}

View file

@ -1,40 +0,0 @@
package morphsubnet
import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
"github.com/nspcc-dev/neo-go/pkg/util"
)
// DeletePrm groups parameters of Delete method of Subnet contract.
type DeletePrm struct {
cliPrm client.InvokePrm
args [1]any
}
// SetTxHash sets hash of the transaction which spawned the notification.
// Ignore this parameter for new requests.
func (x *DeletePrm) SetTxHash(hash util.Uint256) {
x.cliPrm.SetHash(hash)
}
// SetID sets identifier of the subnet to be removed in a binary FrostFS API protocol format.
func (x *DeletePrm) SetID(id []byte) {
x.args[0] = id
}
// DeleteRes groups the resulting values of Delete method of Subnet contract.
type DeleteRes struct{}
// Delete removes subnet though the call of the corresponding method of the Subnet contract.
func (x Client) Delete(prm DeletePrm) (*DeleteRes, error) {
prm.cliPrm.SetMethod(deleteMethod)
prm.cliPrm.SetArgs(prm.args[:]...)
err := x.client.Invoke(prm.cliPrm)
if err != nil {
return nil, err
}
return new(DeleteRes), nil
}

View file

@ -1,55 +0,0 @@
package morphsubnet
import (
"errors"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
)
// GetPrm groups parameters of Get method of Subnet contract.
type GetPrm struct {
args [1]any
}
// SetID sets identifier of the subnet to be read in a binary FrostFS API protocol format.
func (x *GetPrm) SetID(id []byte) {
x.args[0] = id
}
// GetRes groups the resulting values of Get method of Subnet contract.
type GetRes struct {
info []byte
}
// Info returns information about the subnet in a binary format of FrostFS API protocol.
func (x GetRes) Info() []byte {
return x.info
}
var errEmptyResponse = errors.New("empty response")
// Get reads the subnet through the call of the corresponding method of the Subnet contract.
func (x *Client) Get(prm GetPrm) (*GetRes, error) {
var prmGet client.TestInvokePrm
prmGet.SetMethod(getMethod)
prmGet.SetArgs(prm.args[:]...)
res, err := x.client.TestInvoke(prmGet)
if err != nil {
return nil, err
}
if len(res) == 0 {
return nil, errEmptyResponse
}
data, err := client.BytesFromStackItem(res[0])
if err != nil {
return nil, err
}
return &GetRes{
info: data,
}, nil
}

View file

@ -1,58 +0,0 @@
package morphsubnet
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
)
// NodeAllowedPrm groups parameters of NodeAllowed method of Subnet contract.
type NodeAllowedPrm struct {
cliPrm client.TestInvokePrm
args [2]any
}
// SetID sets identifier of the subnet of the node in a binary FrostFS API protocol format.
func (x *NodeAllowedPrm) SetID(id []byte) {
x.args[0] = id
}
// SetNode sets public key of the node that is being checked.
func (x *NodeAllowedPrm) SetNode(id []byte) {
x.args[1] = id
}
// NodeAllowedRes groups the resulting values of NodeAllowed method of Subnet contract.
type NodeAllowedRes struct {
result bool
}
// Allowed returns true iff the node is allowed to enter the subnet.
func (x NodeAllowedRes) Allowed() bool {
return x.result
}
// NodeAllowed checks if the node is included in the subnetwork.
func (x *Client) NodeAllowed(prm NodeAllowedPrm) (*NodeAllowedRes, error) {
prm.cliPrm.SetMethod(nodeAllowedMethod)
prm.cliPrm.SetArgs(prm.args[:]...)
res, err := x.client.TestInvoke(prm.cliPrm)
if err != nil {
return nil, fmt.Errorf("could not make test invoke: %w", err)
}
if len(res) == 0 {
return nil, errEmptyResponse
}
result, err := client.BoolFromStackItem(res[0])
if err != nil {
return nil, err
}
return &NodeAllowedRes{
result: result,
}, nil
}

View file

@ -1,54 +0,0 @@
package morphsubnet
import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
// ManageNodesPrm groups parameters of node management in Subnet contract.
//
// Zero value adds node to subnet. Subnet and node IDs must be specified via setters.
type ManageNodesPrm struct {
// remove or add node
rm bool
args [2]any
}
// SetRemove marks node to be removed. By default, node is added.
func (x *ManageNodesPrm) SetRemove() {
x.rm = true
}
// SetSubnet sets identifier of the subnet in a binary NeoFS API protocol format.
func (x *ManageNodesPrm) SetSubnet(id []byte) {
x.args[0] = id
}
// SetNode sets node's public key in a binary format.
func (x *ManageNodesPrm) SetNode(id []byte) {
x.args[1] = id
}
// ManageNodesRes groups the resulting values of node management methods of Subnet contract.
type ManageNodesRes struct{}
// ManageNodes manages node list of the NeoFS subnet through Subnet contract calls.
func (x Client) ManageNodes(prm ManageNodesPrm) (*ManageNodesRes, error) {
var method string
if prm.rm {
method = removeNodeMethod
} else {
method = addNodeMethod
}
var prmInvoke client.InvokePrm
prmInvoke.SetMethod(method)
prmInvoke.SetArgs(prm.args[:]...)
err := x.client.Invoke(prmInvoke)
if err != nil {
return nil, err
}
return new(ManageNodesRes), nil
}

View file

@ -1,50 +0,0 @@
package morphsubnet
import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
"github.com/nspcc-dev/neo-go/pkg/util"
)
// PutPrm groups parameters of Put method of Subnet contract.
type PutPrm struct {
cliPrm client.InvokePrm
args [3]any
}
// SetTxHash sets hash of the transaction which spawned the notification.
// Ignore this parameter for new requests.
func (x *PutPrm) SetTxHash(hash util.Uint256) {
x.cliPrm.SetHash(hash)
}
// SetID sets identifier of the created subnet in a binary FrostFS API protocol format.
func (x *PutPrm) SetID(id []byte) {
x.args[0] = id
}
// SetOwner sets identifier of the subnet owner in a binary FrostFS API protocol format.
func (x *PutPrm) SetOwner(id []byte) {
x.args[1] = id
}
// SetInfo sets information about the created subnet in a binary FrostFS API protocol format.
func (x *PutPrm) SetInfo(id []byte) {
x.args[2] = id
}
// PutRes groups the resulting values of Put method of Subnet contract.
type PutRes struct{}
// Put creates subnet though the call of the corresponding method of the Subnet contract.
func (x Client) Put(prm PutPrm) (*PutRes, error) {
prm.cliPrm.SetMethod(putMethod)
prm.cliPrm.SetArgs(prm.args[:]...)
err := x.client.Invoke(prm.cliPrm)
if err != nil {
return nil, err
}
return new(PutRes), nil
}

View file

@ -1,63 +0,0 @@
package subnetevents
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/util"
)
// Delete structures information about the notification generated by Delete method of Subnet contract.
type Delete struct {
txHash util.Uint256
id []byte
}
// MorphEvent implements Neo:Morph Event interface.
func (Delete) MorphEvent() {}
// ID returns identifier of the removed subnet in a binary format of NeoFS API protocol.
func (x Delete) ID() []byte {
return x.id
}
// TxHash returns hash of the transaction which thrown the notification event.
// Makes sense only in notary environments.
func (x Delete) TxHash() util.Uint256 {
return x.txHash
}
// ParseDelete parses the notification about the removal of a subnet which has been thrown
// by the appropriate method of the Subnet contract.
//
// Resulting event is of Delete type.
func ParseDelete(e *state.ContainedNotificationEvent) (event.Event, error) {
var (
ev Delete
err error
)
items, err := event.ParseStackArray(e)
if err != nil {
return nil, fmt.Errorf("parse stack array: %w", err)
}
const itemNumDelete = 1
if ln := len(items); ln != itemNumDelete {
return nil, event.WrongNumberOfParameters(itemNumDelete, ln)
}
// parse ID
ev.id, err = client.BytesFromStackItem(items[0])
if err != nil {
return nil, fmt.Errorf("id item: %w", err)
}
ev.txHash = e.Container
return ev, nil
}

View file

@ -1,42 +0,0 @@
package subnetevents_test
import (
"testing"
subnetevents "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/subnet"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/stretchr/testify/require"
)
func TestParseDelete(t *testing.T) {
id := []byte("id")
t.Run("wrong number of items", func(t *testing.T) {
prms := []stackitem.Item{
stackitem.NewByteArray(nil),
stackitem.NewByteArray(nil),
}
_, err := subnetevents.ParseDelete(createNotifyEventFromItems(prms))
require.Error(t, err)
})
t.Run("wrong id item", func(t *testing.T) {
_, err := subnetevents.ParseDelete(createNotifyEventFromItems([]stackitem.Item{
stackitem.NewMap(),
}))
require.Error(t, err)
})
t.Run("correct behavior", func(t *testing.T) {
ev, err := subnetevents.ParseDelete(createNotifyEventFromItems([]stackitem.Item{
stackitem.NewByteArray(id),
}))
require.NoError(t, err)
v := ev.(subnetevents.Delete)
require.Equal(t, id, v.ID())
})
}

View file

@ -1,147 +0,0 @@
package subnetevents
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/network/payload"
"github.com/nspcc-dev/neo-go/pkg/util"
)
// Put structures information about the notification generated by Put method of Subnet contract.
type Put struct {
notaryRequest *payload.P2PNotaryRequest
txHash util.Uint256
id []byte
owner []byte
info []byte
}
// MorphEvent implements Neo:Morph Event interface.
func (Put) MorphEvent() {}
// ID returns identifier of the creating subnet in a binary format of FrostFS API protocol.
func (x Put) ID() []byte {
return x.id
}
// Owner returns subnet owner's public key in a binary format.
func (x Put) Owner() []byte {
return x.owner
}
// Info returns information about the subnet in a binary format of FrostFS API protocol.
func (x Put) Info() []byte {
return x.info
}
// TxHash returns hash of the transaction which thrown the notification event.
// Makes sense only in notary environments.
func (x Put) TxHash() util.Uint256 {
return x.txHash
}
// NotaryMainTx returns main transaction of the request in the Notary service.
// Returns nil in non-notary environments.
func (x Put) NotaryMainTx() *transaction.Transaction {
if x.notaryRequest != nil {
return x.notaryRequest.MainTransaction
}
return nil
}
// number of items in notification about subnet creation.
const itemNumPut = 3
// ParsePut parses the notification about the creation of a subnet which has been thrown
// by the appropriate method of the subnet contract.
//
// Resulting event is of Put type.
func ParsePut(e *state.ContainedNotificationEvent) (event.Event, error) {
var (
put Put
err error
)
items, err := event.ParseStackArray(e)
if err != nil {
return nil, fmt.Errorf("parse stack array: %w", err)
}
if ln := len(items); ln != itemNumPut {
return nil, event.WrongNumberOfParameters(itemNumPut, ln)
}
// parse ID
put.id, err = client.BytesFromStackItem(items[0])
if err != nil {
return nil, fmt.Errorf("id item: %w", err)
}
// parse owner
put.owner, err = client.BytesFromStackItem(items[1])
if err != nil {
return nil, fmt.Errorf("owner item: %w", err)
}
// parse info about subnet
put.info, err = client.BytesFromStackItem(items[2])
if err != nil {
return nil, fmt.Errorf("info item: %w", err)
}
put.txHash = e.Container
return put, nil
}
// ParseNotaryPut parses the notary notification about the creation of a subnet which has been
// thrown by the appropriate method of the subnet contract.
//
// Resulting event is of Put type.
func ParseNotaryPut(e event.NotaryEvent) (event.Event, error) {
var put Put
put.notaryRequest = e.Raw()
if put.notaryRequest == nil {
panic(fmt.Sprintf("nil %T in notary environment", put.notaryRequest))
}
var (
err error
prms = e.Params()
)
if ln := len(prms); ln != itemNumPut {
return nil, event.WrongNumberOfParameters(itemNumPut, ln)
}
// parse info about subnet
put.info, err = event.BytesFromOpcode(prms[0])
if err != nil {
return nil, fmt.Errorf("info param: %w", err)
}
// parse owner
put.owner, err = event.BytesFromOpcode(prms[1])
if err != nil {
return nil, fmt.Errorf("creator param: %w", err)
}
// parse ID
put.id, err = event.BytesFromOpcode(prms[2])
if err != nil {
return nil, fmt.Errorf("id param: %w", err)
}
return put, nil
}

View file

@ -1,69 +0,0 @@
package subnetevents_test
import (
"testing"
subnetevents "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/subnet"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/stretchr/testify/require"
)
func TestParsePut(t *testing.T) {
var (
id = []byte("id")
owner = []byte("owner")
info = []byte("info")
)
t.Run("wrong number of items", func(t *testing.T) {
prms := []stackitem.Item{
stackitem.NewByteArray(nil),
stackitem.NewByteArray(nil),
}
_, err := subnetevents.ParsePut(createNotifyEventFromItems(prms))
require.Error(t, err)
})
t.Run("wrong id item", func(t *testing.T) {
_, err := subnetevents.ParsePut(createNotifyEventFromItems([]stackitem.Item{
stackitem.NewMap(),
}))
require.Error(t, err)
})
t.Run("wrong owner item", func(t *testing.T) {
_, err := subnetevents.ParsePut(createNotifyEventFromItems([]stackitem.Item{
stackitem.NewByteArray(id),
stackitem.NewMap(),
}))
require.Error(t, err)
})
t.Run("wrong info item", func(t *testing.T) {
_, err := subnetevents.ParsePut(createNotifyEventFromItems([]stackitem.Item{
stackitem.NewByteArray(id),
stackitem.NewByteArray(owner),
stackitem.NewMap(),
}))
require.Error(t, err)
})
t.Run("correct behavior", func(t *testing.T) {
ev, err := subnetevents.ParsePut(createNotifyEventFromItems([]stackitem.Item{
stackitem.NewByteArray(id),
stackitem.NewByteArray(owner),
stackitem.NewByteArray(info),
}))
require.NoError(t, err)
v := ev.(subnetevents.Put)
require.Equal(t, id, v.ID())
require.Equal(t, owner, v.Owner())
require.Equal(t, info, v.Info())
})
}

View file

@ -1,69 +0,0 @@
package subnetevents
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/util"
)
// RemoveNode structure of subnet.RemoveNode notification from morph chain.
type RemoveNode struct {
subnetID []byte
nodeKey []byte
// txHash is used in notary environmental
// for calculating unique but same for
// all notification receivers values.
txHash util.Uint256
}
// MorphEvent implements Neo:Morph Event interface.
func (RemoveNode) MorphEvent() {}
// SubnetworkID returns a marshalled subnetID structure, defined in API.
func (rn RemoveNode) SubnetworkID() []byte { return rn.subnetID }
// Node is public key of the nodeKey that is being deleted.
func (rn RemoveNode) Node() []byte { return rn.nodeKey }
// TxHash returns hash of the TX with RemoveNode
// notification.
func (rn RemoveNode) TxHash() util.Uint256 { return rn.txHash }
const expectedItemNumRemoveNode = 2
// ParseRemoveNode parses notification into subnet event structure.
//
// Expects 2 stack items.
func ParseRemoveNode(e *state.ContainedNotificationEvent) (event.Event, error) {
var (
ev RemoveNode
err error
)
params, err := event.ParseStackArray(e)
if err != nil {
return nil, fmt.Errorf("could not parse stack items from notify event: %w", err)
}
if ln := len(params); ln != expectedItemNumRemoveNode {
return nil, event.WrongNumberOfParameters(expectedItemNumRemoveNode, ln)
}
ev.subnetID, err = client.BytesFromStackItem(params[0])
if err != nil {
return nil, fmt.Errorf("could not get raw subnetID: %w", err)
}
ev.nodeKey, err = client.BytesFromStackItem(params[1])
if err != nil {
return nil, fmt.Errorf("could not get raw public key of the node: %w", err)
}
ev.txHash = e.Container
return ev, nil
}

View file

@ -1,56 +0,0 @@
package subnetevents_test
import (
"testing"
. "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/subnet"
subnetid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/subnet/id"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/stretchr/testify/require"
)
func TestParseRemoveNode(t *testing.T) {
t.Run("wrong number of arguments", func(t *testing.T) {
_, err := ParseRemoveNode(createNotifyEventFromItems([]stackitem.Item{}))
require.Error(t, err)
})
t.Run("invalid item type", func(t *testing.T) {
args := []stackitem.Item{stackitem.NewMap(), stackitem.Make(123)}
_, err := ParseRemoveNode(createNotifyEventFromItems(args))
require.Error(t, err)
})
subnetID := subnetid.ID{}
subnetID.SetNumeric(123)
rawSubnetID := subnetID.Marshal()
priv, err := keys.NewPrivateKey()
require.NoError(t, err)
pub := priv.PublicKey()
t.Run("good", func(t *testing.T) {
args := []stackitem.Item{stackitem.NewByteArray(rawSubnetID), stackitem.Make(pub.Bytes())}
e, err := ParseRemoveNode(createNotifyEventFromItems(args))
require.NoError(t, err)
gotRaw := e.(RemoveNode).SubnetworkID()
require.NoError(t, err)
require.Equal(t, rawSubnetID, gotRaw)
require.Equal(t, pub.Bytes(), e.(RemoveNode).Node())
})
}
func createNotifyEventFromItems(items []stackitem.Item) *state.ContainedNotificationEvent {
return &state.ContainedNotificationEvent{
NotificationEvent: state.NotificationEvent{
Item: stackitem.NewArray(items),
},
}
}