From 4770cb8bf61464a63ec03bf36fba9e78f933219c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 30 Mar 2022 13:16:41 +0300 Subject: [PATCH] [#1208] innerring: Disallow to tick timer twice on the same height Provide current heights as an argument to ticker. Zero height disables any checks, thus corresponding to the old behaviour. If non-zero height is used, ignore the tick if the height is less than the timer tick state. Signed-off-by: Evgenii Stratonikov --- pkg/innerring/blocktimer.go | 4 +-- pkg/innerring/innerring.go | 2 +- pkg/morph/timer/block.go | 15 +++++++--- pkg/morph/timer/block_test.go | 55 ++++++++++++++++++++++++++++++++++- 4 files changed, 68 insertions(+), 8 deletions(-) diff --git a/pkg/innerring/blocktimer.go b/pkg/innerring/blocktimer.go index 85d35bc11..0fe4daed3 100644 --- a/pkg/innerring/blocktimer.go +++ b/pkg/innerring/blocktimer.go @@ -66,9 +66,9 @@ func (s *Server) startBlockTimers() error { return nil } -func (s *Server) tickTimers() { +func (s *Server) tickTimers(h uint32) { for i := range s.blockTimers { - s.blockTimers[i].Tick() + s.blockTimers[i].Tick(h) } } diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 24792458f..2d8a83268 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -241,7 +241,7 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) { zap.Uint32("block_index", b.Index)) } - s.tickTimers() + s.tickTimers(b.Index) }) if !s.withoutMainNet { diff --git a/pkg/morph/timer/block.go b/pkg/morph/timer/block.go index c3fea906f..a8b6b78c9 100644 --- a/pkg/morph/timer/block.go +++ b/pkg/morph/timer/block.go @@ -27,6 +27,8 @@ type BlockTimer struct { cur, tgt uint32 + last uint32 + h BlockTickHandler ps []BlockTimer @@ -159,13 +161,18 @@ func (t *BlockTimer) reset() { // Tick ticks one block in the BlockTimer. // // Executes all callbacks which are awaiting execution at the new block. -func (t *BlockTimer) Tick() { +func (t *BlockTimer) Tick(h uint32) { t.mtx.Lock() - t.tick() + t.tick(h) t.mtx.Unlock() } -func (t *BlockTimer) tick() { +func (t *BlockTimer) tick(h uint32) { + if h != 0 && t.last == h { + return + } + + t.last = h t.cur++ if t.cur == t.tgt { @@ -182,6 +189,6 @@ func (t *BlockTimer) tick() { } for i := range t.ps { - t.ps[i].tick() + t.ps[i].tick(h) } } diff --git a/pkg/morph/timer/block_test.go b/pkg/morph/timer/block_test.go index c5d6525f5..2d4afc4e0 100644 --- a/pkg/morph/timer/block_test.go +++ b/pkg/morph/timer/block_test.go @@ -9,7 +9,7 @@ import ( func tickN(t *timer.BlockTimer, n uint32) { for i := uint32(0); i < n; i++ { - t.Tick() + t.Tick(0) } } @@ -159,3 +159,56 @@ func TestNewOneTickTimer(t *testing.T) { require.Equal(t, 1, detlaCallCounter) }) } + +func TestBlockTimer_TickSameHeight(t *testing.T) { + var baseCounter, deltaCounter int + + blockDur := uint32(2) + bt := timer.NewBlockTimer( + func() (uint32, error) { return blockDur, nil }, + func() { baseCounter++ }) + bt.OnDelta(2, 1, func() { + deltaCounter++ + }) + require.NoError(t, bt.Reset()) + + check := func(t *testing.T, h uint32, base, delta int) { + for i := 0; i < 2*int(blockDur); i++ { + bt.Tick(h) + require.Equal(t, base, baseCounter) + require.Equal(t, delta, deltaCounter) + } + } + + check(t, 1, 0, 0) + check(t, 2, 1, 0) + check(t, 3, 1, 0) + check(t, 4, 2, 1) + + t.Run("works the same way after `Reset()`", func(t *testing.T) { + t.Run("same block duration", func(t *testing.T) { + require.NoError(t, bt.Reset()) + baseCounter = 0 + deltaCounter = 0 + + check(t, 1, 0, 0) + check(t, 2, 1, 0) + check(t, 3, 1, 0) + check(t, 4, 2, 1) + }) + t.Run("different block duration", func(t *testing.T) { + blockDur = 3 + + require.NoError(t, bt.Reset()) + baseCounter = 0 + deltaCounter = 0 + + check(t, 1, 0, 0) + check(t, 2, 0, 0) + check(t, 3, 1, 0) + check(t, 4, 1, 0) + check(t, 5, 1, 0) + check(t, 6, 2, 1) + }) + }) +}