fix: deduplicate QRINFO base blocks#7349
Conversation
|
@coderabbitai review |
✅ Action performedReview finished.
|
✅ No Merge Conflicts DetectedThis PR currently has no conflicts with other open PRs. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
WalkthroughThis PR modifies the quorum rotation snapshot construction to unconditionally sort base block indexes by ascending block height. Additionally, deduplication is applied only on the non-legacy construction path; the legacy path remains height-sorted but preserves duplicate entries to maintain legacy peer wire response behavior. The implementation adds the Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
✅ Review complete (commit 470ec0e) |
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Both agents converged on no findings for this small, well-scoped fix that sorts and deduplicates QRINFO baseBlockIndexes. CodeRabbit also reported no inline findings. The change is covered by both unit and functional tests.
|
Might this be a breaking change? Especially how we have the "legacy construction" flag? seems for some reason at some point the exact structure was deemed important? |
Address review feedback: the prior commit unconditionally sorted and deduplicated baseBlockIndexes, which touched the legacy construction path used to serve peers < EFFICIENT_QRINFO_VERSION. Restrict deduplication to the non-legacy path so the wire response to older peers stays bit-for-bit identical to the pre-fix behavior. The legacy path keeps the sort it always relied on for baseBlockIndexes.back() and GetLastBaseBlockHash(). Strengthen the unit test to explicitly prove the legacy no-op invariant: GetLastBaseBlockHash returns the same hash whether the sorted input contains duplicates or not, so legacy multiplicity is harmless. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Good catch. I narrowed the change in The repeated-base-hash fix now applies to the non-legacy path used by the RPC. I also added a direct unit assertion documenting that duplicates are a no-op for legacy Validation: |
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Carried-forward prior findings: none (prior review at e34105f had no issues). New delta at 9f30867 correctly narrows the dedupe added in the first commit to the non-legacy QRINFO construction path, preserving bit-for-bit wire compatibility for peers below EFFICIENT_QRINFO_VERSION while keeping the sort the legacy path already relied on. The unit test addition explicitly asserts the legacy no-op invariant (duplicate vs. unique input yields identical GetLastBaseBlockHash output). Both Claude and Codex agents reported zero findings; verification against src/llmq/snapshot.cpp and src/test/llmq_snapshot_tests.cpp confirms the change is correct, well-scoped, and adequately tested.
| if (use_legacy_construction) { | ||
| // Legacy construction (served to peers < EFFICIENT_QRINFO_VERSION) only needs the | ||
| // input sorted; do not deduplicate so the wire response stays bit-for-bit identical | ||
| // to the pre-fix behavior for older peers. | ||
| std::sort(baseBlockIndexes.begin(), baseBlockIndexes.end(), | ||
| [](const CBlockIndex* a, const CBlockIndex* b) { return a->nHeight < b->nHeight; }); | ||
| } else { | ||
| std::sort(baseBlockIndexes.begin(), baseBlockIndexes.end(), | ||
| [](const CBlockIndex* a, const CBlockIndex* b) { return a->nHeight < b->nHeight; }); |
There was a problem hiding this comment.
| if (use_legacy_construction) { | |
| // Legacy construction (served to peers < EFFICIENT_QRINFO_VERSION) only needs the | |
| // input sorted; do not deduplicate so the wire response stays bit-for-bit identical | |
| // to the pre-fix behavior for older peers. | |
| std::sort(baseBlockIndexes.begin(), baseBlockIndexes.end(), | |
| [](const CBlockIndex* a, const CBlockIndex* b) { return a->nHeight < b->nHeight; }); | |
| } else { | |
| std::sort(baseBlockIndexes.begin(), baseBlockIndexes.end(), | |
| [](const CBlockIndex* a, const CBlockIndex* b) { return a->nHeight < b->nHeight; }); | |
| // Sort in all cases: the legacy path (served to peers < EFFICIENT_QRINFO_VERSION) | |
| // relies on the order for baseBlockIndexes.back() and GetLastBaseBlockHash(). | |
| std::sort(baseBlockIndexes.begin(), baseBlockIndexes.end(), | |
| [](const CBlockIndex* a, const CBlockIndex* b) { return a->nHeight < b->nHeight; }); | |
| if (!use_legacy_construction) { | |
| // Only deduplicate on the non-legacy path; leave the legacy path untouched so the | |
| // wire response to older peers stays bit-for-bit identical to the pre-fix behavior. |
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Small, well-scoped change hoisting the sort of baseBlockIndexes out of the legacy-only branch and adding dedup on the non-legacy QRINFO construction path only. Behavior is correctness-preserving (GetLastBaseBlockHash is robust to duplicates) and the asymmetric dedup is intentionally conservative for wire compatibility per recent commit history. Unit and functional coverage are appropriate.
Issue being fixed or feature implemented
QRINFO request handling accepts caller-provided base block hashes and carries the
validated block indexes through quorum rotation response construction. Repeated
base hashes do not add useful information, so this change canonicalizes those
base indexes before the builder phases use them.
Provenance: thepastaclaw/tracker#1450
What was done?
paths.
result as a single base hash.
How Has This Been Tested?
Environment: macOS arm64, local Dash Core worktree based on
upstream/develop.Commands run:
git diff --check upstream/develop..HEAD— passedmake -C src -j$(sysctl -n hw.ncpu) test/test_dash— passed earlier in thisworktree before the final Python-only test addition
src/test/test_dash --run_test=llmq_snapshot_tests/get_last_base_block_hash_repeated_base_blocks_test— passed
test/functional/feature_llmq_rotation.py— skipped locally because thisworktree was configured with
--disable-walletcode-review dashpay/dash upstream/develop fix/qrinfo-dedupe-base-hashes ...— passed with recommendation: ship
Also checked:
gh api repos/dashpay/dash --jq '.default_branch'—developopen PR found
Breaking Changes
None expected.
Checklist: