From 62efa3f098177407faf1cc92ce7b078789cf3358 Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Wed, 21 Jul 2021 18:15:56 +0300 Subject: [PATCH] [#708] innerring: Synchronize initial epoch tick When Inner Ring node starts, it should sync nearest epoch tick event based on the block of the latest epoch. Otherwise epoch ticking can be stopped, because ballots or notary transactions are valid for limited period of time. Signed-off-by: Alex Vanin --- pkg/innerring/innerring.go | 58 +++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index ec166b4f3..907038c9b 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -25,6 +25,7 @@ import ( "github.com/nspcc-dev/neofs-node/pkg/innerring/processors/reputation" "github.com/nspcc-dev/neofs-node/pkg/innerring/processors/settlement" auditSettlement "github.com/nspcc-dev/neofs-node/pkg/innerring/processors/settlement/audit" + timerEvent "github.com/nspcc-dev/neofs-node/pkg/innerring/timers" "github.com/nspcc-dev/neofs-node/pkg/morph/client" auditWrapper "github.com/nspcc-dev/neofs-node/pkg/morph/client/audit/wrapper" balanceWrapper "github.com/nspcc-dev/neofs-node/pkg/morph/client/balance/wrapper" @@ -79,10 +80,14 @@ type ( sideNotaryConfig *notaryConfig // internal variables - key *keys.PrivateKey - pubKey []byte - contracts *contracts - predefinedValidators keys.PublicKeys + key *keys.PrivateKey + pubKey []byte + contracts *contracts + predefinedValidators keys.PublicKeys + initialEpochTickDelta uint32 + + // runtime processors + netmapProcessor *netmap.Processor workers []func(context.Context) @@ -201,6 +206,14 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) { zap.String("error", err.Error())) } + // tick initial epoch + initialEpochTicker := timer.NewOneTickTimer( + timer.StaticBlockMeter(s.initialEpochTickDelta), + func() { + s.netmapProcessor.HandleNewEpochTick(timerEvent.NewEpochTick{}) + }) + s.addBlockTimer(initialEpochTicker) + morphErr := make(chan error) mainnnetErr := make(chan error) @@ -564,7 +577,7 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error } // create netmap processor - netmapProcessor, err := netmap.New(&netmap.Params{ + server.netmapProcessor, err = netmap.New(&netmap.Params{ Log: log, PoolSize: cfg.GetInt("workers.netmap"), NetmapContract: server.contracts.netmap, @@ -591,7 +604,7 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error return nil, err } - err = bindMorphProcessor(netmapProcessor, server) + err = bindMorphProcessor(server.netmapProcessor, server) if err != nil { return nil, err } @@ -708,7 +721,7 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error // initialize epoch timers server.epochTimer = newEpochTimer(&epochTimerArgs{ l: server.log, - nm: netmapProcessor, + nm: server.netmapProcessor, cnrWrapper: cnrClient, epoch: server, epochDuration: globalConfig.EpochDuration, @@ -966,6 +979,12 @@ func (s *Server) initConfigFromBlockchain() error { return fmt.Errorf("can't read balance contract precision: %w", err) } + // get next epoch delta tick + s.initialEpochTickDelta, err = s.nextEpochBlockDelta() + if err != nil { + return err + } + s.epochCounter.Store(epoch) s.precision.SetBalancePrecision(balancePrecision) @@ -974,11 +993,36 @@ func (s *Server) initConfigFromBlockchain() error { zap.Bool("alphabet", s.IsAlphabet()), zap.Uint64("epoch", epoch), zap.Uint32("precision", balancePrecision), + zap.Uint32("init_epoch_tick_delta", s.initialEpochTickDelta), ) return nil } +func (s *Server) nextEpochBlockDelta() (uint32, error) { + epochBlock, err := s.netmapClient.LastEpochBlock() + if err != nil { + return 0, fmt.Errorf("can't read last epoch block: %w", err) + } + + blockHeight, err := s.morphClient.BlockCount() + if err != nil { + return 0, fmt.Errorf("can't get side chain height: %w", err) + } + + epochDuration, err := s.netmapClient.EpochDuration() + if err != nil { + return 0, fmt.Errorf("can't get epoch duration: %w", err) + } + + delta := uint32(epochDuration) + epochBlock + if delta < blockHeight { + return 0, nil + } + + return delta - blockHeight, nil +} + // onlyActiveHandler wrapper around event handler that executes it // only if inner ring node state is active. func (s *Server) onlyActiveEventHandler(f event.Handler) event.Handler {