Repository navigation
fix(validator): resync report range when upstream last_validated is behind - #225
mega-putin[bot] wants to merge 4 commits into
Conversation
…ehind Generated-by: engineer-agent
Claude review status
✅ Review clean Last reviewed: head New this round: 0 finding(s), 0 question(s) · Resolved this round: 0 · Open questions: 0 |
|
No actionable review feedback is available yet; the only PR comment says the review is still in progress. No code changes or commit were made. |
|
Added the |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d32b5cb819
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| "Report rejected" | ||
| ); | ||
|
|
||
| if upstream_number < anchor.block_number { |
There was a problem hiding this comment.
Resync from a range the validator can actually retain
When the upstream pointer is below anchor, this is the only path that attempts recovery, but a normally produced ValidatorDB cannot retain that pointer: initialization creates the chain at the anchor, pipeline advancement is strictly forward, and retention only removes older rows. Consequently get_block_hash(upstream_number) will always return None; the passing test manufactures a non-contiguous row (#15 after anchor #70). Deployed validators therefore still cannot heal this report gap, and fixed-range runs will fail after their retries. Base recoverability on an actually retained range or obtain and verify the needed predecessor hash.
AGENTS.md reference: AGENTS.md:L71-L72
Useful? React with 👍 / 👎.
|
Addressed the review feedback and committed:
Changes:
Validation run:
No push performed. |
Generated-by: engineer-agent
Generated-by: engineer-agent
|
🔧 Pushed CI fixes. Agent log |
vincent-k2026
left a comment
There was a problem hiding this comment.
Reviewed against HEAD (34dcf0eb).
Theme: keeping the reporter alive is a real fix. The resync path, though, changes what this validator claims to have validated, and that needs an explicit decision rather than coming in as a side effect of a bug fix.
Good: on main, a validation gap makes report_range_once return Err, which ends the validation_reporter task. The pipeline keeps validating, but nothing reports upstream and nothing surfaces it. Logging and looping instead (runner.rs:218-222) is the right call.
Blocking (needs a decision)
-
The resync reports
[upstream_last_validated, tip], which covers heights this validator never executed.- The anchor comes from the operator's
--start-blockand is trusted. This node only re-executes(anchor, tip]. - When the receiver is behind the anchor, the retry claims
(upstream, anchor]as well (runner.rs:110-130,retry_covering_report). - On
mainthis case was deliberately fatal for--end-blockslices. The removed comment called a detected gap deterministic. - The header check added in
497b14conly proves the receiver's pointer is canonical, which mega-reth already checks onfirst_blockagainst its durable chain before accepting. It says nothing about whether the heights in between were validated. - Concretely: a receiver with no validated pointer, or whose pointer is no longer canonical, reports
(0, genesis)on rejection (mega-rethwitness.rs:560-575). This path then fetches header 0, it matches, and the validator pushes[0, tip]. - Note on Codex's P1: it pointed out the local-DB branch is unreachable in production. The
497b14cresponse made the branch reachable through the header lookup, rather than revisiting whether the range should be reported at all.
I'm aware mega-reth's
FullNodepublisher already does this on purpose. Theset_validated_blocksdocs say it re-executes(anchor, tip]but publishes[genesis, tip], and that coverage inside the range is "the pusher's own claim and is trusted as-is". If the team wants the stateless validator to make the same claim, that's a legitimate choice. But it should be made explicitly, by an owner, and documented here. In that case the header lookup is redundant: report[genesis, tip]the same wayFullNodedoes.If not, keep the gap non-recoverable. Leave the reporter alive and alarming loudly (error log plus a metric, with backoff), and keep failing
--end-blockslices. Never push a range that starts below the anchor. - The anchor comes from the operator's
Non-blocking
- An unresolvable gap repeats every second.
- The reporter interval is 1s, and
last_reportedis not updated on rejection. - On a hash mismatch, every round costs one
mega_setValidatedBlockscall, oneeth_getHeaderByNumbercall (5s deadline) and three warn/error lines. - Fix: back off, and log once per distinct
(upstream_number, upstream_hash)pointer.
- The reporter interval is 1s, and
report_range_oncecan no longer returnErr, but its signature still says it can.- The
Result<bool>is now misleading. - Dead code: the
Errarms invalidation_reporterand in the final-flush loop, plus the doc comment about non-retryable errors. - Fix: return
bool, and drop those arms.
- The
- The log-capture test does not discriminate.
install_log_captureinstalls a global subscriber with one shared buffer, so tests running in parallel write into it concurrently.- Three other log lines on this path also contain "validation gap", so
rejected_gap_logs_validation_gapstill passes after deleting the line it is meant to pin. - Fix: scope the capture with
tracing::subscriber::with_defaultand assert the exact message. Addingtracing-subscriberas a dev-dependency just for this probably isn't worth it either way.
- Missing case: the
(0, genesis)response from item 1. Whichever way item 1 is decided, add a test for it. - Nits.
Happy to be wrong if there is an operational reason to treat pre-anchor heights as validated that I'm missing.
|
Thanks — agreed. I removed the header-lookup recovery path and kept pre-anchor gaps non-recoverable for the standalone validator. It now only retries a covering report when the upstream pointer is actually retained in the local canonical-chain window; otherwise it logs the validation gap, keeps the reporter alive, and fixed-range final flushes fail after their bounded retries rather than claiming pre-anchor heights. I also simplified |
Generated-by: engineer-agent
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
No actionable review feedback is available yet; the latest Codex and Claude comments only show reviews still in progress for |
Codecov Report✅ All modified and coverable lines are covered by tests. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Codecov reports full coverage for modified coverable lines and no requested code changes. The “3 commits behind head on main” note is informational, so no changes or commit were made. |
Summary
Keep the validation reporter alive on rejected mega_setValidatedBlocks responses, log validation gaps, and retry from upstream last_validated to the local tip when that block is still in the local canonical chain. Added tests for successful resync, hash mismatch handling, and greppable gap logging.