Skip to content

Drop only interested requests when a historical ledger entry is missing - #8527

Merged
Eddy Ashton (eddyashton) merged 4 commits into
mainfrom
achamayou-special-fishstick
Oct 9, 2026
Merged

Eddy Ashton (eddyashton) merged 4 commits into
mainfrom
achamayou-special-fishstick

Conversation

@achamayou

Copy link
Copy Markdown
Member

Motivation

Found while reviewing #8525 (pre-existing on main, no tracking issue).

When the host reports NotFound or TooLarge for a requested ledger range, StateCacheImpl::handle_no_entry_range calls delete_all_interested_requests(seqno) to drop the requests which were asking for that entry. Its predicate was Request::get_store_details(seqno) != nullptr, which looks up the cache-wide all_stores map shared by every request rather than the request's own stores. While the StoreDetails for that seqno was alive, every request looked interested, so requests were erased in handle order until the last owner of the details died:

  • unrelated requests with a lower handle than the interested one were dropped;
  • when next_secret_fetch_handle owned the details (the entry was being fetched to recover an older ledger secret), nothing in the loop released it, so every in-flight historical request was dropped.

Implementation summary

  • Request::is_interested_in(seqno): true iff the seqno is in my_stores, in supporting_signatures, or is the ledger secret entry the request is waiting for (awaiting_ledger_secrets). delete_all_interested_requests now uses it.
  • handle_no_entry_range resets next_secret_fetch_handle when the erased all_stores entry is the one it points at, so the orphaned StoreDetails is not retained. Tick/expiry/sweep logic is untouched.
  • Regression tests in src/node/test/historical_queries.cpp, each failing before the fix:
    • Missing entries only drop interested requests: an unrelated lower-handle request survives and is served after handle_no_entry; the interested request is dropped. Also covers interest held only through supporting_signatures.
    • Missing ledger secret entries only drop waiting requests: recovered-node scenario where only the request awaiting the previous ledger secret is dropped.
  • CHANGELOG entry under 7.0.19 / Fixed.

Validation: historical_queries_test (21 cases) passes; cpp-format-checks.sh, prettier-checks.sh, release-notes-checks.sh, ascii-checks.sh, copyright-checks.sh, todo-checks.sh pass. A mutation check (removing the supporting_signatures/awaiting_ledger_secrets clauses) makes the corresponding assertions fail.

Safety and compatibility

Availability fix only: the untrusted host could previously cause unrelated historical queries (or all of them) to be dropped by reporting one entry as missing; the affected queries would simply restart on the next request. No change to what entries are trusted, to receipts, to consensus/KV, to any API or data format, or to mixed-version operation. Interest tracking is now strictly per request, and dropped requests are evicted via the existing lru_evict path.

delete_all_interested_requests used Request::get_store_details, which
looks up the cache-wide all_stores map shared by every request. While the
StoreDetails for the missing seqno was alive, every request looked
interested and was erased in handle order until the last owner died, or
all of them when next_secret_fetch_handle was the owner.

Decide interest per request instead: a request is interested if the seqno
is in its own stores, its supporting signatures, or is the ledger secret
entry it is waiting for. Also release next_secret_fetch_handle when its
entry is erased so the orphaned StoreDetails is not retained.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 7, 2026 22:11
@achamayou
Amaury Chamayou (achamayou) requested a review from a team as a code owner October 7, 2026 22:11
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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.

🔵 Needs a closer look

CI checks remain in progress, leaving validation incomplete.

0 open findings

What changed in this PR

Fixes historical-query cache eviction so a missing or oversized ledger entry drops only requests that depend on it.

Changes:

  • Tracks request-specific dependencies and releases failed ledger-secret fetch ownership.
  • Adds regression coverage for direct requests, supporting signatures, and ledger-secret recovery.
  • Documents the fix under version 7.0.19.

Custom instructions used

Applied the supplied repository, security/safety, and changelog guidance; corresponding instruction files were unavailable locally.

File Description
src/​node/​test/​historical_queries.cpp Verifies unrelated requests survive missing entries.
src/​node/​historical_queries.h Restricts eviction and cleans up failed secret fetches.
CHANGELOG.md Records the historical-query availability fix.

🧠 Review effort: Balanced


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

@eddyashton
Eddy Ashton (eddyashton) enabled auto-merge (squash) October 8, 2026 14:15
@eddyashton
Eddy Ashton (eddyashton) merged commit e69b0b5 into main Oct 9, 2026
12 checks passed
@eddyashton
Eddy Ashton (eddyashton) deleted the achamayou-special-fishstick branch October 9, 2026 07:20
Amaury Chamayou (achamayou) added a commit that referenced this pull request Oct 9, 2026
Resolve CHANGELOG.md by keeping both 7.0.19 Fixed entries (#8532, #8527).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Amaury Chamayou (achamayou) added a commit that referenced this pull request Oct 9, 2026
Mark the routing index queries [[nodiscard]] and take the request handle by value, as clang-tidy requires. After merging the base, a missing entry drops only the requests interested in it (#8527), so the rejection regression now checks that the unrelated request survives, and the routing oracle checks that Request::is_interested_in agrees with routing membership at every indexed seqno.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Amaury Chamayou (achamayou) added a commit that referenced this pull request Oct 10, 2026
Mark the routing index queries [[nodiscard]] and take the request handle by value, as clang-tidy requires. After merging the base, a missing entry drops only the requests interested in it (#8527), so the rejection regression now checks that the unrelated request survives, and the routing oracle checks that Request::is_interested_in agrees with routing membership at every indexed seqno.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Amaury Chamayou (achamayou) added a commit that referenced this pull request Oct 12, 2026
Mark the routing index queries [[nodiscard]] and take the request handle by value, as clang-tidy requires. After merging the base, a missing entry drops only the requests interested in it (#8527), so the rejection regression now checks that the unrelated request survives, and the routing oracle checks that Request::is_interested_in agrees with routing membership at every indexed seqno.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

4 participants