Skip to content

Commit 90db4bd

Browse files
committed
fix: seed slot throttles with a below-genesis sentinel
The zero value of lastCheckpointAheadWarnSlot equals slot index 0, so the first checkpoint-ahead warning there was swallowed (CodeRabbit). Writing the regression test surfaced that lastSlotWithForcedFork has the same collision one field over: its zero value makes isConsensusStuck treat the genesis slot as if a forced fork just happened and skip its entire body. Both now start at math.MinInt64, as does lastStuckRequestSlot in the bootstrapper for the same pattern. Pinned by TestMetaForkDetector_CheckpointAheadWarnsAtSlotIndexZero. Refs #90
1 parent a081057 commit 90db4bd

3 files changed

Lines changed: 40 additions & 0 deletions

File tree

core/process/sync/metaForkDetector.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ func NewMetaForkDetector(
4747
bfd.fork.rollBackNonce = math.MaxUint64
4848
bfd.fork.probableHighestNonce = bfd.genesisNonce
4949
bfd.fork.highestNonceReceived = bfd.genesisNonce
50+
// Sentinels below any real slot index: the zero values would otherwise
51+
// collide with slot index 0. For the warn throttle that swallows the first
52+
// checkpoint-ahead warning; for lastSlotWithForcedFork it makes
53+
// isConsensusStuck treat the genesis slot as if a forced fork just happened
54+
// and skip its entire body.
55+
bfd.lastCheckpointAheadWarnSlot.Store(math.MinInt64)
56+
bfd.fork.lastSlotWithForcedFork = math.MinInt64
5057

5158
mfd := metaForkDetector{
5259
baseForkDetector: bfd,

core/process/sync/metaForkDetector_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,3 +276,31 @@ func TestMetaForkDetector_CheckpointAheadWarnsOncePerSlot(t *testing.T) {
276276
_ = bfd.CheckFork()
277277
require.Greater(t, buff.Len(), firstLen)
278278
}
279+
280+
// Slot index 0 is the one value that would collide with an uninitialized
281+
// throttle field: without the MinInt64 sentinel stored at construction, the
282+
// first Swap(0) returns the zero value and swallows the warning entirely.
283+
func TestMetaForkDetector_CheckpointAheadWarnsAtSlotIndexZero(t *testing.T) {
284+
buff := &bytes.Buffer{}
285+
require.Nil(t, logger.AddLogObserver(buff, &checkpointAheadWarnFormatter{}))
286+
t.Cleanup(func() {
287+
require.Nil(t, logger.RemoveLogObserver(buff))
288+
})
289+
290+
sloterMock := &consensusMock.SlotManagerMock{
291+
SlotIndex: 0,
292+
TimeDurationCalled: func() time.Duration { return 0 },
293+
}
294+
bfd, err := sync.NewMetaForkDetector(sloterMock, &mock.BlackListHandlerStub{}, 0)
295+
require.Nil(t, err)
296+
297+
// checkBlockBasicValidity accepts headers one slot ahead of the local index,
298+
// so a checkpoint at slot 1 is reachable while the index still reads 0.
299+
hdr := &block.Block{Header: &block.BlockHeader{Nonce: 1, Slot: 1}}
300+
require.Nil(t, bfd.AddHeader(hdr, []byte("hash"), process.BHProcessed, nil, nil))
301+
302+
forkInfo := bfd.CheckFork()
303+
require.False(t, forkInfo.IsDetected)
304+
305+
require.Contains(t, buff.String(), "last checkpoint is ahead of the local slot index")
306+
}

core/process/sync/metablock.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package sync
22

33
import (
44
"context"
5+
"math"
56

67
"github.com/klever-io/klever-go/common"
78
"github.com/klever-io/klever-go/core"
@@ -64,6 +65,10 @@ func NewMetaBootstrap(arguments ArgMetaBootstrapper) (*MetaBootstrap, error) {
6465
isInImportMode: arguments.IsInImportMode,
6566
hasStarted: arguments.SlotManager.BeforeGenesis() || arguments.IsInImportMode || arguments.StartWithInSync,
6667
}
68+
// Sentinel below any real slot index, mirroring the fork detector's warning
69+
// throttle: the zero value would equal slot index 0 and swallow the first
70+
// burst there.
71+
base.lastStuckRequestSlot.Store(math.MinInt64)
6772

6873
if base.hasStarted {
6974
log.Warn("node starting inSync state")

0 commit comments

Comments
 (0)