Lokasi ngalangkungan proxy:   [ UP ]  
[Ngawartoskeun bug]   [Panyetelan cookie]                
Skip to content

fix: prune retained attestation state#408

Open
randygrok wants to merge 4 commits into
mainfrom
jgimeno/issue-399-attestation-retention
Open

fix: prune retained attestation state#408
randygrok wants to merge 4 commits into
mainfrom
jgimeno/issue-399-attestation-retention

Conversation

@randygrok

@randygrok randygrok commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Enables epoch-end pruning for retained attestation state, including per-height signatures.
  • Centralizes the attestation retention boundary used by pruning and MsgAttest height validation.
  • Adds tests for full attestation-state pruning, EndBlocker pruning, and retention-boundary inclusivity.
  • Documents attestation state retention behavior in the network module README.

Validation

  • go test -count=1 ./modules/network/keeper

Summary by CodeRabbit

  • New Features
    • Automatic pruning of old attestation data and related signature state at each epoch boundary using the configured retention window.
    • Attestation submissions are rejected when their height falls below the retention window to prevent recreation of pruned state.
  • Documentation
    • Expanded network module docs to clarify retention/pruning rules and the attestation event emitted when quorum is reached.
  • Tests
    • Added coverage for retention boundary calculations and epoch-boundary pruning behavior.
  • Chores
    • Increased the default retention parameter (PruneAfter) to improve the out-of-the-box retention window.

Closes #399

@randygrok randygrok requested a review from a team as a code owner June 10, 2026 16:11
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR implements attestation state retention and pruning for the network module. A new retention boundary abstraction computes which epochs and block heights should be retained based on the PruneAfter parameter. The pruning logic is refactored to use this boundary to clear old attestation bitmaps, signatures, and related state at epoch boundaries. Attestation messages are validated against the boundary to reject writes below the retention window. The implementation is documented and tested.

Changes

Attestation State Retention and Pruning

Layer / File(s) Summary
Retention boundary abstraction and computation
modules/network/keeper/keeper.go
Introduces attestationRetentionBoundary struct and helper method to compute the first retained epoch and block height from PruneAfter and EpochLength, with a guard for disabled pruning.
Pruning implementation with boundary-based cleanup
modules/network/keeper/keeper.go
Refactors PruneOldBitmaps to compute and use the retention boundary, clearing attestation bitmaps, stored info, epoch bitmaps, and signature entries for heights below the boundary.
Attestation message validation with retention enforcement
modules/network/keeper/msg_server.go
Updates Attest handler to compute and apply the retention boundary, rejecting attestations below the first retained height with boundary-aware error messages.
Epoch-end pruning orchestration
modules/network/keeper/abci.go
Integrates PruneOldBitmaps into processEpochEnd, replacing TODO placeholder code with active pruning before validator index rebuild.
Parameter configuration update
modules/network/types/params.go
Updates default PruneAfter parameter from 15 to 1000 epochs, extending the retention window for attestation state.
Documentation and test coverage
modules/network/README.md, modules/network/keeper/msg_server_test.go
Adds README section documenting the attestation retention policy and EventSoftCheckpoint emission; refactors TestAttestHeightBounds with per-case retention overrides; introduces three tests validating boundary computation, pruning behavior, and end-blocker integration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

  • evstack/ev-abci#359: Modifies the same Attest message validation in msg_server.go to enforce the attestation retention-window lower height bound and adds corresponding test coverage.

Suggested reviewers

  • julienrbrt

Poem

🐰 The rabbit hops through epochs past,
Old bitmaps pruned, retention steadfast,
Boundaries drawn with careful might,
Attestations validated right! 🌙✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title 'fix: prune retained attestation state' accurately summarizes the main change: implementing epoch-end pruning for retained attestation state with centralized retention boundary logic.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jgimeno/issue-399-attestation-retention

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@randygrok randygrok changed the title Prune retained attestation state fix: prune retained attestation state Jun 10, 2026

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
modules/network/keeper/msg_server.go (1)

55-69: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reject negative attestation heights before they become unprunable state.

When currentEpoch <= PruneAfter, boundary is nil, so an authorized attester can still write msg.Height < 0. Downstream, PruneOldBitmaps only clears AttestationBitmap and StoredAttestationInfo over [0, firstRetainedHeight), so those negative-height entries never age out.

Suggested fix
 	currentHeight := ctx.BlockHeight()
 	maxFutureHeight := currentHeight + 1
+	if msg.Height < 0 {
+		return nil, sdkerr.Wrapf(sdkerrors.ErrInvalidRequest, "attestation height must be non-negative: %d", msg.Height)
+	}
 	if msg.Height > maxFutureHeight {
 		return nil, sdkerr.Wrapf(sdkerrors.ErrInvalidRequest, "attestation height %d exceeds max allowed height %d", msg.Height, maxFutureHeight)
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/network/keeper/msg_server.go` around lines 55 - 69, Add an explicit
rejection for negative attestation heights: before using
attestationRetentionBoundary(k.attestationRetentionBoundary) or calling
boundary.prunesHeight, check if msg.Height < 0 and return an
sdkerrors.ErrInvalidRequest explaining the height is negative; this ensures when
currentEpoch <= PruneAfter (boundary == nil) callers cannot write negative
heights that PruneOldBitmaps (which only trims [0, firstRetainedHeight)) will
never remove from AttestationBitmap/StoredAttestationInfo. Use the same error
wrapping style as the existing checks so the check sits alongside the current
maxFutureHeight and boundary.prunesHeight validations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@modules/network/keeper/msg_server.go`:
- Around line 67-69: The Attest validation uses
k.attestationRetentionBoundary(ctx, k.GetCurrentEpoch(ctx)) causing the write
cutoff to advance at the start of a new epoch before pruning runs in
processEpochEnd; change the boundary calculation to use the last
completed/pruned epoch (e.g., compute lastCompletedEpoch :=
k.GetCurrentEpoch(ctx) - 1 or only advance when ctx.BlockHeight() is the epoch
boundary) and pass that into attestationRetentionBoundary so Attest rejects only
heights actually pruned by PruneOldBitmaps; update attestationRetentionBoundary
call sites (including Attest) accordingly and add a regression test exercising
EpochLength > 1 demonstrating block-start rejects do not occur until the
epoch-end prune has run.

In `@modules/network/README.md`:
- Line 130: The README's checkpoint event description is out of sync with the
actual EventSoftCheckpoint emitted by emitCheckpointHashes: update the
documentation text to list the real event fields (height, validator_hash,
commit_hash, soft_confirmed) and remove/replace references to block_hash,
attester bitmap, and voting power, or alternatively change emitCheckpointHashes
(EventSoftCheckpoint emission in abci.go) to emit the documented fields; refer
to the function emitCheckpointHashes and the EventSoftCheckpoint usage to ensure
the docs exactly match the emitted event structure.

---

Outside diff comments:
In `@modules/network/keeper/msg_server.go`:
- Around line 55-69: Add an explicit rejection for negative attestation heights:
before using attestationRetentionBoundary(k.attestationRetentionBoundary) or
calling boundary.prunesHeight, check if msg.Height < 0 and return an
sdkerrors.ErrInvalidRequest explaining the height is negative; this ensures when
currentEpoch <= PruneAfter (boundary == nil) callers cannot write negative
heights that PruneOldBitmaps (which only trims [0, firstRetainedHeight)) will
never remove from AttestationBitmap/StoredAttestationInfo. Use the same error
wrapping style as the existing checks so the check sits alongside the current
maxFutureHeight and boundary.prunesHeight validations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1f9cade7-fe32-4715-a7ef-6810375c3f74

📥 Commits

Reviewing files that changed from the base of the PR and between 2deaf94 and 0d47359.

📒 Files selected for processing (5)
  • modules/network/README.md
  • modules/network/keeper/abci.go
  • modules/network/keeper/keeper.go
  • modules/network/keeper/msg_server.go
  • modules/network/keeper/msg_server_test.go

Comment thread modules/network/keeper/msg_server.go Outdated
Comment thread modules/network/README.md
@@ -128,7 +128,20 @@ The module's `EndBlocker` is executed at the end of every block and performs the

1. **Quorum Evaluation**: It iterates through recent blocks that have received attestations and checks if the cumulative voting power of the attesters has reached the required quorum.
2. **Checkpoint Emission**: If quorum is met for a block, it emits an `EventSoftCheckpoint` with the `height`, `block_hash`, a bitmap of the participating attesters, and the total voting power.

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.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical: Event field documentation doesn't match implementation.

The documentation claims the checkpoint event includes block_hash, a bitmap of participating attesters, and total voting power. However, the actual event emitted by emitCheckpointHashes (abci.go:131-148) includes different fields:

  • Actual: height, validator_hash, commit_hash, soft_confirmed
  • Documented: height, block_hash, bitmap, voting power

This mismatch will mislead consumers trying to parse checkpoint events.

📝 Proposed fix to align documentation with actual event
-2.  **Checkpoint Emission**: If quorum is met for a block, it emits an `EventSoftCheckpoint` with the `height`, `block_hash`, a bitmap of the participating attesters, and the total voting power.
+2.  **Checkpoint Emission**: If quorum is met for a block, it emits a `checkpoint` event with the `height`, `validator_hash`, `commit_hash`, and `soft_confirmed` status.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
2. **Checkpoint Emission**: If quorum is met for a block, it emits an `EventSoftCheckpoint` with the `height`, `block_hash`, a bitmap of the participating attesters, and the total voting power.
2. **Checkpoint Emission**: If quorum is met for a block, it emits a `checkpoint` event with the `height`, `validator_hash`, `commit_hash`, and `soft_confirmed` status.
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 130-130: Spaces after list markers
Expected: 1; Actual: 2

(MD030, list-marker-space)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/network/README.md` at line 130, The README's checkpoint event
description is out of sync with the actual EventSoftCheckpoint emitted by
emitCheckpointHashes: update the documentation text to list the real event
fields (height, validator_hash, commit_hash, soft_confirmed) and remove/replace
references to block_hash, attester bitmap, and voting power, or alternatively
change emitCheckpointHashes (EventSoftCheckpoint emission in abci.go) to emit
the documented fields; refer to the function emitCheckpointHashes and the
EventSoftCheckpoint usage to ensure the docs exactly match the emitted event
structure.

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.

Define retention strategy for network attestation state

1 participant