From 2e31cd34e68958d0fad0c10add4e038b4409d216 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 18 May 2021 10:40:21 +0300 Subject: [PATCH] [#502] innerring: synchronize validators on mainnet alphabet update Signed-off-by: Evgenii Stratonikov --- pkg/innerring/innerring.go | 4 +++ .../processors/governance/handlers.go | 21 +++++++++++-- .../processors/governance/processor.go | 14 +++++++-- pkg/morph/client/client.go | 5 +++ pkg/morph/event/rolemanagement/designate.go | 31 +++++++++++++++++++ .../event/rolemanagement/designate_test.go | 27 ++++++++++++++++ 6 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 pkg/morph/event/rolemanagement/designate.go create mode 100644 pkg/morph/event/rolemanagement/designate_test.go diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 0f789db97..1f091d21d 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -490,6 +490,10 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error } } else { alphaSync = governanceProcessor.HandleAlphabetSync + err = bindMainnetProcessor(governanceProcessor, server) + if err != nil { + return nil, err + } } // create netmap processor diff --git a/pkg/innerring/processors/governance/handlers.go b/pkg/innerring/processors/governance/handlers.go index 1b41f0c9a..9b6ceb8de 100644 --- a/pkg/innerring/processors/governance/handlers.go +++ b/pkg/innerring/processors/governance/handlers.go @@ -1,12 +1,29 @@ package governance import ( + "github.com/nspcc-dev/neo-go/pkg/core/native" + "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neofs-node/pkg/morph/event" + "github.com/nspcc-dev/neofs-node/pkg/morph/event/rolemanagement" "go.uber.org/zap" ) -func (gp *Processor) HandleAlphabetSync(_ event.Event) { - gp.log.Info("new event", zap.String("type", "sync")) +func (gp *Processor) HandleAlphabetSync(e event.Event) { + var typ string + + switch et := e.(type) { + case Sync: + typ = "sync" + case rolemanagement.Designate: + if et.Role != noderoles.NeoFSAlphabet { + return + } + typ = native.DesignationEventName + default: + return + } + + gp.log.Info("new event", zap.String("type", typ)) // send event to the worker pool diff --git a/pkg/innerring/processors/governance/processor.go b/pkg/innerring/processors/governance/processor.go index 3e98150fc..e663469ff 100644 --- a/pkg/innerring/processors/governance/processor.go +++ b/pkg/innerring/processors/governance/processor.go @@ -4,11 +4,13 @@ import ( "errors" "fmt" + "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neofs-node/pkg/innerring/config" "github.com/nspcc-dev/neofs-node/pkg/morph/client" "github.com/nspcc-dev/neofs-node/pkg/morph/event" + "github.com/nspcc-dev/neofs-node/pkg/morph/event/rolemanagement" "github.com/panjf2000/ants/v2" "go.uber.org/zap" ) @@ -111,12 +113,20 @@ func New(p *Params) (*Processor, error) { // ListenerParsers for the 'event.Listener' event producer. func (gp *Processor) ListenerParsers() []event.ParserInfo { - return nil + var pi event.ParserInfo + pi.SetScriptHash(gp.mainnetClient.GetDesignateHash()) + pi.SetType(event.TypeFromString(native.DesignationEventName)) + pi.SetParser(rolemanagement.ParseDesignate) + return []event.ParserInfo{pi} } // ListenerHandlers for the 'event.Listener' event producer. func (gp *Processor) ListenerHandlers() []event.HandlerInfo { - return nil + var hi event.HandlerInfo + hi.SetScriptHash(gp.mainnetClient.GetDesignateHash()) + hi.SetType(event.TypeFromString(native.DesignationEventName)) + hi.SetHandler(gp.HandleAlphabetSync) + return []event.HandlerInfo{hi} } // TimersHandlers for the 'Timers' event producer. diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 52e8e565b..e97f63e25 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -236,6 +236,11 @@ func (c *Client) NeoFSAlphabetList() (keys.PublicKeys, error) { return list, nil } +// GetDesignateHash returns hash of the native `RoleManagement` contract. +func (c *Client) GetDesignateHash() util.Uint160 { + return c.designate +} + func (c *Client) roleList(r noderoles.Role) (keys.PublicKeys, error) { height, err := c.client.GetBlockCount() if err != nil { diff --git a/pkg/morph/event/rolemanagement/designate.go b/pkg/morph/event/rolemanagement/designate.go new file mode 100644 index 000000000..700f224fe --- /dev/null +++ b/pkg/morph/event/rolemanagement/designate.go @@ -0,0 +1,31 @@ +package rolemanagement + +import ( + "fmt" + + "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/nspcc-dev/neofs-node/pkg/morph/event" +) + +// Designate represents designation event of the mainnet RoleManagement contract. +type Designate struct { + Role noderoles.Role +} + +// MorphEvent implements Neo:Morph Event interface. +func (Designate) MorphEvent() {} + +// ParseDesignate from notification into container event structure. +func ParseDesignate(params []stackitem.Item) (event.Event, error) { + if len(params) != 2 { + return nil, event.WrongNumberOfParameters(2, len(params)) + } + + bi, err := params[0].TryInteger() + if err != nil { + return nil, fmt.Errorf("invalid stackitem type: %w", err) + } + + return Designate{Role: noderoles.Role(bi.Int64())}, nil +} diff --git a/pkg/morph/event/rolemanagement/designate_test.go b/pkg/morph/event/rolemanagement/designate_test.go new file mode 100644 index 000000000..8c1dc014e --- /dev/null +++ b/pkg/morph/event/rolemanagement/designate_test.go @@ -0,0 +1,27 @@ +package rolemanagement + +import ( + "testing" + + "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/stretchr/testify/require" +) + +func TestParseRoleUpdate(t *testing.T) { + t.Run("wrong number of arguments", func(t *testing.T) { + _, err := ParseDesignate([]stackitem.Item{}) + require.Error(t, err) + }) + t.Run("invalid item type", func(t *testing.T) { + args := []stackitem.Item{stackitem.NewMap(), stackitem.Make(123)} + _, err := ParseDesignate(args) + require.Error(t, err) + }) + t.Run("good", func(t *testing.T) { + args := []stackitem.Item{stackitem.Make(int(noderoles.NeoFSAlphabet)), stackitem.Make(123)} + e, err := ParseDesignate(args) + require.NoError(t, err) + require.Equal(t, noderoles.NeoFSAlphabet, e.(Designate).Role) + }) +}