Skip to content

fix(net): bound QGETDATA request tracking - #7519

Merged
PastaPastaPasta merged 1 commit into
dashpay:developfrom
PastaPastaPasta:sec/v008
Aug 23, 2026
Merged

fix(net): bound QGETDATA request tracking#7519
PastaPastaPasta merged 1 commit into
dashpay:developfrom
PastaPastaPasta:sec/v008

Conversation

@PastaPastaPasta

@PastaPastaPasta PastaPastaPasta commented Aug 2, 2026

Copy link
Copy Markdown
Member

Issue being fixed or feature implemented

Inbound QGETDATA registration happened before validation, and each fresh quorumHash produced a distinct map key. Entries remained for the expiry window while cleanup depended on block-tip callbacks that are skipped during IBD and while unsynced, allowing an MNAuth peer or unauthenticated qwatch peer to grow request tracking without a hard bound.

This PR is now the request-tracking half of the original combined change. Requester-supplied response-error validation was split into #7605 so the two defects can be reviewed and merged independently.

What was done?

  • Prevalidate the LLMQ type and active-chain block before tracking:
    • unregistered LLMQ types return QUORUM_TYPE_INVALID, score 100, and are not tracked;
    • unknown or off-active-chain blocks return QUORUM_BLOCK_NOT_FOUND unscored and are not tracked;
    • active-chain blocks are registered before the commitment lookup so repeated uncached misses are rate-limited.
  • Bound attacker-controlled inbound tracking to 64 live entries per requester and 4096 globally. Outbound requests initiated by this node do not consume those budgets.
  • Score authenticated requesters that exhaust their own budget by 25. Shared/global exhaustion is not scored because the arriving peer is not necessarily responsible.
  • Run expired-request cleanup every minute independently of block-tip progress, while retaining tip-triggered cleanup.

Unauthenticated qwatch peers continue to share the null identity used by the existing per-key limiter. Exhaustion of that shared 64-entry budget is therefore unscored; the independent 4096-entry global cap remains the hard memory bound.

How Has This Been Tested?

  • Full local make -j13 build on macOS arm64 using the prebuilt depends tree.
  • ./src/test/test_dash --run_test=llmq_qgetdata_tests
  • ./src/test/test_dash --run_test='llmq_*' (75 cases)
  • /opt/homebrew/bin/python3.9 test/functional/test_runner.py p2p_quorum_data.py
  • test/lint/all-lint.py
  • git diff --check

The Python lint subcheck skipped because flake8 is not installed; the remaining lint checks passed.

Breaking Changes

None.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone

This pull request was created by Codex.

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants