Skip to content

core/tracker: fix inclusion trim underflow at chain start - #4662

Merged
KaloyanTanev merged 3 commits into
mainfrom
kalo/tracker-inclusion-underflow
Aug 25, 2026
Merged

core/tracker: fix inclusion trim underflow at chain start#4662
KaloyanTanev merged 3 commits into
mainfrom
kalo/tracker-inclusion-underflow

Conversation

@KaloyanTanev

@KaloyanTanev KaloyanTanev commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

The inclusion checker's unsigned slot arithmetic underflows on fresh chains: until wall slot InclCheckLag+InclMissedLag, Trim received a huge cutoff and flushed every pending submission as duty not included on-chain. Skip ticks until a slot is old enough to check, and only trim once a slot can be declared missed.

category: bug
ticket: none

@KaloyanTanev KaloyanTanev self-assigned this Aug 25, 2026
@KaloyanTanev
KaloyanTanev marked this pull request as draft August 25, 2026 09:39
The inclusion checker's slot arithmetic underflows on fresh chains:
before genesis the wall-clock offset is negative, during the first
InclCheckLag slots the checked slot goes negative, and until wall slot
InclCheckLag+InclMissedLag the trim slot goes negative. The trim
underflow makes Trim(huge) delete every pending submission and report
each fresh duty as "duty not included on-chain", failing all early
proposals on every fresh-genesis network.

Skip ticks until a slot is old enough to check, and only trim once a
slot can actually be declared missed.
@KaloyanTanev
KaloyanTanev force-pushed the kalo/tracker-inclusion-underflow branch from c73fb7f to cc9adfe Compare August 25, 2026 09:44
@KaloyanTanev
KaloyanTanev marked this pull request as ready for review August 25, 2026 09:47
@KaloyanTanev
KaloyanTanev requested a lite review from Copilot August 25, 2026 09:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes unsigned-arithmetic underflows in the tracker inclusion checker at/near genesis so fresh-chain networks don’t incorrectly trim all pending submissions and mark early duties as “not included on-chain”.

Changes:

  • Add a chain-start guard to skip inclusion checks until sinceGenesis is large enough to compute a non-underflowing checked slot.
  • Guard trimming so slot-InclMissedLag cannot underflow and trigger mass deletion/false misses.
  • Add a regression test covering the trim-underflow behavior at chain start.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
core/tracker/inclusion.go Adds chain-start guards to prevent underflow in checked-slot and trim-slot computations.
core/tracker/inclusion_internal_test.go Adds a regression test to ensure early-chain submissions are not falsely reported missed due to trim underflow.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread core/tracker/inclusion_internal_test.go Outdated
Comment thread core/tracker/inclusion.go
@codecov

codecov Bot commented Aug 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 42.85714% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 58.45%. Comparing base (e628470) to head (4660635).

Files with missing lines Patch % Lines
core/tracker/inclusion.go 42.85% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4662      +/-   ##
==========================================
+ Coverage   58.35%   58.45%   +0.09%     
==========================================
  Files         247      247              
  Lines       34094    34098       +4     
==========================================
+ Hits        19896    19931      +35     
+ Misses      11723    11684      -39     
- Partials     2475     2483       +8     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

The zero-valued checkedSlot skipped slot 0 as already-checked; start
from a MaxUint64 sentinel instead. Synchronize the chain-start
regression test on the first inclusion check rather than sleeping,
and pin it to the genesis slot so it covers both guards.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (2)

core/tracker/inclusion.go:612

  • With the new early-continue guard, the first eligible computed slot can be 0 (when wall slot == InclCheckLag). Since checkedSlot defaults to 0, the if checkedSlot == slot check will skip processing slot 0 entirely, delaying inclusion checking by one slot and potentially never checking slot 0.
			// Skip until a slot is old enough to check: the unsigned
			// arithmetic below underflows before genesis (negative elapsed
			// time) and during the first InclCheckLag slots.
			sinceGenesis := time.Since(a.genesis)
			if sinceGenesis < a.slotDuration*InclCheckLag {
				continue
			}

			slot := uint64(sinceGenesis/a.slotDuration) - InclCheckLag

core/tracker/inclusion_internal_test.go:635

  • This regression test can pass without actually exercising the buggy path if Run returns early (e.g., FetchSlotsConfig failure), and the fixed time.Sleep makes the test more timing-flaky. Prefer waiting for an observed checkBlockFunc call and for the Run goroutine to exit deterministically (e.g., via channels + require.Eventually) instead of sleeping.
	}

	// A pending proposal from slot 3: too recent to be declared missed.
	block := testutil.RandomDenebVersionedSignedProposal()
	coreBlock, err := core.NewVersionedSignedProposal(block)
	require.NoError(t, err)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

core/tracker/inclusion_internal_test.go:595

  • This test constructs an InclusionChecker without setting checkBlockAndAttsFunc. If the attestation_inclusion feature is enabled (e.g., via environment/config), InclusionChecker.Run will call checkBlockAndAtts and panic when invoking the nil function. Make the test deterministic by explicitly disabling the feature (or wiring checkBlockAndAttsFunc) within the test.
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	bmock, err := beaconmock.New(ctx)
	require.NoError(t, err)

The test wires only checkBlockFunc; disable the attestation_inclusion
feature explicitly so Run cannot take the nil checkBlockAndAttsFunc
path regardless of test ordering.
@sonarqubecloud

Copy link
Copy Markdown

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@KaloyanTanev
KaloyanTanev requested a review from pinebit August 25, 2026 10:32
@KaloyanTanev
KaloyanTanev enabled auto-merge (squash) August 25, 2026 10:39
@KaloyanTanev
KaloyanTanev merged commit ad04571 into main Aug 25, 2026
12 checks passed
@KaloyanTanev
KaloyanTanev deleted the kalo/tracker-inclusion-underflow branch August 25, 2026 10:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants