[#815] morph/event/netmap: Add updateState notary notification support

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
Pavel Karpy 2021-09-09 14:55:01 +03:00 committed by Alex Vanin
parent 74afcbe409
commit b303e49408
5 changed files with 129 additions and 18 deletions

View file

@ -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

View file

@ -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))
}

View file

@ -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
}

View file

@ -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

View file

@ -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
}