From 8858840751ea0613d04d9df1bf2142b7ddd3fdab Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Mon, 19 Sep 2022 14:34:55 +0400 Subject: [PATCH] [#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 --- pkg/innerring/innerring.go | 4 ++ .../netmap/nodevalidation/state/validator.go | 41 ++++++++++++++ .../nodevalidation/state/validator_test.go | 54 +++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 pkg/innerring/processors/netmap/nodevalidation/state/validator.go create mode 100644 pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 4289fafb7..d7b91ec58 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -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, diff --git a/pkg/innerring/processors/netmap/nodevalidation/state/validator.go b/pkg/innerring/processors/netmap/nodevalidation/state/validator.go new file mode 100644 index 000000000..79093dde5 --- /dev/null +++ b/pkg/innerring/processors/netmap/nodevalidation/state/validator.go @@ -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") +} diff --git a/pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go b/pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go new file mode 100644 index 000000000..3d08a02d8 --- /dev/null +++ b/pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go @@ -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) + } +}