[#1680] morph/netmap: Adopt to recent contract changes

After recent Netmap contract changes all read methods which return
network map (either candidates or snapshots) encode node descriptors
into same structure.

Decode `netmap.Node` contract-side structure from the call results.
Replace node state with the value from the `netmap.Node.State` field.

Signed-off-by: Leonard Lyubich <ctulhurider@gmail.com>
This commit is contained in:
Leonard Lyubich 2022-09-28 15:34:28 +04:00 committed by fyrchik
parent d6c01199c8
commit eb1fba5182
14 changed files with 135 additions and 221 deletions

View file

@ -45,7 +45,7 @@ func removeNodesCmd(cmd *cobra.Command, args []string) error {
bw := io.NewBufBinWriter() bw := io.NewBufBinWriter()
for i := range nodeKeys { for i := range nodeKeys {
emit.AppCall(bw.BinWriter, nmHash, "updateStateIR", callflag.All, emit.AppCall(bw.BinWriter, nmHash, "updateStateIR", callflag.All,
int64(netmapcontract.OfflineState), nodeKeys[i].Bytes()) int64(netmapcontract.NodeStateOffline), nodeKeys[i].Bytes())
} }
if err := emitNewEpochCall(bw, wCtx, nmHash); err != nil { if err := emitNewEpochCall(bw, wCtx, nmHash); err != nil {

2
go.mod
View file

@ -18,7 +18,7 @@ require (
github.com/nspcc-dev/neo-go v0.99.2 github.com/nspcc-dev/neo-go v0.99.2
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220809123759-3094d3e0c14b // indirect github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220809123759-3094d3e0c14b // indirect
github.com/nspcc-dev/neofs-api-go/v2 v2.13.2-0.20220919124434-cf868188ef9c github.com/nspcc-dev/neofs-api-go/v2 v2.13.2-0.20220919124434-cf868188ef9c
github.com/nspcc-dev/neofs-contract v0.15.5 github.com/nspcc-dev/neofs-contract v0.15.5-0.20220930133158-d95bc535894c
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.6.0.20220926102839-c6576c8112ee github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.6.0.20220926102839-c6576c8112ee
github.com/nspcc-dev/tzhash v1.6.1 github.com/nspcc-dev/tzhash v1.6.1
github.com/panjf2000/ants/v2 v2.4.0 github.com/panjf2000/ants/v2 v2.4.0

4
go.sum
View file

@ -456,8 +456,8 @@ github.com/nspcc-dev/neofs-api-go/v2 v2.11.1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyE
github.com/nspcc-dev/neofs-api-go/v2 v2.13.2-0.20220919124434-cf868188ef9c h1:YZwtBY9uypaShbe/NLhosDanIfxt8VhQlSLYUeFIWv8= github.com/nspcc-dev/neofs-api-go/v2 v2.13.2-0.20220919124434-cf868188ef9c h1:YZwtBY9uypaShbe/NLhosDanIfxt8VhQlSLYUeFIWv8=
github.com/nspcc-dev/neofs-api-go/v2 v2.13.2-0.20220919124434-cf868188ef9c/go.mod h1:DRIr0Ic1s+6QgdqmNFNLIqMqd7lNMJfYwkczlm1hDtM= github.com/nspcc-dev/neofs-api-go/v2 v2.13.2-0.20220919124434-cf868188ef9c/go.mod h1:DRIr0Ic1s+6QgdqmNFNLIqMqd7lNMJfYwkczlm1hDtM=
github.com/nspcc-dev/neofs-contract v0.15.3/go.mod h1:BXVZUZUJxrmmDETglXHI8+5DSgn84B9y5DoSWqEjYCs= github.com/nspcc-dev/neofs-contract v0.15.3/go.mod h1:BXVZUZUJxrmmDETglXHI8+5DSgn84B9y5DoSWqEjYCs=
github.com/nspcc-dev/neofs-contract v0.15.5 h1:6Fsr1VRaG1klCWipWWPHvVkKaVS85tcxxsNDbvVB2zk= github.com/nspcc-dev/neofs-contract v0.15.5-0.20220930133158-d95bc535894c h1:jG8gu/qLprxjh99J7qGqGiPMJPXPQ5eM0el8Cb6o0Tc=
github.com/nspcc-dev/neofs-contract v0.15.5/go.mod h1:gN5bo2TlMvLbySImmg76DVj3jVmYgti2VVlQ+h/tcr0= github.com/nspcc-dev/neofs-contract v0.15.5-0.20220930133158-d95bc535894c/go.mod h1:gN5bo2TlMvLbySImmg76DVj3jVmYgti2VVlQ+h/tcr0=
github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA= github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA=
github.com/nspcc-dev/neofs-crypto v0.2.3/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= github.com/nspcc-dev/neofs-crypto v0.2.3/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw=
github.com/nspcc-dev/neofs-crypto v0.3.0/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= github.com/nspcc-dev/neofs-crypto v0.3.0/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw=

View file

@ -40,7 +40,7 @@ func (ap *Processor) processEmit() {
return return
} }
networkMap, err := ap.netmapClient.Snapshot() networkMap, err := ap.netmapClient.NetMap()
if err != nil { if err != nil {
ap.log.Warn("can't get netmap snapshot to emit gas to storage nodes", ap.log.Warn("can't get netmap snapshot to emit gas to storage nodes",
zap.String("error", err.Error())) zap.String("error", err.Error()))

View file

@ -37,7 +37,7 @@ func (np *Processor) processNewEpoch(ev netmapEvent.NewEpoch) {
} }
// get new netmap snapshot // get new netmap snapshot
networkMap, err := np.netmapClient.Snapshot() networkMap, err := np.netmapClient.NetMap()
if err != nil { if err != nil {
np.log.Warn("can't get netmap snapshot to perform cleanup", np.log.Warn("can't get netmap snapshot to perform cleanup",
zap.String("error", err.Error())) zap.String("error", err.Error()))

View file

@ -169,14 +169,12 @@ func (np *Processor) processRemoveSubnetNode(ev subnetEvent.RemoveNode) {
return return
} }
candidateNodes := candidates.Nodes() for i := range candidates {
if !bytes.Equal(candidates[i].PublicKey(), ev.Node()) {
for i := range candidateNodes {
if !bytes.Equal(candidateNodes[i].PublicKey(), ev.Node()) {
continue continue
} }
err = candidateNodes[i].IterateSubnets(func(subNetID subnetid.ID) error { err = candidates[i].IterateSubnets(func(subNetID subnetid.ID) error {
if subNetID.Equals(subnetToRemoveFrom) { if subNetID.Equals(subnetToRemoveFrom) {
return netmap.ErrRemoveSubnet return netmap.ErrRemoveSubnet
} }
@ -198,7 +196,7 @@ func (np *Processor) processRemoveSubnetNode(ev subnetEvent.RemoveNode) {
} }
} else { } else {
prm := netmapclient.AddPeerPrm{} prm := netmapclient.AddPeerPrm{}
prm.SetNodeInfo(candidateNodes[i]) prm.SetNodeInfo(candidates[i])
prm.SetHash(ev.TxHash()) prm.SetHash(ev.TxHash())
err = np.netmapClient.AddPeer(prm) err = np.netmapClient.AddPeer(prm)

View file

@ -301,10 +301,8 @@ func (s *Server) handleSubnetRemoval(e event.Event) {
return return
} }
candidateNodes := candidates.Nodes() for i := range candidates {
s.processCandidate(delEv.TxHash(), removedID, candidates[i])
for i := range candidateNodes {
s.processCandidate(delEv.TxHash(), removedID, candidateNodes[i])
} }
} }

View file

@ -4,19 +4,13 @@ import (
"fmt" "fmt"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
netmapcontract "github.com/nspcc-dev/neofs-contract/netmap"
"github.com/nspcc-dev/neofs-node/pkg/morph/client" "github.com/nspcc-dev/neofs-node/pkg/morph/client"
"github.com/nspcc-dev/neofs-sdk-go/netmap" "github.com/nspcc-dev/neofs-sdk-go/netmap"
) )
const ( // GetNetMapByEpoch calls "snapshotByEpoch" method with the given epoch and
nodeInfoFixedPrmNumber = 1 // decodes netmap.NetMap from the response.
peerWithStateFixedPrmNumber = 2
)
// GetNetMapByEpoch receives information list about storage nodes
// through the Netmap contract call, composes network map
// from them and returns it. Returns snapshot of the specified epoch number.
func (c *Client) GetNetMapByEpoch(epoch uint64) (*netmap.NetMap, error) { func (c *Client) GetNetMapByEpoch(epoch uint64) (*netmap.NetMap, error) {
invokePrm := client.TestInvokePrm{} invokePrm := client.TestInvokePrm{}
invokePrm.SetMethod(epochSnapshotMethod) invokePrm.SetMethod(epochSnapshotMethod)
@ -28,145 +22,126 @@ func (c *Client) GetNetMapByEpoch(epoch uint64) (*netmap.NetMap, error) {
epochSnapshotMethod, err) epochSnapshotMethod, err)
} }
nm, err := unmarshalNetmap(res, epochSnapshotMethod) nm, err := decodeNetMap(res)
if err == nil { if err != nil {
nm.SetEpoch(epoch) return nil, err
} }
nm.SetEpoch(epoch)
return nm, err return nm, err
} }
// GetCandidates receives information list about candidates // GetCandidates calls "netmapCandidates" method and decodes []netmap.NodeInfo
// for the next epoch network map through the Netmap contract // from the response.
// call, composes network map from them and returns it. func (c *Client) GetCandidates() ([]netmap.NodeInfo, error) {
func (c *Client) GetCandidates() (*netmap.NetMap, error) {
invokePrm := client.TestInvokePrm{} invokePrm := client.TestInvokePrm{}
invokePrm.SetMethod(netMapCandidatesMethod) invokePrm.SetMethod(netMapCandidatesMethod)
prms, err := c.client.TestInvoke(invokePrm) res, err := c.client.TestInvoke(invokePrm)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not perform test invocation (%s): %w", netMapCandidatesMethod, err) return nil, fmt.Errorf("could not perform test invocation (%s): %w", netMapCandidatesMethod, err)
} }
candVals, err := nodeInfosFromStackItems(prms, netMapCandidatesMethod) if len(res) > 0 {
if err != nil { return decodeNodeList(res[0])
return nil, fmt.Errorf("could not parse contract response: %w", err)
} }
var nm netmap.NetMap return nil, nil
nm.SetNodes(candVals)
return &nm, nil
} }
// NetMap performs the test invoke of get network map // NetMap calls "netmap" method and decode netmap.NetMap from the response.
// method of NeoFS Netmap contract. func (c *Client) NetMap() (*netmap.NetMap, error) {
func (c *Client) NetMap() ([][]byte, error) {
invokePrm := client.TestInvokePrm{} invokePrm := client.TestInvokePrm{}
invokePrm.SetMethod(netMapMethod) invokePrm.SetMethod(netMapMethod)
prms, err := c.client.TestInvoke(invokePrm) res, err := c.client.TestInvoke(invokePrm)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not perform test invocation (%s): %w", return nil, fmt.Errorf("could not perform test invocation (%s): %w",
netMapMethod, err) netMapMethod, err)
} }
return peersFromStackItems(prms, netMapMethod) return decodeNetMap(res)
} }
func nodeInfosFromStackItems(stack []stackitem.Item, method string) ([]netmap.NodeInfo, error) { func decodeNetMap(resStack []stackitem.Item) (*netmap.NetMap, error) {
if ln := len(stack); ln != 1 { var nm netmap.NetMap
return nil, fmt.Errorf("unexpected stack item count (%s): %d", method, ln)
}
netmapNodes, err := client.ArrayFromStackItem(stack[0]) if len(resStack) > 0 {
nodes, err := decodeNodeList(resStack[0])
if err != nil { if err != nil {
return nil, fmt.Errorf("could not get stack item array from stack item (%s): %w", method, err) return nil, err
} }
res := make([]netmap.NodeInfo, len(netmapNodes)) nm.SetNodes(nodes)
for i := range netmapNodes {
err := stackItemToNodeInfo(netmapNodes[i], &res[i])
if err != nil {
return nil, fmt.Errorf("could not parse stack item (Peer #%d): %w", i, err)
}
} }
return res, nil return &nm, nil
} }
func stackItemToNodeInfo(prm stackitem.Item, res *netmap.NodeInfo) error { func decodeNodeList(itemNodes stackitem.Item) ([]netmap.NodeInfo, error) {
prms, err := client.ArrayFromStackItem(prm) itemArrNodes, err := client.ArrayFromStackItem(itemNodes)
if err != nil { if err != nil {
return fmt.Errorf("could not get stack item array (PeerWithState): %w", err) return nil, fmt.Errorf("decode item array of nodes from the response item: %w", err)
} else if ln := len(prms); ln != peerWithStateFixedPrmNumber {
return fmt.Errorf(
"unexpected stack item count (PeerWithState): expected %d, has %d",
peerWithStateFixedPrmNumber,
ln,
)
} }
peer, err := peerInfoFromStackItem(prms[0]) var nodes []netmap.NodeInfo
if len(itemArrNodes) > 0 {
nodes = make([]netmap.NodeInfo, len(itemArrNodes))
for i := range itemArrNodes {
err = decodeNodeInfo(&nodes[i], itemArrNodes[i])
if err != nil { if err != nil {
return fmt.Errorf("could not get bytes from 'node' field of PeerWithState: %w", err) return nil, fmt.Errorf("decode node #%d: %w", i+1, err)
} else if err = res.Unmarshal(peer); err != nil { }
return fmt.Errorf("can't unmarshal peer info: %w", err) }
} }
// state return nodes, nil
state, err := client.IntFromStackItem(prms[1]) }
func decodeNodeInfo(dst *netmap.NodeInfo, itemNode stackitem.Item) error {
nodeFields, err := client.ArrayFromStackItem(itemNode)
if err != nil { if err != nil {
return fmt.Errorf("could not get int from 'state' field of PeerWithState: %w", err) return fmt.Errorf("decode item array of node fields: %w", err)
} }
switch state { var node netmapcontract.Node
case 1:
res.SetOnline() if len(nodeFields) > 0 {
case 2: node.BLOB, err = client.BytesFromStackItem(nodeFields[0])
res.SetOffline() if err != nil {
return fmt.Errorf("decode node info BLOB: %w", err)
}
}
node.State = netmapcontract.NodeStateOnline
if len(nodeFields) > 1 {
state, err := client.IntFromStackItem(nodeFields[1])
if err != nil {
return fmt.Errorf("decode integer from 2nd item: %w", err)
}
node.State = netmapcontract.NodeState(state)
}
err = dst.Unmarshal(node.BLOB)
if err != nil {
return fmt.Errorf("decode node info: %w", err)
}
switch node.State {
default:
return fmt.Errorf("unsupported state %v", node.State)
case netmapcontract.NodeStateOnline:
dst.SetOnline()
case netmapcontract.NodeStateOffline:
dst.SetOffline()
case netmapcontract.NodeStateMaintenance:
dst.SetMaintenance()
} }
return nil return nil
} }
func peersFromStackItems(stack []stackitem.Item, method string) ([][]byte, error) {
if ln := len(stack); ln != 1 {
return nil, fmt.Errorf("unexpected stack item count (%s): %d",
method, ln)
}
peers, err := client.ArrayFromStackItem(stack[0])
if err != nil {
return nil, fmt.Errorf("could not get stack item array from stack item (%s): %w",
method, err)
}
res := make([][]byte, 0, len(peers))
for i := range peers {
peer, err := peerInfoFromStackItem(peers[i])
if err != nil {
return nil, fmt.Errorf("could not parse stack item (Peer #%d): %w", i, err)
}
res = append(res, peer)
}
return res, nil
}
func peerInfoFromStackItem(prm stackitem.Item) ([]byte, error) {
prms, err := client.ArrayFromStackItem(prm)
if err != nil {
return nil, fmt.Errorf("could not get stack item array (PeerInfo): %w", err)
} else if ln := len(prms); ln != nodeInfoFixedPrmNumber {
return nil, fmt.Errorf(
"unexpected stack item count (PeerInfo): expected %d, has %d",
nodeInfoFixedPrmNumber,
ln,
)
}
return client.BytesFromStackItem(prms[0])
}

View file

@ -19,10 +19,12 @@ func Test_stackItemsToNodeInfos(t *testing.T) {
rand.Read(pub) rand.Read(pub)
switch i % 3 { switch i % 3 {
case int(netmapcontract.OfflineState): default:
expected[i].SetOffline() expected[i].SetOffline()
case int(netmapcontract.OnlineState): case int(netmapcontract.NodeStateOnline):
expected[i].SetOnline() expected[i].SetOnline()
case int(netmapcontract.NodeStateMaintenance):
expected[i].SetMaintenance()
} }
expected[i].SetPublicKey(pub) expected[i].SetPublicKey(pub)
@ -38,20 +40,20 @@ func Test_stackItemsToNodeInfos(t *testing.T) {
switch { switch {
case expected[i].IsOnline(): case expected[i].IsOnline():
state = int64(netmapcontract.OnlineState) state = int64(netmapcontract.NodeStateOnline)
case expected[i].IsOffline(): case expected[i].IsOffline():
state = int64(netmapcontract.OfflineState) state = int64(netmapcontract.NodeStateOffline)
case expected[i].IsMaintenance():
state = int64(netmapcontract.NodeStateMaintenance)
} }
items[i] = stackitem.NewStruct([]stackitem.Item{ items[i] = stackitem.NewStruct([]stackitem.Item{
stackitem.NewStruct([]stackitem.Item{
stackitem.NewByteArray(data), stackitem.NewByteArray(data),
}),
stackitem.NewBigInteger(big.NewInt(state)), stackitem.NewBigInteger(big.NewInt(state)),
}) })
} }
actual, err := nodeInfosFromStackItems([]stackitem.Item{stackitem.NewArray(items)}, "") actual, err := decodeNodeList(stackitem.NewArray(items))
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, expected, actual) require.Equal(t, expected, actual)
} }

View file

@ -1,28 +1,12 @@
package netmap package netmap
import ( import (
"fmt"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/nspcc-dev/neofs-node/pkg/morph/client" "github.com/nspcc-dev/neofs-node/pkg/morph/client"
"github.com/nspcc-dev/neofs-sdk-go/netmap" "github.com/nspcc-dev/neofs-sdk-go/netmap"
) )
// GetNetMap receives information list about storage nodes // GetNetMap calls "snapshot" method and decodes netmap.NetMap from the response.
// through the Netmap contract call, composes network map
// from them and returns it. With diff == 0 returns current
// network map, else return snapshot of previous network map.
func (c *Client) GetNetMap(diff uint64) (*netmap.NetMap, error) { func (c *Client) GetNetMap(diff uint64) (*netmap.NetMap, error) {
return c.getNetMap(diff)
}
// Snapshot returns current netmap node infos.
// Consider using pkg/morph/client/netmap for this.
func (c *Client) Snapshot() (*netmap.NetMap, error) {
return c.getNetMap(0)
}
func (c *Client) getNetMap(diff uint64) (*netmap.NetMap, error) {
prm := client.TestInvokePrm{} prm := client.TestInvokePrm{}
prm.SetMethod(snapshotMethod) prm.SetMethod(snapshotMethod)
prm.SetArgs(diff) prm.SetArgs(diff)
@ -32,24 +16,5 @@ func (c *Client) getNetMap(diff uint64) (*netmap.NetMap, error) {
return nil, err return nil, err
} }
return unmarshalNetmap(res, snapshotMethod) return decodeNetMap(res)
}
func unmarshalNetmap(items []stackitem.Item, method string) (*netmap.NetMap, error) {
rawPeers, err := peersFromStackItems(items, method)
if err != nil {
return nil, err
}
result := make([]netmap.NodeInfo, len(rawPeers))
for i := range rawPeers {
if err := result[i].Unmarshal(rawPeers[i]); err != nil {
return nil, fmt.Errorf("can't unmarshal node info (%s): %w", method, err)
}
}
var nm netmap.NetMap
nm.SetNodes(result)
return &nm, nil
} }

View file

@ -7,18 +7,11 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/morph/client" "github.com/nspcc-dev/neofs-node/pkg/morph/client"
) )
// TODO: enum can become redundant after neofs-contract#270
const (
stateOffline int8 = iota
stateOnline
stateMaintenance
)
// UpdatePeerPrm groups parameters of UpdatePeerState operation. // UpdatePeerPrm groups parameters of UpdatePeerState operation.
type UpdatePeerPrm struct { type UpdatePeerPrm struct {
key []byte key []byte
state int8 // state enum value state netmap.NodeState
client.InvokePrmOptional client.InvokePrmOptional
} }
@ -32,14 +25,14 @@ func (u *UpdatePeerPrm) SetKey(key []byte) {
// //
// Zero UpdatePeerPrm marks node as "offline". // Zero UpdatePeerPrm marks node as "offline".
func (u *UpdatePeerPrm) SetOnline() { func (u *UpdatePeerPrm) SetOnline() {
u.state = stateOnline u.state = netmap.NodeStateOnline
} }
// SetMaintenance marks node to be switched into "maintenance" state. // SetMaintenance marks node to be switched into "maintenance" state.
// //
// Zero UpdatePeerPrm marks node as "offline". // Zero UpdatePeerPrm marks node as "offline".
func (u *UpdatePeerPrm) SetMaintenance() { func (u *UpdatePeerPrm) SetMaintenance() {
u.state = stateMaintenance u.state = netmap.NodeStateMaintenance
} }
// UpdatePeerState changes peer status through Netmap contract call. // UpdatePeerState changes peer status through Netmap contract call.
@ -53,22 +46,9 @@ func (c *Client) UpdatePeerState(p UpdatePeerPrm) error {
method += "IR" method += "IR"
} }
state := netmap.OfflineState // pre-assign since type of value is unexported
switch p.state {
default:
panic(fmt.Sprintf("unexpected node's state value %v", p.state))
case stateOffline:
// already set above
case stateOnline:
state = netmap.OnlineState
case stateMaintenance:
state = netmap.OfflineState + 1 // FIXME: use named constant after neofs-contract#269
}
prm := client.InvokePrm{} prm := client.InvokePrm{}
prm.SetMethod(method) prm.SetMethod(method)
prm.SetArgs(int64(state), p.key) prm.SetArgs(int64(p.state), p.key)
prm.InvokePrmOptional = p.InvokePrmOptional prm.InvokePrmOptional = p.InvokePrmOptional
if err := c.client.Invoke(prm); err != nil { if err := c.client.Invoke(prm); err != nil {

View file

@ -12,17 +12,10 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/morph/event" "github.com/nspcc-dev/neofs-node/pkg/morph/event"
) )
// TODO: enum can become redundant after neofs-contract#270
const (
_ int8 = iota
stateOnline
stateMaintenance
)
type UpdatePeer struct { type UpdatePeer struct {
publicKey *keys.PublicKey publicKey *keys.PublicKey
state int8 // state enum value state netmap.NodeState
// For notary notifications only. // For notary notifications only.
// Contains raw transactions of notary request. // Contains raw transactions of notary request.
@ -35,13 +28,13 @@ func (UpdatePeer) MorphEvent() {}
// Online returns true if node's state is requested to be switched // Online returns true if node's state is requested to be switched
// to "online". // to "online".
func (s UpdatePeer) Online() bool { func (s UpdatePeer) Online() bool {
return s.state == stateOnline return s.state == netmap.NodeStateOnline
} }
// Maintenance returns true if node's state is requested to be switched // Maintenance returns true if node's state is requested to be switched
// to "maintenance". // to "maintenance".
func (s UpdatePeer) Maintenance() bool { func (s UpdatePeer) Maintenance() bool {
return s.state == stateMaintenance return s.state == netmap.NodeStateMaintenance
} }
func (s UpdatePeer) PublicKey() *keys.PublicKey { func (s UpdatePeer) PublicKey() *keys.PublicKey {
@ -54,6 +47,18 @@ func (s UpdatePeer) NotaryRequest() *payload.P2PNotaryRequest {
return s.notaryRequest return s.notaryRequest
} }
func (s *UpdatePeer) decodeState(state int64) error {
switch s.state = netmap.NodeState(state); s.state {
default:
return fmt.Errorf("unsupported node state %d", state)
case
netmap.NodeStateOffline,
netmap.NodeStateOnline,
netmap.NodeStateMaintenance:
return nil
}
}
const expectedItemNumUpdatePeer = 2 const expectedItemNumUpdatePeer = 2
func ParseUpdatePeer(e *state.ContainedNotificationEvent) (event.Event, error) { func ParseUpdatePeer(e *state.ContainedNotificationEvent) (event.Event, error) {
@ -88,14 +93,9 @@ func ParseUpdatePeer(e *state.ContainedNotificationEvent) (event.Event, error) {
return nil, fmt.Errorf("could not get node status: %w", err) return nil, fmt.Errorf("could not get node status: %w", err)
} }
switch st { err = ev.decodeState(st)
default: if err != nil {
return nil, fmt.Errorf("unsupported node state %d", st) return nil, err
case int64(netmap.OfflineState):
case int64(netmap.OnlineState):
ev.state = stateOnline
case int64(netmap.OfflineState) + 1: // FIXME: use named constant after neofs-contract#269
ev.state = stateMaintenance
} }
return ev, nil return ev, nil

View file

@ -7,7 +7,6 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/nspcc-dev/neofs-contract/netmap"
"github.com/nspcc-dev/neofs-node/pkg/morph/event" "github.com/nspcc-dev/neofs-node/pkg/morph/event"
) )
@ -61,14 +60,9 @@ func ParseUpdatePeerNotary(ne event.NotaryEvent) (event.Event, error) {
return nil, err return nil, err
} }
switch state { err = ev.decodeState(state)
default: if err != nil {
return nil, fmt.Errorf("unsupported node state %d", err) return nil, err
case int64(netmap.OfflineState):
case int64(netmap.OnlineState):
ev.state = stateOnline
case int64(netmap.OfflineState) + 1: // FIXME: use named constant after neofs-contract#269
ev.state = stateMaintenance
} }
fieldNum++ fieldNum++

View file

@ -6,6 +6,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/nspcc-dev/neofs-contract/netmap"
"github.com/nspcc-dev/neofs-node/pkg/morph/event" "github.com/nspcc-dev/neofs-node/pkg/morph/event"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -43,15 +44,16 @@ func TestParseUpdatePeer(t *testing.T) {
}) })
t.Run("correct behavior", func(t *testing.T) { t.Run("correct behavior", func(t *testing.T) {
const state = netmap.NodeStateMaintenance
ev, err := ParseUpdatePeer(createNotifyEventFromItems([]stackitem.Item{ ev, err := ParseUpdatePeer(createNotifyEventFromItems([]stackitem.Item{
stackitem.NewBigInteger(new(big.Int).SetInt64(1)), stackitem.NewBigInteger(big.NewInt(int64(state))),
stackitem.NewByteArray(publicKey.Bytes()), stackitem.NewByteArray(publicKey.Bytes()),
})) }))
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, UpdatePeer{ require.Equal(t, UpdatePeer{
publicKey: publicKey, publicKey: publicKey,
state: stateOnline, state: state,
}, ev) }, ev)
}) })
} }