From b303e4940850327f9cb6eeca0043f34b52e99b54 Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Thu, 9 Sep 2021 14:55:01 +0300 Subject: [PATCH] [#815] morph/event/netmap: Add `updateState` notary notification support Signed-off-by: Pavel Karpy --- cmd/neofs-node/morph.go | 2 +- .../processors/netmap/process_peers.go | 8 +- pkg/innerring/processors/netmap/processor.go | 38 +++++---- pkg/morph/event/netmap/update_peer.go | 17 +++- pkg/morph/event/netmap/update_peer_notary.go | 82 +++++++++++++++++++ 5 files changed, 129 insertions(+), 18 deletions(-) create mode 100644 pkg/morph/event/netmap/update_peer_notary.go diff --git a/cmd/neofs-node/morph.go b/cmd/neofs-node/morph.go index cb70a63e..f9067012 100644 --- a/cmd/neofs-node/morph.go +++ b/cmd/neofs-node/morph.go @@ -96,7 +96,7 @@ func initMorphComponents(c *cfg) { ) }) - wrap, err := wrapper.NewFromMorph(c.cfgMorph.client, c.cfgNetmap.scriptHash, 0) + wrap, err := wrapper.NewFromMorph(c.cfgMorph.client, c.cfgNetmap.scriptHash, 0, wrapper.TryNotary()) fatalOnErr(err) var netmapSource netmap.Source diff --git a/pkg/innerring/processors/netmap/process_peers.go b/pkg/innerring/processors/netmap/process_peers.go index 96f3c1e1..85e2ee57 100644 --- a/pkg/innerring/processors/netmap/process_peers.go +++ b/pkg/innerring/processors/netmap/process_peers.go @@ -84,7 +84,13 @@ func (np *Processor) processUpdatePeer(ev netmapEvent.UpdatePeer) { // again before new epoch will tick np.netmapSnapshot.flag(hex.EncodeToString(ev.PublicKey().Bytes())) - err := np.netmapClient.UpdatePeerState(ev.PublicKey().Bytes(), ev.Status()) + var err error + + if nr := ev.NotaryRequest(); nr != nil { + err = np.netmapClient.Morph().NotarySignAndInvokeTX(nr.MainTransaction) + } else { + err = np.netmapClient.UpdatePeerState(ev.PublicKey().Bytes(), ev.Status()) + } if err != nil { np.log.Error("can't invoke netmap.UpdatePeer", zap.Error(err)) } diff --git a/pkg/innerring/processors/netmap/processor.go b/pkg/innerring/processors/netmap/processor.go index 67410b45..594f8ec6 100644 --- a/pkg/innerring/processors/netmap/processor.go +++ b/pkg/innerring/processors/netmap/processor.go @@ -164,13 +164,6 @@ func (np *Processor) ListenerNotificationParsers() []event.NotificationParserInf newEpoch.SetParser(netmapEvent.ParseNewEpoch) parsers = append(parsers, newEpoch) - // update peer event - updatePeer := event.NotificationParserInfo{} - updatePeer.SetType(updatePeerStateNotification) - updatePeer.SetScriptHash(np.netmapContract) - updatePeer.SetParser(netmapEvent.ParseUpdatePeer) - parsers = append(parsers, updatePeer) - if !np.notaryDisabled { return parsers } @@ -182,6 +175,13 @@ func (np *Processor) ListenerNotificationParsers() []event.NotificationParserInf addPeer.SetParser(netmapEvent.ParseAddPeer) parsers = append(parsers, addPeer) + // update peer event + updatePeer := event.NotificationParserInfo{} + updatePeer.SetType(updatePeerStateNotification) + updatePeer.SetScriptHash(np.netmapContract) + updatePeer.SetParser(netmapEvent.ParseUpdatePeer) + parsers = append(parsers, updatePeer) + return parsers } @@ -196,13 +196,6 @@ func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI newEpoch.SetHandler(np.handleNewEpoch) handlers = append(handlers, newEpoch) - // update peer handler - updatePeer := event.NotificationHandlerInfo{} - updatePeer.SetType(updatePeerStateNotification) - updatePeer.SetScriptHash(np.netmapContract) - updatePeer.SetHandler(np.handleUpdateState) - handlers = append(handlers, updatePeer) - if !np.notaryDisabled { return handlers } @@ -214,6 +207,13 @@ func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI addPeer.SetHandler(np.handleAddPeer) handlers = append(handlers, addPeer) + // update peer handler + updatePeer := event.NotificationHandlerInfo{} + updatePeer.SetType(updatePeerStateNotification) + updatePeer.SetScriptHash(np.netmapContract) + updatePeer.SetHandler(np.handleUpdateState) + handlers = append(handlers, updatePeer) + return handlers } @@ -233,6 +233,11 @@ func (np *Processor) ListenerNotaryParsers() []event.NotaryParserInfo { p.SetParser(netmapEvent.ParseAddPeerNotary) pp = append(pp, p) + // update state + p.SetRequestType(netmapEvent.UpdateStateNotaryEvent) + p.SetParser(netmapEvent.ParseUpdatePeerNotary) + pp = append(pp, p) + return pp } @@ -252,6 +257,11 @@ func (np *Processor) ListenerNotaryHandlers() []event.NotaryHandlerInfo { h.SetHandler(np.handleAddPeer) hh = append(hh, h) + // update state + h.SetRequestType(netmapEvent.UpdateStateNotaryEvent) + h.SetHandler(np.handleUpdateState) + hh = append(hh, h) + return hh } diff --git a/pkg/morph/event/netmap/update_peer.go b/pkg/morph/event/netmap/update_peer.go index 950cc114..6c3b7bf5 100644 --- a/pkg/morph/event/netmap/update_peer.go +++ b/pkg/morph/event/netmap/update_peer.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/network/payload" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neofs-api-go/pkg/netmap" v2netmap "github.com/nspcc-dev/neofs-api-go/v2/netmap" @@ -15,6 +16,10 @@ import ( type UpdatePeer struct { publicKey *keys.PublicKey status netmap.NodeState + + // For notary notifications only. + // Contains raw transactions of notary request. + notaryRequest *payload.P2PNotaryRequest } // MorphEvent implements Neo:Morph Event interface. @@ -28,14 +33,22 @@ func (s UpdatePeer) PublicKey() *keys.PublicKey { return s.publicKey } +// NotaryRequest returns raw notary request if notification +// was received via notary service. Otherwise, returns nil. +func (s UpdatePeer) NotaryRequest() *payload.P2PNotaryRequest { + return s.notaryRequest +} + +const expectedItemNumUpdatePeer = 2 + func ParseUpdatePeer(prms []stackitem.Item) (event.Event, error) { var ( ev UpdatePeer err error ) - if ln := len(prms); ln != 2 { - return nil, event.WrongNumberOfParameters(2, ln) + if ln := len(prms); ln != expectedItemNumUpdatePeer { + return nil, event.WrongNumberOfParameters(expectedItemNumUpdatePeer, ln) } // parse public key diff --git a/pkg/morph/event/netmap/update_peer_notary.go b/pkg/morph/event/netmap/update_peer_notary.go new file mode 100644 index 00000000..8ead2010 --- /dev/null +++ b/pkg/morph/event/netmap/update_peer_notary.go @@ -0,0 +1,82 @@ +package netmap + +import ( + "crypto/elliptic" + "errors" + "fmt" + + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/vm/opcode" + "github.com/nspcc-dev/neofs-api-go/pkg/netmap" + netmapv2 "github.com/nspcc-dev/neofs-api-go/v2/netmap" + "github.com/nspcc-dev/neofs-node/pkg/morph/event" +) + +var errNilPubKey = errors.New("could not parse public key: public key is nil") + +func (s *UpdatePeer) setPublicKey(v []byte) (err error) { + if v == nil { + return errNilPubKey + } + + s.publicKey, err = keys.NewPublicKeyFromBytes(v, elliptic.P256()) + if err != nil { + return fmt.Errorf("could not parse public key: %w", err) + } + + return +} + +func (s *UpdatePeer) setStatus(v uint32) { + s.status = netmap.NodeStateFromV2(netmapv2.NodeState(v)) +} + +const ( + // UpdateStateNotaryEvent is method name for netmap state updating + // operations in `Netmap` contract. Is used as identificator for + // notary delete container requests. + UpdateStateNotaryEvent = "updateState" +) + +// ParseUpdatePeerNotary from NotaryEvent into netmap event structure. +func ParseUpdatePeerNotary(ne event.NotaryEvent) (event.Event, error) { + var ( + ev UpdatePeer + err error + + currCode opcode.Opcode + ) + + fieldNum := 0 + + for _, op := range ne.Params() { + currCode = op.Code() + + switch { + case fieldNum == 0 && opcode.PUSHDATA1 <= currCode && currCode <= opcode.PUSHDATA4: + err = ev.setPublicKey(op.Param()) + if err != nil { + return nil, err + } + + fieldNum++ + case fieldNum == 1: + state, err := event.IntFromOpcode(op) + if err != nil { + return nil, err + } + + ev.setStatus(uint32(state)) + + fieldNum++ + case fieldNum == expectedItemNumUpdatePeer: + return nil, event.UnexpectedArgNumErr(UpdateStateNotaryEvent) + default: + return nil, event.UnexpectedOpcode(UpdateStateNotaryEvent, currCode) + } + } + + ev.notaryRequest = ne.Raw() + + return ev, nil +}