Skip to content

feat(audit): finalize LEP-6 consensus gap fixes#122

Merged
j-rafique merged 1 commit intoLEP-6-foundationfrom
LEP-6-consensus-gap-fixes
Apr 27, 2026
Merged

feat(audit): finalize LEP-6 consensus gap fixes#122
j-rafique merged 1 commit intoLEP-6-foundationfrom
LEP-6-consensus-gap-fixes

Conversation

@j-rafique
Copy link
Copy Markdown
Contributor

No description provided.

@j-rafique j-rafique self-assigned this Apr 22, 2026
@roomote-v0
Copy link
Copy Markdown

roomote-v0 Bot commented Apr 22, 2026

Rooviewer Checkmark   Follow task

Re-reviewed commit 114f175 (CP1 must-fix items). All three previously-flagged issues are now resolved: indexed lookups replace full-table scans, errorsmod.Wrapf replaces fmt.Errorf, and PruneOldEpochs now prunes st/rrs-tt/, st/spt-tbe/, and st/spt/ via dedicated helpers (pruneSupernodeWindowReporter, pruneTargetBucketEpoch, pruneStorageProofTranscripts). No net-new issues found. Approving.

  • hasIndependentReporterPassInWindow and hasCleanRecheckInWindow perform full-table scans over reporter-result and transcript stores (O(total_records) per contradiction check) -- consider adding narrower indexes
  • linkStorageTruthRecheckTranscript returns a plain fmt.Errorf instead of wrapping with a registered module error code
  • New secondary indexes st/rrs-tt/, st/spt-tbe/, and primary transcript store st/spt/ are never pruned in PruneOldEpochs, leading to unbounded state growth
Previous reviews

Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues.

Comment thread x/audit/v1/keeper/storage_truth_fact_indexes.go
Comment thread x/audit/v1/keeper/storage_truth_fact_indexes.go Outdated
@mateeullahmalik
Copy link
Copy Markdown
Contributor

Production-gate review by Zee — 4 findings

Methodology: full file-by-file read of every non-generated changed file in this PR's diff (pr-122 vs its base branch), cross-checked against:

  • LEP-6 spec (Notion source of truth)
  • invariant-first-coding skill (write-path enumeration, sibling symmetry, single source of truth, post-fix re-audit)
  • Cosmos SDK consensus discipline (no float, no map iteration, bounded EndBlock, genesis round-trip, errorsmod wrapping)

Status legend: each finding's status is computed at the PR #122 stack-tip (consensus-gap-fixes commit a51c439), so 'FIXED' means a downstream PR in the stack already addresses it; 'OPEN' means it is still present at the tip and must be fixed before merge / Phase-2 activation. Severity rubric in the charter (~/work/lep6-review/ctx/charter.md): CRITICAL = consensus halt / state corruption / non-determinism in ABCI; HIGH = spec mismatch with economic impact, missing genesis round-trip, replay enabler; MEDIUM = invariant asymmetry without immediate exploit, unbounded loop with practical bound, missing param validation.

Severity breakdown: MEDIUM=4


122-F1 — Per-storage-proof-result unbounded transcript-prefix scans in DeliverTx

  • Severity: MEDIUM
  • File: x/audit/v1/keeper/msg_submit_epoch_report_storage_proofs.go (~239-286), storage_truth_fact_indexes.go (~256-311)
  • Status at PR feat(audit): finalize LEP-6 consensus gap fixes #122 tip: OPEN — coupled with PR audit: implement storage truth enforcement and self-healing lifecycle #121 Finding 6. Build secondary indexes keyed by (target, bucket, epoch) for the consistency check and (ticket, target, epoch) for the contradiction helpers, so iterators can Iterator(startKey, endKey) over only the relevant epoch window.
  • What: hasObservedEligibleTicketForTargetBucketInWindow, hasIndependentReporterPassInWindow, hasCleanRecheckInWindow iterate the entire transcript / reporter-result prefix and JSON-Unmarshal every value, called per StorageProofResult inside SubmitEpochReport. O(N × results) per tx where N is full retained set. Charter §3 unbounded-loop-in-DeliverTx anti-pattern; invariant-first Anti-pattern 10 (cheap by inspection).

122-F2 — Cascade finalization aborts on legacy 0-count metadata

  • Severity: MEDIUM
  • File: x/action/v1/keeper/action.go
  • Lines: 247-262 (new finalize hook)
  • Status at PR feat(audit): finalize LEP-6 consensus gap fixes #122 tip: OPEN — mirror the Process/GetUpdatedMetadata fallback (uint32(len(cascadeMeta.RqIdsIds))) when either count is zero. Single-source-of-truth violation per invariant-first Step 3.
  • What: FinalizeAction hook unmarshals CascadeMetadata and unconditionally calls auditKeeper.SetStorageTruthTicketArtifactCounts, which errors when either count is 0. Any not-pre-filled metadata bricks finalization for that ticket.

122-F3 — linkStorageTruthRecheckTranscript silently no-ops on recheck-hash collision

  • Severity: MEDIUM
  • File: x/audit/v1/keeper/storage_truth_fact_indexes.go
  • Lines: ~175-222
  • Status at PR feat(audit): finalize LEP-6 consensus gap fixes #122 tip: OPEN — when existing transcript record at recheckTranscriptHash exists, validate existing.TicketID == challenged.TicketID && existing.TargetAccount == challenged.TargetAccount before returning nil. Reject otherwise. Don't silently accept on collision.
  • What: After updating challenged.RecheckTranscriptHash, code checks for an existing record at that hash and returns nil if found — without verifying it refers to the same (ticket,target) and without writing the bidirectional back-reference. The 'no existing record' branch correctly writes both directions; the 'exists' branch breaks the invariant.

122-F4 — KeepLastEpochEntries lower bound widened with no module migration

  • Severity: MEDIUM
  • File: x/audit/v1/types/params.go
  • Lines: ~611-625
  • Status at PR feat(audit): finalize LEP-6 consensus gap fixes #122 tip: OPEN — add module migration that bumps KeepLastEpochEntries to max(KeepLastEpochEntries, DefaultStorageTruthOldClassAFaultWindow=21), OR document this as a hard activation precondition in the implementation guide.
  • What: Params.Validate() now requires KeepLastEpochEntries >= max(...windows). Default OldClassAFaultWindow=21 will fail Validate on chains where existing param is <21 (e.g. baseline 14). Hard upgrade gate with no in-PR migration.

This review is posted as a COMMENT (not REQUEST_CHANGES) so it does not block merge mechanically — but the CRITICAL and HIGH items must be triaged before activation. I'm available to walk through any of these in detail.

— Zee

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR finalizes a set of LEP-6 “consensus gap” fixes across x/audit and x/action, tightening on-chain storage-proof determinism and aligning enforcement/scoring behavior with the updated spec.

Changes:

  • Add canonical per-ticket artifact count anchoring (from cascade finalization) and enforce artifact-count/ordinal validation for submitted storage proofs.
  • Introduce additional LEP-6 params (old Class-A window, contradiction window, reporter ineligibility duration) and derive bucket thresholds from epoch_length_blocks.
  • Refine storage-truth scoring and enforcement behavior (trust-scaling scope, contradiction confirmation, recovery gating/events), and update protos/docs/tests accordingly.

Reviewed changes

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

Show a summary per file
File Description
x/audit/v1/types/params_test.go Extends params default/validation tests for new LEP-6 fields and derived bucket thresholds.
x/audit/v1/types/params.pb.go Regenerated protobuf code for new Params fields.
x/audit/v1/types/params.go Adds new param keys/defaults, derives bucket sizes from epoch length, and validates new LEP-6 windows.
x/audit/v1/types/keys.go Adds new KV prefixes/keys for ticket artifact counts and exposes additional prefixes.
x/audit/v1/types/genesis.pb.go Regenerated genesis protobuf code to include ticket artifact count states.
x/audit/v1/types/errors.go Introduces a new audit error code for artifact-count mismatch.
x/audit/v1/keeper/storage_truth_ticket_artifact_counts.go Adds keeper API to anchor immutable canonical artifact counts per ticket.
x/audit/v1/keeper/storage_truth_state_test.go Adds round-trip + immutability tests for ticket artifact count state.
x/audit/v1/keeper/storage_truth_state.go Persists and iterates ticket artifact count state in KV store.
x/audit/v1/keeper/storage_truth_scoring_internal_test.go Updates scoring expectations and adds test for pattern window usage.
x/audit/v1/keeper/storage_truth_scoring.go Adjusts trust-scaling scope, contradiction confirmation behavior, and window usage for pattern tracking.
x/audit/v1/keeper/storage_truth_fact_indexes.go Extends transcript indexing payload and adds contradiction confirmation helpers + recheck linking.
x/audit/v1/keeper/query_storage_truth_test.go Updates query tests to include new proof envelope fields and artifact counts.
x/audit/v1/keeper/msg_submit_epoch_report_test.go Adds helpers and new validation cases around artifact counts and NO_ELIGIBLE consistency.
x/audit/v1/keeper/msg_submit_epoch_report_storage_truth_scores_test.go Updates score tests to seed canonical counts and reflect revised scoring semantics.
x/audit/v1/keeper/msg_submit_epoch_report_storage_proofs.go Enforces new proof envelope fields and validates artifact counts against anchored canonical state.
x/audit/v1/keeper/msg_submit_epoch_report.go Hooks canonical-count validation into epoch report submission pipeline.
x/audit/v1/keeper/msg_storage_truth_test.go Extends recheck evidence tests for transcript linking behavior.
x/audit/v1/keeper/msg_storage_truth.go Links challenged ↔ recheck transcripts during recheck evidence submission; adds failed-heal cooldown.
x/audit/v1/keeper/genesis_test.go Adds genesis round-trip coverage for ticket artifact count states.
x/audit/v1/keeper/genesis.go Imports/exports ticket artifact count states in genesis.
x/audit/v1/keeper/enforcement_test.go Adds test ensuring recovery emits a storage-truth recovered event.
x/audit/v1/keeper/enforcement.go Emits recovery events and makes old-Class-A window configurable; strengthens recovery gating.
x/action/v1/types/metadata_proto_test.go Updates proto round-trip test to include new cascade artifact count fields.
x/action/v1/types/metadata.pb.go Regenerated protobuf code for new CascadeMetadata fields.
x/action/v1/types/expected_keepers.go Extends AuditKeeper interface to anchor canonical ticket artifact counts.
x/action/v1/keeper/keeper_test.go Seeds cascade metadata with artifact counts in keeper tests.
x/action/v1/keeper/action_test.go Verifies cascade finalization anchors artifact counts via the AuditKeeper mock.
x/action/v1/keeper/action_cascade.go Adds backward-compatible defaults and propagates artifact counts into updated metadata.
x/action/v1/keeper/action.go On cascade finalization, calls audit keeper to anchor canonical artifact counts.
testutil/keeper/action.go Extends MockAuditKeeper to record anchored artifact counts for action tests.
tests/systemtests/audit_test_helpers_test.go Seeds genesis ticket artifact count states and updates proof JSON builder for new fields.
tests/systemtests/audit_storage_truth_edge_cases_test.go Updates system tests to new prober/target selection and revised scoring expectations.
tests/systemtests/audit_storage_truth_activation_test.go Ensures decay default handling and seeds synthetic ticket artifact counts in genesis.
tests/system/audit/msg_storage_truth_test.go Updates system tests for recheck evidence scoring and new proof envelope fields.
proto/lumera/audit/v1/params.proto Adds new Params fields for old Class-A window, contradiction window, and ineligibility duration.
proto/lumera/audit/v1/genesis.proto Adds repeated TicketArtifactCountState to audit genesis.
proto/lumera/audit/v1/audit.proto Extends StorageProofResult envelope and introduces TicketArtifactCountState message.
proto/lumera/action/v1/metadata.proto Adds canonical artifact count fields to CascadeMetadata.
docs/leps/LEP-6-implementation-guide.md Updates LEP-6 implementation guide to reflect new fields, params, validation rules, and activation plan.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread x/audit/v1/keeper/msg_storage_truth.go
Comment thread x/audit/v1/keeper/storage_truth_fact_indexes.go Outdated
Comment thread x/audit/v1/keeper/storage_truth_fact_indexes.go Outdated
Comment thread x/audit/v1/keeper/storage_truth_fact_indexes.go Outdated
Comment thread x/audit/v1/keeper/msg_submit_epoch_report_storage_proofs.go Outdated
Comment thread x/audit/v1/keeper/msg_submit_epoch_report_storage_proofs.go Outdated
Comment thread x/audit/v1/types/errors.go Outdated
Comment thread x/audit/v1/keeper/storage_truth_ticket_artifact_counts.go
@j-rafique j-rafique force-pushed the LEP-6-consensus-gap-fixes branch from a51c439 to 3471d6e Compare April 27, 2026 20:31
@j-rafique j-rafique changed the base branch from LEP-6-activation to LEP-6-foundation April 27, 2026 20:34
@j-rafique j-rafique force-pushed the LEP-6-consensus-gap-fixes branch from 3471d6e to 66cdaa8 Compare April 27, 2026 20:35
Comment thread x/audit/v1/keeper/prune.go
Copy link
Copy Markdown

@roomote-v0 roomote-v0 Bot left a comment

Choose a reason for hiding this comment

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

Re-reviewed commit 66cdaa8 (CP1 must-fix items). All four of Zee's findings (122-F1 through 122-F4) are addressed and the two previously-resolved items remain fixed. No net new issues found.

One prior item remains open: secondary indexes st/rrs-tt/, st/spt-tbe/, and primary transcript store st/spt/ are not pruned in PruneOldEpochs. This is a state-growth concern (MEDIUM) that can be addressed in a follow-up.

CRITICAL
- 121-F16: Replace float64 neg-rate arithmetic with integer cross-multiplication
  in ApplyReporterDivergenceAtEpochEnd to eliminate consensus non-determinism
  across validators (different IEEE-754 implementations could produce divergent
  sort orders and median values).
- 121-F15: Remove stale WindowPositiveCount/WindowNegativeCount fallback in
  divergence stats; divergence now exclusively reads per-record KV data.

HIGH
- 121-F1: RECHECK bucket results bypass storageTruthBookkeepingForResult to
  prevent double-applying the contradiction penalty already handled in
  SubmitStorageRecheckEvidence.
- 121-F2: Use challengedRecord.ReporterAccount (authoritative) instead of
  ticketState.LastReporterSupernodeAccount when targeting the original reporter
  for overturn/confirm scoring in SubmitStorageRecheckEvidence.
- 121-F4: Add time-window guard to StrongPostpone index-failure predicate;
  LastIndexFailEpoch must be within classAWindow epochs (not unbounded).
- 121-F13: Fix inverted eligibility predicate in GetAssignmentEligibleReporters:
  was AND-ing score threshold with ineligibility window, should be OR.
- 120-F3 / 121-F6: Add epoch-window pruning for recheck-evidence dedup keys
  (st/rce/), node failure records (st/nf/), reporter result records (st/rrs/),
  and failed-heal records (st/fh/) in PruneOldEpochs.
- 121-F7: StorageTruthPostponementKey and RecheckEvidence round-trip verified
  via existing tests; genesis wiring confirmed correct.

MEDIUM
- 119-Copilot-3: Fix first-failure-at-epoch-0 predicate in
  applyTicketDeteriorationDelta; use (!found || epochID != state.LastFailureEpoch)
  so epoch-0 failures are properly counted.
- 119-F7: Same-epoch contradiction check uses <= instead of < so two reporters
  in the same epoch can contradict each other.
- 121-F3 / 119-F5: Remove spurious currentReporterPenalty = -4 on contradiction
  detection; the PASS score delta already provides the -4 recovery signal.
- 121-F12: storageTruthBandStrongPostpone emits a distinct event type
  (storage_truth_band_strong_postpone_candidate) instead of reusing the regular
  postpone event type.
- 122-F3: linkStorageTruthRecheckTranscript now validates that an existing
  recheck transcript record was created by the same challenged hash and reporter
  before silently returning nil (prevents silent hash-collision bypass).
- 122-Copilot-2: Recheck transcript record no longer copies
  DerivationInputHash, ChallengerSignature, ObserverAttestations from the
  challenged record; these fields are zeroed in synthetic recheck records.
- 122-Roomote-B: linkStorageTruthRecheckTranscript uses errorsmod.Wrapf instead
  of fmt.Errorf so errors carry the correct SDK error code for clients.
- 122-Copilot-8: SetStorageTruthTicketArtifactCounts uses errorsmod.Wrap
  instead of fmt.Errorf throughout.

LOW
- 121-Copilot-1: Move SetRecheckEvidence call after linkStorageTruthRecheckTranscript
  succeeds so that a transcript-link failure does not permanently consume the
  per-(epoch, ticket, creator) dedup slot.
- 120-Copilot-4: ClaimHealComplete emits AttributeKeyHealManifestHash attribute
  instead of the generic AttributeKeyTranscriptHash; new constant added to
  types/events.go.
- 120-Copilot-5: Broaden the events.go file comment to cover all event types.
- 121-Roomote-C: Remove dead mulInt64ByUint64Saturated helper (unreachable code).

Previously landed (prior sessions, squashed here):
- Params fix: WithDefaults preserves UNSPECIFIED enforcement mode instead of
  promoting it to SHADOW; Validate accepts UNSPECIFIED as a valid no-op mode.
- Cascade bytes moved from HostReport to SupernodeMetricsState.Metrics (LEP-6 §12).
- AutoCLI: add EpochAnchor, CurrentEpochAnchor, AssignedTargets entries; skip
  float64-heavy RPC methods (EpochReport, EpochReportsByReporter, HostReports).
- enforcement_empty_active_set_test.go: update mock expectations to Active-only
  GetAllSuperNodes call (LEP-6 §17).
- distribution_freshness_test / query_get_reward_eligibility_test: addSupernode
  before height advance so MetricsState.Height is correctly set to initial height.
- e2e and integration everlight tests: remove stale CascadeKademliaDbBytes from
  HostReport literal; call SetMetricsState for cascade bytes instead.

All 44 packages pass (go test ./... -count=1 -timeout=300s).
@j-rafique j-rafique force-pushed the LEP-6-consensus-gap-fixes branch from 66cdaa8 to 114f175 Compare April 27, 2026 20:55
Copy link
Copy Markdown

@roomote-v0 roomote-v0 Bot left a comment

Choose a reason for hiding this comment

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

All three previously-flagged issues are resolved in commit 114f175. No net-new issues found in this review pass. LGTM.

@j-rafique j-rafique merged commit 868cbc7 into LEP-6-foundation Apr 27, 2026
8 checks passed
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