[#1796] ir/netmap: Allow to call AddPeer with ONLINE state only

In previous implementation Inner Ring allowed storage nodes with any
state to register in the network. According to the current design, only
nodes with ONLINE state are allowed to enter the network map.

Create new `state` sub-package of `nodevalidation` package of Inner Ring
application. Define `state.NetMapCandidateValidator` type and provide
`NodeValidator` interface required by the Inner Ring's processor of
`Netmap` contract's notification events. Embed new validator into the
one used by the Inner Ring application.

From now all `AddPeer` notifications with node state other than `ONLINE`
will be denied.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2022-09-19 14:34:55 +04:00 committed by fyrchik
parent 8bf82d738b
commit 8858840751
3 changed files with 99 additions and 0 deletions

View file

@ -22,6 +22,7 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/innerring/processors/netmap"
nodevalidator "github.com/nspcc-dev/neofs-node/pkg/innerring/processors/netmap/nodevalidation"
addrvalidator "github.com/nspcc-dev/neofs-node/pkg/innerring/processors/netmap/nodevalidation/maddress"
statevalidation "github.com/nspcc-dev/neofs-node/pkg/innerring/processors/netmap/nodevalidation/state"
subnetvalidator "github.com/nspcc-dev/neofs-node/pkg/innerring/processors/netmap/nodevalidation/subnet"
"github.com/nspcc-dev/neofs-node/pkg/innerring/processors/reputation"
"github.com/nspcc-dev/neofs-node/pkg/innerring/processors/settlement"
@ -689,6 +690,8 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper, errChan chan<-
}
}
var netMapCandidateStateValidator statevalidation.NetMapCandidateValidator
// create netmap processor
server.netmapProcessor, err = netmap.New(&netmap.Params{
Log: log,
@ -711,6 +714,7 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper, errChan chan<-
),
AlphabetSyncHandler: alphaSync,
NodeValidator: nodevalidator.New(
&netMapCandidateStateValidator,
addrvalidator.New(),
locodeValidator,
subnetValidator,

View file

@ -0,0 +1,41 @@
/*
Package state collects functionality for verifying states of network map members.
NetMapCandidateValidator type provides an interface for checking the network
map candidates.
*/
package state
import (
"errors"
"github.com/nspcc-dev/neofs-sdk-go/netmap"
)
// NetMapCandidateValidator represents tool which checks state of nodes which
// are going to register in the NeoFS network (enter the network map).
//
// NetMapCandidateValidator can be instantiated using built-in var declaration
// and currently doesn't require any additional initialization.
//
// NetMapCandidateValidator implements
// github.com/nspcc-dev/neofs-node/pkg/innerring/processors/netmap.NodeValidator.
type NetMapCandidateValidator struct {
}
// VerifyAndUpdate checks state of the network map candidate described by
// netmap.NodeInfo parameter. Returns no error if status is correct, otherwise
// returns an error describing a violation of the rules:
//
// status MUST be ONLINE
//
// VerifyAndUpdate does not mutate the parameter in a binary format.
//
// See also netmap.NodeInfo.IsOnline/SetOnline.
func (x *NetMapCandidateValidator) VerifyAndUpdate(node *netmap.NodeInfo) error {
if node.IsOnline() {
return nil
}
return errors.New("invalid status: MUST be ONLINE")
}

View file

@ -0,0 +1,54 @@
package state_test
import (
"testing"
"github.com/nspcc-dev/neofs-node/pkg/innerring/processors/netmap/nodevalidation/state"
"github.com/nspcc-dev/neofs-sdk-go/netmap"
"github.com/stretchr/testify/require"
)
func TestValidator_VerifyAndUpdate(t *testing.T) {
var v state.NetMapCandidateValidator
for _, testCase := range []struct {
name string
preparer func(*netmap.NodeInfo) // modifies zero instance
valid bool // is node valid after preparation
}{
{
name: "UNDEFINED",
preparer: func(info *netmap.NodeInfo) {},
valid: false,
},
{
name: "ONLINE",
preparer: (*netmap.NodeInfo).SetOnline,
valid: true,
},
{
name: "OFFLINE",
preparer: (*netmap.NodeInfo).SetOffline,
valid: false,
},
} {
var node netmap.NodeInfo
// prepare node
testCase.preparer(&node)
// save binary representation for mutation check
binNode := node.Marshal()
err := v.VerifyAndUpdate(&node)
if testCase.valid {
require.NoError(t, err, testCase.name)
} else {
require.Error(t, err, testCase.name)
}
// check mutation
require.Equal(t, binNode, node.Marshal(), testCase.name)
}
}