Uh oh!
There was an error while loading. Please reload this page.
fix(net): bound CoinJoin message vector intake - #7419
Conversation
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📥 CommitsReviewing files that changed from the base of the PR and between 48a1eb95838ba3ce1ef1bdee48657e30bb6f05e8 and 45ee9af. 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (4)
WalkthroughCoinJoin entry serialization now uses explicit methods with bounded input and output vector deserialization. DSSIGNFINALTX processing validates signing state and peer participation, bounds transaction-input counts, and passes peer context through the server. AddEntry rejects oversized inputs or outputs and consumes matching collateral. Tests cover stream handling, session preservation, oversized vectors, and boundary round trips. Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Peer
participant CCoinJoinServer
participant CDataStream
Peer->>CCoinJoinServer: DSSIGNFINALTX message
CCoinJoinServer->>CCoinJoinServer: Validate state and participant address
CCoinJoinServer->>CDataStream: Read bounded transaction-input count
alt oversized count
CCoinJoinServer-->>Peer: Reject with ERR_MAXIMUM
else valid count
CCoinJoinServer->>CCoinJoinServer: Process input signatures
end
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ 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 in progress — actively reviewing now (commit 45ee9af) |
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:fa8feddcd3
ℹ️ 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".
Uh oh!
There was an error while loading. Please reload this page.
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Source: reviewers claude/general=opus(failed), codex/general=gpt-5.5(completed), claude/dash-core-commit-history=opus(failed), codex/dash-core-commit-history=gpt-5.5(completed); verifier=gpt-5.5
The PR addresses the intended CoinJoin intake hardening, but the new bounded deserialization introduces a portable build regression. The new braced size_t initializers from ReadCompactSize() are ill-formed on supported 32-bit targets because ReadCompactSize() returns uint64_t.
Verified findings
- [BLOCKING] src/coinjoin/coinjoin.h:182-194: Avoid narrowing list-initialization from ReadCompactSize
ReadCompactSize()returnsuint64_t, but these newsize_tvariables are initialized with braces. On supported 32-bit builds,size_tcannot represent everyuint64_tvalue, soconst size_t x{ReadCompactSize(s)};is ill-formed before tests can run. The value is already range-checked byReadCompactSize()againstMAX_SIZE, which fits in 32-bitsize_t, so ordinary copy-initialization preserves the intended behavior without triggering C++ narrowing rules. - [BLOCKING] src/coinjoin/server.cpp:228: Avoid narrowing list-initialization in DSSIGNFINALTX
ReadCompactSize()returnsuint64_t, so list-initializing asize_twith braces is a narrowing conversion on 32-bit targets and fails to compile. Dash still carries i686 depends hosts, so this new CoinJoin server path needs to use a form that remains valid whensize_tis 32 bits.
Note: posted as a COMMENT review because GitHub does not allow approving/requesting changes on my own PR via the normal review event.
thepastaclaw
commented
Jul 7, 2026
@coderabbitai review |
✅ Action performedReview finished.
|
thepastaclaw
commented
Jul 7, 2026
Handled the self-review finding by replacing the braced |
There was a problem hiding this comment.
Code Review
Source: reviewers claude/general=opus(failed: extra-usage quota), codex/general=gpt-5.5(ok), claude/dash-core-commit-history=opus(failed: extra-usage quota), codex/dash-core-commit-history=gpt-5.5(ok); verifier=gpt-5.5 (Opus verifier failed: extra-usage quota)
Reviewed commit: a031fe71.
The two prior blocking portability findings from fa8feddc are fixed at the current head: all new ReadCompactSize() counts now use copy-initialization instead of braced size_t initialization. I found no remaining code-level correctness issue in the changed CoinJoin bounds handling.
Prior Finding Reconciliation
- FIXED
src/coinjoin/coinjoin.h:182-194—txdsin_sizeandtxout_sizenow use= ReadCompactSize(s). - FIXED
src/coinjoin/server.cpp:228—txins_sizenow uses= ReadCompactSize(vRecv).
Carried-forward prior findings: none.
New Findings In Latest Delta
- [SUGGESTION]
<commit:a031fe7>: Fold compact-size narrowing fix into the introducing commits
Commita031fe718e8only changesReadCompactSize()count initializers introduced by the previous two commits. If the stack is merged as-is, the permanent history contains intermediate commits with a portable-build regression that is fixed only by the final cleanup commit. Fold thesrc/coinjoin/server.cppchange into450b3bb7f39and thesrc/coinjoin/coinjoin.hchanges intofa8feddcd3fso each substantive hardening commit is buildable on its own.
CodeRabbit context: no concrete inline findings; no reactions posted.
a031fe7 to
d80de2aComparethepastaclaw
commented
Jul 7, 2026
Resolved the self-review commit-history feedback by folding the compact-size narrowing cleanup into the commits that introduced the reads:
Validation:
|
thepastaclaw
commented
Jul 7, 2026
@coderabbitai review |
✅ Action performedReview finished.
|
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Source: reviewers claude/general=opus(failed: extra-usage quota), codex/general=gpt-5.5(completed), claude/dash-core-commit-history=opus(failed: extra-usage quota), codex/dash-core-commit-history=gpt-5.5(completed); verifier=gpt-5.5(codex)
Reviewed commit: d80de2ae.
The current head rewrites the stack into two self-contained CoinJoin hardening commits. The prior commit-history suggestion from a031fe71 is fixed: the standalone compact-size cleanup commit is gone, and the ReadCompactSize() count initialization fixes are folded into the introducing commits. I found no in-scope issues in the cumulative CoinJoin vector-bound changes.
Prior Finding Reconciliation
- FIXED
<commit:a031fe7>—Fold compact-size narrowing fix into the introducing commits. Current stack has only7704aa835bfandd80de2aec27, both substantive/self-contained, and no separate compact-size cleanup commit remains.
Carried-forward prior findings: none.
New Findings In Latest Delta
None. git diff a031fe71..d80de2ae is tree-empty after the history rewrite, and the cumulative review found no new current-head issue.
CodeRabbit context: no concrete inline findings; no reactions posted.
Note: GitHub does not allow me to submit an approval review on my own PR, so this is posted as a COMMENT while preserving the verified clean result.
thepastaclaw
commented
Jul 8, 2026
@coderabbitai review |
✅ Action performedReview finished.
|
thepastaclaw
commented
Jul 8, 2026
@coderabbitai review |
✅ Action performedReview finished.
|
9f03035 ci: harden conflict advisory comments (PastaClaw) a506e22 ci: make conflict prediction advisory (PastaClaw) Pull request description: # ci: make conflict prediction advisory ## Issue being fixed or feature implemented The existing potential-conflicts workflow is hard to act on because it can fail CI and only reports the conflict from the triggering PR's side. For review and merge planning, maintainers need an advisory comment on both affected PRs that explains which PR would force the other to rebase if merged first. ## What was done? Reworked the potential-conflicts workflow to: - Replace the external conflict-checker and sticky-comment actions with a repository-local Python handler. - Discover same-base open PRs with overlapping changed files through the GitHub API. - Validate overlap candidates with GitHub's pre-mergeability page before reporting them. - Maintain one GitHub Actions-owned advisory comment per affected PR. - Show both directions in that comment: - "If this PR merges first" - "If these PRs merge first" - Update reciprocal comments on the conflicting PRs so both sides show the merge-order risk. - Keep the workflow advisory-only with `continue-on-error`, so conflicts do not make CI red. - Clean stale reciprocal state when conflicts disappear, PRs close, or PRs are converted to draft. - Ignore user-authored comments that forge the managed marker; only `github-actions[bot]` comments are treated as workflow-owned state. - Serialize the workflow globally to avoid reciprocal comment write races. ## How Has This Been Tested? Validated locally on macOS with: ```bash python3 .github/workflows/test_handle_potential_conflicts.py python3 -m py_compile \ .github/workflows/handle_potential_conflicts.py \ .github/workflows/test_handle_potential_conflicts.py python3 test/lint/lint-python.py \ .github/workflows/handle_potential_conflicts.py \ .github/workflows/test_handle_potential_conflicts.py git diff --check 25aeb5f..HEAD ``` Ran a live read-only dry-run against `#7419`: ```bash GITHUB_TOKEN=$(gh auth token) \ GITHUB_REPOSITORY=dashpay/dash \ .github/workflows/handle_potential_conflicts.py \ --pr-number 7419 \ --dry-run ``` - The dry-run found `#7052` as the validated advisory conflict and rendered the managed comment body without writing comments. Also ran an Opus sidecar design pass and multiple Codex review-gate passes. The final blocker-only review returned `No issues found`. ## Breaking Changes None. The workflow remains advisory-only and does not fail CI when conflicts are found or when comment updates fail. ## Checklist - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] 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 _(for repository code-owners and collaborators only)_ Top commit has no ACKs. Tree-SHA512: 94b9b8b6b9623795e5da1843b5dc7e6192d17dbacaaef26a6f54e0a0c032d283fd3d2ae4358d275c5c5d4ed579c70977b42241a91bf53c2e1ec66e95e307bdcf
UdjinM6
commented
Jul 8, 2026
pls consider a2c7b0a |
d80de2a to
1894eacComparethepastaclaw
commented
Jul 8, 2026
Applied UdjinM6’s Updated head: What changed:
Validation passed:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:1894eacb13
ℹ️ 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".
Uh oh!
There was an error while loading. Please reload this page.
thepastaclaw
commented
Jul 8, 2026
@coderabbitai review |
✅ Action performedReview finished.
|
1894eac to
eb4aef2Compare✅ Action performedReview finished.
|
✅ Action performedReviews resumed. |
| BOOST_REQUIRE(m_node.mn_sync); | ||
| m_node.mn_sync->SwitchToNextAsset(); | ||
| BOOST_REQUIRE(m_node.mn_sync->IsBlockchainSynced()); | ||
| CActiveMasternodeManager mn_activeman(*Assert(m_node.connman), *Assert(m_node.dmnman), MakeSecretKey()); | ||
| TestableCoinJoinServer server(m_node.peerman.get(), *Assert(m_node.chainman), *Assert(m_node.connman), | ||
| *Assert(m_node.dmnman), *Assert(m_node.dstxman), *Assert(m_node.mn_metaman), | ||
| *Assert(m_node.mempool), mn_activeman, *Assert(m_node.mn_sync), | ||
| *Assert(m_node.llmq_ctx->isman)); |
There was a problem hiding this comment.
nit: consider moving this to the common helper ; and inline MakeSecretKey there
BOOST_REQUIRE(m_node.mn_sync);
m_node.mn_sync->SwitchToNextAsset();
BOOST_REQUIRE(m_node.mn_sync->IsBlockchainSynced());
CActiveMasternodeManager mn_activeman(*Assert(m_node.connman), *Assert(m_node.dmnman), MakeSecretKey());
TestableCoinJoinServer server(m_node.peerman.get(), *Assert(m_node.chainman), *Assert(m_node.connman),
*Assert(m_node.dmnman), *Assert(m_node.dstxman), *Assert(m_node.mn_metaman),
*Assert(m_node.mempool), mn_activeman, *Assert(m_node.mn_sync),
*Assert(m_node.llmq_ctx->isman));
// Same setup, but this time the oversized DSSIGNFINALTX comes from the
// session participant itself. It must still be rejected without materializing
// the txin vector and without collapsing the session for everyone else.
auto participant = MakePeer(/*id=*/7, /*ipv4=*/0x0a000001);
server.SeedParticipant(participant->addr);
server.EnterSigningState();
Deserialize CoinJoin entry input and output vectors through the pool-wide 180-element wire cap while retaining the 9-element per-entry policy in AddEntry. Apply the shared pool cap to DSSIGNFINALTX and only consume an oversized entry's collateral when it was accepted into the current session.
48a1eb9 to
45ee9afCompare✅ Action performedReviews resumed. |
Uh oh!
There was an error while loading. Please reload this page.
af6a0fd feat(serialize): add bounded-vector deserialization primitives (PastaClaw) Pull request description: ## Issue being fixed or feature implemented Network messages often have protocol-specific vector limits below the generic serialization limit. Callers need to enforce those limits before vector allocation and element decoding, without changing the wire format. ## What was done? - Factor the existing batched vector element decoder into a shared internal helper. - Add `UnserializeVectorWithMaxSize` for runtime bounds. - Add `LIMITED_VECTOR` / `LimitedVectorFormatter` for compile-time bounds in `READWRITE` declarations. - Keep serialization byte-for-byte compatible with ordinary vectors; only deserialization is bounded. - Compare CompactSize counts before narrowing or allocating, including counts at and above `MAX_SIZE`. ## Stacked adopters Each consumer remains a separate command-specific PR: - dashpay#7416 — quorum-data response vectors - dashpay#7418 — LLMQ signing message vectors - dashpay#7419 — CoinJoin message vectors - dashpay#7438 — SPORK signature vector Reviewing dashpay#7439 first leaves each child PR with only its protocol-specific policy, punishment, and regression tests. ## How Has This Been Tested? - `src/test/test_dash --run_test=serialize_tests` - Exact and over-limit boundaries, zero limits, custom element formatters, `MAX_SIZE` and `MAX_SIZE + 1` declarations, 64-bit CompactSize counts, wire compatibility, and rejection before element decode are covered. ## Breaking Changes None. Existing vector serialization and deserialization behavior is unchanged. ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] 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 Top commit has no ACKs. Tree-SHA512: 61e4183a5a2a173254f3105d30969704c2c53dac3ce421f0b3e8e989bc87ec1a94d2757944694db219802403a668d7460943d507ab7948db30b97145d57f26d6
45ee9af fix: separate CoinJoin entry wire and semantic limits (PastaClaw) d81ff3c fix: bound CoinJoin entry intake (PastaClaw) c72a8f5 fix: bound CoinJoin final signature intake (PastaClaw) Pull request description: Depends on dashpay#7439. Please review only the three CoinJoin-specific commits here. ## Issue being fixed or feature implemented CoinJoin server messages could deserialize or process peer-controlled input/output vectors before enforcing CoinJoin session bounds. This hardens the final-signature and entry intake paths by separating the wire-safety bound from the per-entry semantic bound. ## What was done? - Accept `DSSIGNFINALTX` only during signing and only from an active session participant. - Bound `DSSIGNFINALTX` input deserialization at the largest complete CoinJoin size: currently 20 participants × 9 inputs = 180. - Apply the same 180-element wire-safety cap to both `CCoinJoinEntry` vectors, rejecting larger declarations before vector materialization. - Keep the existing semantic limit of 9 inputs and 9 outputs per entry in `AddEntry()`. - Allow declarations from 10 through 180 to deserialize safely and reach semantic rejection, consuming collateral only when it matches a collateral accepted for the active session. - Remove the special `MAX + 1` input rule, oversized-output flag, and asymmetric input/output deserialization behavior. - Add focused boundary, participant, session-state, collateral, and round-trip tests. The reusable bounded-vector deserialization primitive is introduced separately in dashpay#7439. ## How Has This Been Tested? - `make -C src -j15 test/test_dash` - `./src/test/test_dash --run_test=coinjoin_inouts_tests` (8/8 passed) - `test/lint/lint-whitespace.py` - Focused `LogPrint` format-string lint - Focused `clang-format-diff.py` - `git diff --check` - Independent exact-range Codex review (`9474fc5e2a1..48a1eb95838`): ship, 0 findings ## Breaking Changes None. ## Checklist - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] 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 _(for repository code-owners and collaborators only)_ ACKs for top commit: UdjinM6: utACK 45ee9af Tree-SHA512: 8924d894d99ec8420034968cb55dad6ed4970911e01b5cc073b2f71ee79d0246d0aa1936b1d4a99b8f0749f5665097329c4fe65757c5986db25762a5c4ef10b4
af6a0fd feat(serialize): add bounded-vector deserialization primitives (PastaClaw) Pull request description: ## Issue being fixed or feature implemented Network messages often have protocol-specific vector limits below the generic serialization limit. Callers need to enforce those limits before vector allocation and element decoding, without changing the wire format. ## What was done? - Factor the existing batched vector element decoder into a shared internal helper. - Add `UnserializeVectorWithMaxSize` for runtime bounds. - Add `LIMITED_VECTOR` / `LimitedVectorFormatter` for compile-time bounds in `READWRITE` declarations. - Keep serialization byte-for-byte compatible with ordinary vectors; only deserialization is bounded. - Compare CompactSize counts before narrowing or allocating, including counts at and above `MAX_SIZE`. ## Stacked adopters Each consumer remains a separate command-specific PR: - dashpay#7416 — quorum-data response vectors - dashpay#7418 — LLMQ signing message vectors - dashpay#7419 — CoinJoin message vectors - dashpay#7438 — SPORK signature vector Reviewing dashpay#7439 first leaves each child PR with only its protocol-specific policy, punishment, and regression tests. ## How Has This Been Tested? - `src/test/test_dash --run_test=serialize_tests` - Exact and over-limit boundaries, zero limits, custom element formatters, `MAX_SIZE` and `MAX_SIZE + 1` declarations, 64-bit CompactSize counts, wire compatibility, and rejection before element decode are covered. ## Breaking Changes None. Existing vector serialization and deserialization behavior is unchanged. ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] 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 Top commit has no ACKs. Tree-SHA512: 61e4183a5a2a173254f3105d30969704c2c53dac3ce421f0b3e8e989bc87ec1a94d2757944694db219802403a668d7460943d507ab7948db30b97145d57f26d6
45ee9af fix: separate CoinJoin entry wire and semantic limits (PastaClaw) d81ff3c fix: bound CoinJoin entry intake (PastaClaw) c72a8f5 fix: bound CoinJoin final signature intake (PastaClaw) Pull request description: Depends on dashpay#7439. Please review only the three CoinJoin-specific commits here. ## Issue being fixed or feature implemented CoinJoin server messages could deserialize or process peer-controlled input/output vectors before enforcing CoinJoin session bounds. This hardens the final-signature and entry intake paths by separating the wire-safety bound from the per-entry semantic bound. ## What was done? - Accept `DSSIGNFINALTX` only during signing and only from an active session participant. - Bound `DSSIGNFINALTX` input deserialization at the largest complete CoinJoin size: currently 20 participants × 9 inputs = 180. - Apply the same 180-element wire-safety cap to both `CCoinJoinEntry` vectors, rejecting larger declarations before vector materialization. - Keep the existing semantic limit of 9 inputs and 9 outputs per entry in `AddEntry()`. - Allow declarations from 10 through 180 to deserialize safely and reach semantic rejection, consuming collateral only when it matches a collateral accepted for the active session. - Remove the special `MAX + 1` input rule, oversized-output flag, and asymmetric input/output deserialization behavior. - Add focused boundary, participant, session-state, collateral, and round-trip tests. The reusable bounded-vector deserialization primitive is introduced separately in dashpay#7439. ## How Has This Been Tested? - `make -C src -j15 test/test_dash` - `./src/test/test_dash --run_test=coinjoin_inouts_tests` (8/8 passed) - `test/lint/lint-whitespace.py` - Focused `LogPrint` format-string lint - Focused `clang-format-diff.py` - `git diff --check` - Independent exact-range Codex review (`9474fc5e2a1..48a1eb95838`): ship, 0 findings ## Breaking Changes None. ## Checklist - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] 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 _(for repository code-owners and collaborators only)_ ACKs for top commit: UdjinM6: utACK 45ee9af Tree-SHA512: 8924d894d99ec8420034968cb55dad6ed4970911e01b5cc073b2f71ee79d0246d0aa1936b1d4a99b8f0749f5665097329c4fe65757c5986db25762a5c4ef10b4
…lization 8f0b813 fix(governance): bound vote signature deserialization (PastaClaw) Pull request description: Uses the shared bounded-vector deserialization primitive merged in dashpay#7439. ## Motivation Governance vote signatures were deserialized through the generic byte-vector path. A peer could declare a very large signature length, causing allocation before the stream reported truncation. The outer message-processing catch did not score or disconnect the peer, allowing repeated malformed messages. ## Changes - bound network governance-vote signature reads to 96 bytes before allocation - require one of the two structurally valid encodings: 65-byte compact ECDSA or 96-byte BLS - score malformed or truncated governance vote messages with 100 misbehavior points - preserve disk, hash, and outbound serialization behavior - add focused unit coverage ## Testing - `./src/test/test_dash --run_test=governance_vote_wire_tests` (4/4 tests) - `./src/test/test_dash --run_test=serialize_tests` (10/10 tests) - `test/lint/lint-python.py` Tree-SHA512: backported to v23.1.x by cherry-picking 8f0b813 (applies cleanly). Backport note for v23.1.8 ------------------------- This was missing from the original v23.1.8 branch while its test follow-up dashpay#7450 ("test: make governance vote fixtures wire-valid", 915566d) was already included. That ordering was inverted: dashpay#7450 exists solely to adapt the dashpay#7442 governance-inv fixtures to the bound that dashpay#7440 introduces. Verified by removing dashpay#7450's SetSignature() line and rebuilding: without dashpay#7440 present the fixtures pass regardless, and re-adding dashpay#7440 reproduces exactly the six governance_inv_tests failures dashpay#7450's description cites. So the branch was shipping the compensating test change for a hardening fix it did not have, leaving CGovernanceVote::vchSig unbounded on the network path. The prerequisite dashpay#7439 (LIMITED_VECTOR) is already present via 099b99d, as are the sibling bounding backports dashpay#7416/dashpay#7418/dashpay#7419/dashpay#7438/dashpay#7444, so this restores the intended set rather than widening release scope. Reported-by: UdjinM6 Co-Authored-By: Claude <noreply@anthropic.com>
af6a0fd feat(serialize): add bounded-vector deserialization primitives (PastaClaw) Pull request description: ## Issue being fixed or feature implemented Network messages often have protocol-specific vector limits below the generic serialization limit. Callers need to enforce those limits before vector allocation and element decoding, without changing the wire format. ## What was done? - Factor the existing batched vector element decoder into a shared internal helper. - Add `UnserializeVectorWithMaxSize` for runtime bounds. - Add `LIMITED_VECTOR` / `LimitedVectorFormatter` for compile-time bounds in `READWRITE` declarations. - Keep serialization byte-for-byte compatible with ordinary vectors; only deserialization is bounded. - Compare CompactSize counts before narrowing or allocating, including counts at and above `MAX_SIZE`. ## Stacked adopters Each consumer remains a separate command-specific PR: - dashpay#7416 — quorum-data response vectors - dashpay#7418 — LLMQ signing message vectors - dashpay#7419 — CoinJoin message vectors - dashpay#7438 — SPORK signature vector Reviewing dashpay#7439 first leaves each child PR with only its protocol-specific policy, punishment, and regression tests. ## How Has This Been Tested? - `src/test/test_dash --run_test=serialize_tests` - Exact and over-limit boundaries, zero limits, custom element formatters, `MAX_SIZE` and `MAX_SIZE + 1` declarations, 64-bit CompactSize counts, wire compatibility, and rejection before element decode are covered. ## Breaking Changes None. Existing vector serialization and deserialization behavior is unchanged. ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] 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 Top commit has no ACKs. Tree-SHA512: 61e4183a5a2a173254f3105d30969704c2c53dac3ce421f0b3e8e989bc87ec1a94d2757944694db219802403a668d7460943d507ab7948db30b97145d57f26d6 (cherry picked from commit 9474fc5)
Backport of dashpay#7419 (upstream merge 5d83098, cherry-picked with -m1). v23.1.x adaptation: the coinjoin_inouts_tests.cpp additions are taken as upstream wrote them (including the TestableCoinJoinServer/MakePeer test helpers this PR introduces); develop's pre-existing entry_addscriptsig_matches_and_rejects test case, which sat adjacent in the conflict region but comes from an out-of-scope PR, was not brought along. All src/coinjoin hunks applied cleanly and are unchanged from upstream. (cherry picked from commit 5d8309898467301e3b1489b13e6a1b0a7062b5f2)
af6a0fd feat(serialize): add bounded-vector deserialization primitives (PastaClaw) Pull request description: ## Issue being fixed or feature implemented Network messages often have protocol-specific vector limits below the generic serialization limit. Callers need to enforce those limits before vector allocation and element decoding, without changing the wire format. ## What was done? - Factor the existing batched vector element decoder into a shared internal helper. - Add `UnserializeVectorWithMaxSize` for runtime bounds. - Add `LIMITED_VECTOR` / `LimitedVectorFormatter` for compile-time bounds in `READWRITE` declarations. - Keep serialization byte-for-byte compatible with ordinary vectors; only deserialization is bounded. - Compare CompactSize counts before narrowing or allocating, including counts at and above `MAX_SIZE`. ## Stacked adopters Each consumer remains a separate command-specific PR: - dashpay#7416 — quorum-data response vectors - dashpay#7418 — LLMQ signing message vectors - dashpay#7419 — CoinJoin message vectors - dashpay#7438 — SPORK signature vector Reviewing dashpay#7439 first leaves each child PR with only its protocol-specific policy, punishment, and regression tests. ## How Has This Been Tested? - `src/test/test_dash --run_test=serialize_tests` - Exact and over-limit boundaries, zero limits, custom element formatters, `MAX_SIZE` and `MAX_SIZE + 1` declarations, 64-bit CompactSize counts, wire compatibility, and rejection before element decode are covered. ## Breaking Changes None. Existing vector serialization and deserialization behavior is unchanged. ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] 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 Top commit has no ACKs. Tree-SHA512: 61e4183a5a2a173254f3105d30969704c2c53dac3ce421f0b3e8e989bc87ec1a94d2757944694db219802403a668d7460943d507ab7948db30b97145d57f26d6 (cherry picked from commit 9474fc5)
Backport of dashpay#7419 (upstream merge 5d83098, cherry-picked with -m1). v23.1.x adaptation: the coinjoin_inouts_tests.cpp additions are taken as upstream wrote them (including the TestableCoinJoinServer/MakePeer test helpers this PR introduces); develop's pre-existing entry_addscriptsig_matches_and_rejects test case, which sat adjacent in the conflict region but comes from an out-of-scope PR, was not brought along. All src/coinjoin hunks applied cleanly and are unchanged from upstream. (cherry picked from commit 5d8309898467301e3b1489b13e6a1b0a7062b5f2)
Backport of dashpay#7419 (upstream merge 5d83098, cherry-picked with -m1). v23.1.x adaptation: the coinjoin_inouts_tests.cpp additions are taken as upstream wrote them (including the TestableCoinJoinServer/MakePeer test helpers this PR introduces); develop's pre-existing entry_addscriptsig_matches_and_rejects test case, which sat adjacent in the conflict region but comes from an out-of-scope PR, was not brought along. All src/coinjoin hunks applied cleanly and are unchanged from upstream. (cherry picked from commit 5d8309898467301e3b1489b13e6a1b0a7062b5f2)
af6a0fd feat(serialize): add bounded-vector deserialization primitives (PastaClaw) Pull request description: ## Issue being fixed or feature implemented Network messages often have protocol-specific vector limits below the generic serialization limit. Callers need to enforce those limits before vector allocation and element decoding, without changing the wire format. ## What was done? - Factor the existing batched vector element decoder into a shared internal helper. - Add `UnserializeVectorWithMaxSize` for runtime bounds. - Add `LIMITED_VECTOR` / `LimitedVectorFormatter` for compile-time bounds in `READWRITE` declarations. - Keep serialization byte-for-byte compatible with ordinary vectors; only deserialization is bounded. - Compare CompactSize counts before narrowing or allocating, including counts at and above `MAX_SIZE`. ## Stacked adopters Each consumer remains a separate command-specific PR: - dashpay#7416 — quorum-data response vectors - dashpay#7418 — LLMQ signing message vectors - dashpay#7419 — CoinJoin message vectors - dashpay#7438 — SPORK signature vector Reviewing dashpay#7439 first leaves each child PR with only its protocol-specific policy, punishment, and regression tests. ## How Has This Been Tested? - `src/test/test_dash --run_test=serialize_tests` - Exact and over-limit boundaries, zero limits, custom element formatters, `MAX_SIZE` and `MAX_SIZE + 1` declarations, 64-bit CompactSize counts, wire compatibility, and rejection before element decode are covered. ## Breaking Changes None. Existing vector serialization and deserialization behavior is unchanged. ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] 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 Top commit has no ACKs. Tree-SHA512: 61e4183a5a2a173254f3105d30969704c2c53dac3ce421f0b3e8e989bc87ec1a94d2757944694db219802403a668d7460943d507ab7948db30b97145d57f26d6 (cherry picked from commit 9474fc5)
Backport of dashpay#7419 (upstream merge 5d83098, cherry-picked with -m1). v23.1.x adaptation: the coinjoin_inouts_tests.cpp additions are taken as upstream wrote them (including the TestableCoinJoinServer/MakePeer test helpers this PR introduces); develop's pre-existing entry_addscriptsig_matches_and_rejects test case, which sat adjacent in the conflict region but comes from an out-of-scope PR, was not brought along. All src/coinjoin hunks applied cleanly and are unchanged from upstream. (cherry picked from commit 5d8309898467301e3b1489b13e6a1b0a7062b5f2)
24920a0 chore: prepare v23.1.8 release (pasta) 2194248 Merge #7348: fix: penalize oversized notfound messages (pasta) f5c72c3 Merge #7347: fix: punish invalid dstx messages (pasta) 550caf7 Merge #7465: fix(qt): handle pixel-sized fonts when scaling widgets (pasta) e203710 Merge #7419: fix(net): bound CoinJoin message vector intake (pasta) 5f5b960 Merge #7418: fix(net): bound signing message vector intake (Pasta) 7cc2cca Merge #7450: test: make governance vote fixtures wire-valid (Pasta) f011c80 Merge #7440: fix(net): bound governance vote signature deserialization (Pasta) 4b4d96a Merge #7442: fix(net): authorize governance inv responses via the net-layer per-peer request tracker (Pasta) f855b13 Merge #7444: fix(net): bound bloom message vectors before allocation (Pasta) 5b5c6fb Merge #7415: fix: bound pending sig share queue (Pasta) 9bbe808 Merge #7416: fix(net): bound quorum data response vectors (Pasta) da42f50 Merge #7424: fix: bound ChainLock seen cache (Pasta) 5b310df Merge #7438: fix: bound SPORK signature deserialization (Pasta) e118d0c Merge #7259: fix: dangling point to cj client (Pasta) 9921621 Merge #7439: refactor: add bounded vector deserialization (Pasta) 89bdf7c Merge #7414: fix(net): throttle per-object governance vote sync requests (Pasta) 44c396d Merge #7402: fix: bound pending recovered sig queue to prevent remote OOM (Pasta) 05cfe27 Merge #7351: fix: limit signing share sessions per peer (pasta) 3ef3a5b Merge #7408: fix: bound DKG contribution blob intake (pasta) 0ea6532 Merge #7387: test: migrate governance inv cache coverage to unit tests (Pasta) 8ffdf7f Merge #7398: backport: compact block relay hardening (bitcoin#26898, bitcoin#27626, bitcoin#27743, bitcoin#26969, bitcoin#29412, bitcoin#32646, bitcoin#33296) (Pasta) 2915142 backport: bitcoin#27608 - p2p: Avoid prematurely clearing download state for other peers (PastaClaw) 90b5473 Merge #7396: fix: run of circular-dependencies with python3.15 (Pasta) b003cdc Merge #7395: ci: update GitHub Actions pins for Node 24 (pasta) 97c3dd1 Merge #7394: fix: stabilize par help text in manpages (pasta) 8f8616b Merge #7372: backport: bitcoin#32693: depends: fix cmake compatibility error for freetype (pasta) 48f72be Merge #7360: fix: empty platformP2PPort deprecated field in protx listdiff results (pasta) a8cccff Merge #7298: fix(qt): keep PoSe score visible when hiding banned masternodes (pasta) Pull request description: Release PR for Dash Core v23.1.8, a patch release on top of v23.1.7. Fast-forwards from `v23.1.x` (currently at `chore: prepare v23.1.7 release`), 29 commits, no merge commits, no conflicts. ## Contents Backports of PRs already reviewed and merged on `develop`: `#7259` `#7347` `#7348` `#7351` `#7298` `#7360` `#7372` `#7387` `#7394` `#7395` `#7396` `#7398` `#7402` `#7408` `#7414` `#7415` `#7416` `#7418` `#7419` `#7424` `#7438` `#7439` `#7440` `#7442` `#7444` `#7450` `#7465` Plus `backport: bitcoin#27608`, a single commit taken from Dash #7237 because #7398's compact-block hardening depends on it. The rest of that v0.26 batch is intentionally not included on v23.1.x. The commit is byte-identical to its reviewed counterpart inside #7237. And release preparation: version bump, regenerated man pages, release notes, archived 23.1.7 notes. ## Note for reviewers: this branch was rebuilt An earlier revision of this PR was discarded and the branch rebuilt from scratch. Review comments on the previous revision point at commits that no longer exist, though the feedback itself was carried over (see below). The reason: several commits titled `Merge #NNNN` in the earlier revision contained substantial code that exists nowhere upstream — apparently written from a description of each PR rather than ported from its diff. For example, `feature_llmq_simplepose.py` is byte-identical between v23.1.7 and `develop`, yet the earlier `Merge #7408` rewrote 66 lines of it; `test/functional/p2p_governance_invs.py` does not exist on `develop` at all, yet had grown from 62 to 148 lines. That mislabeling matters because a commit titled `Merge #NNNN` invites less scrutiny, not more. It also had consequences: the earlier revision was **missing #7440 entirely**, and contained eleven consecutive commits that did not compile (code written against newer upstream APIs this branch does not have — `Misbehaving(Peer&)`, and `PeerIsBanned` used five commits before it was declared). Every commit on this branch has now been diffed against its upstream merge commit. Where a backport differs, it is because v23.1.x predates an upstream refactor and the change had to be applied to the pre-refactor file — for example #7418 and #7438 patch `signing_shares.cpp` / `spork.cpp` where upstream patches `net_signing.cpp` / `net_processing.cpp`. ## Dropped from this branch - **#7350** (`net: don't lock cs_main while reading blocks`) — dropped on review feedback. It is a 110-line lock-structure refactor of `ProcessGetBlockData` with no measured benefit, and it would add avoidable churn to the eventual master→develop merge-back. Nothing on this branch depends on it: #7398's compact-block work precedes it, and the remaining 14 commits replay with zero conflicts once it is removed. Thanks @knst. ## Added after the initial review pass - **#7351** (`fix: limit signing share sessions per peer`) — cherry-picked as a single commit and placed before #7402, matching upstream's merge order. The include block additionally carries `<ranges>`: upstream's diff adds only `<algorithm>` because develop already had it, whereas v23.1.x did not and the backported `GetSessionCount()` / `GetAnnouncementSessionCount()` use `std::ranges::count_if`. - **#7465** (`fix(qt): handle pixel-sized fonts when scaling widgets`) — cherry-picked from the five upstream commits. `optiontests.cpp` additionally includes `qt/guiutil_font.h`, because `fontsLoaded()` and `updateFonts()` are declared there on v23.1.x while develop declares them in `qt/guiutil.h`, which is all the upstream test includes. Two further backports were added later and applied without any adaptation -- their diffs are byte-for-byte identical to upstream: - **#7347** (`fix: punish invalid dstx messages`) - **#7348** (`fix: penalize oversized notfound messages`) ## Adaptations worth flagging - **#7360** — upstream gates `platformP2PPort` / `platformHTTPPort` in `protx listdiff` behind `IsServiceDeprecatedRPCEnabled()`. On 23.x those deprecated fields are deliberately not enforced through gating (see `bbcd9d543e6`), so shipping the gate as-is would silently drop two fields that v23.1.7 always returned. Changed to `if (true)` with a comment, per review feedback, keeping the block aligned with `develop`. The substantive fix from #7360 — reading the live port from `netInfo` instead of the always-zero scalar — is retained. - **#7415** — the pending-map caps (`MAX_PENDING_SIG_SHARES_PER_NODE`, `MAX_PENDING_SIG_SHARES_TOTAL`) are backported. The additional bound upstream places on batches awaiting verification is not, because it guards a condition that does not exist here: upstream's dispatcher pushes one task per batch inside an inner loop, whereas v23.1.x pushes a single looping worker per 10 ms tick. There is no unbounded task queue to bound. - **Man pages** — regenerated without the `lock` debug category, which only exists under `DEBUG_LOCKCONTENTION` and so is absent from release binaries. Thanks @UdjinM6 for catching this. ## Known CI failure macOS jobs are expected to fail. `actions/upload-artifact@v6` rejects filenames containing `:`, and the Xcode SDK ships Perl man pages with `::` in the name. A release-branch-only workaround existed on the earlier revision but was dropped as it corresponds to no upstream PR. This is accepted for this release. ## Testing - Every commit through #7465 compiles individually (verified for 27 of the 29; the three additions below were verified at the tip) — verified individually, not just at the tip. - Full build clean; no new warnings. - Unit tests pass. - Functional tests pass: `feature_llmq_signing` (both variants), `feature_llmq_chainlocks`, `feature_llmq_dkgerrors`, `feature_llmq_is_cl_conflicts`, `p2p_instantsend`, `feature_dip3_deterministicmns` (both wallet types), `rpc_coinjoin`. - Qt unit tests pass (32 cases, run under the `cocoa` platform plugin so the pixel-sized font regression from #7465 actually executes rather than self-skipping). - Lint: one pre-existing `lint-cppcheck-dash` failure, identical on v23.1.7, in files this branch does not touch. Top commit has no ACKs. Tree-SHA512: 0fa469c9a33820aa85fbb8b90c5877409d09490f746f1300b05ceda470a600765f900bec42e5aad5d90a2d46b44e28c20e44dc4a8fe719553a072298069eaec4
728f505 doc: record the v23.1.8 critical crash fixes in the release notes (pasta) ca56af8 fix(llmq): reject parentless quorum base blocks instead of terminating (pasta) a801d3f fix(llmq): reject unregistered LLMQ types from qsigshare before quorum lookup (pasta) 6c1f611 fix: skip already-removed conflicts when a ProTx key change clears the mempool (pasta) 24920a0 chore: prepare v23.1.8 release (pasta) 2194248 Merge #7348: fix: penalize oversized notfound messages (pasta) f5c72c3 Merge #7347: fix: punish invalid dstx messages (pasta) 550caf7 Merge #7465: fix(qt): handle pixel-sized fonts when scaling widgets (pasta) e203710 Merge #7419: fix(net): bound CoinJoin message vector intake (pasta) 5f5b960 Merge #7418: fix(net): bound signing message vector intake (Pasta) 7cc2cca Merge #7450: test: make governance vote fixtures wire-valid (Pasta) f011c80 Merge #7440: fix(net): bound governance vote signature deserialization (Pasta) 4b4d96a Merge #7442: fix(net): authorize governance inv responses via the net-layer per-peer request tracker (Pasta) f855b13 Merge #7444: fix(net): bound bloom message vectors before allocation (Pasta) 5b5c6fb Merge #7415: fix: bound pending sig share queue (Pasta) 9bbe808 Merge #7416: fix(net): bound quorum data response vectors (Pasta) da42f50 Merge #7424: fix: bound ChainLock seen cache (Pasta) 5b310df Merge #7438: fix: bound SPORK signature deserialization (Pasta) e118d0c Merge #7259: fix: dangling point to cj client (Pasta) 9921621 Merge #7439: refactor: add bounded vector deserialization (Pasta) 89bdf7c Merge #7414: fix(net): throttle per-object governance vote sync requests (Pasta) 44c396d Merge #7402: fix: bound pending recovered sig queue to prevent remote OOM (Pasta) 05cfe27 Merge #7351: fix: limit signing share sessions per peer (pasta) 3ef3a5b Merge #7408: fix: bound DKG contribution blob intake (pasta) 0ea6532 Merge #7387: test: migrate governance inv cache coverage to unit tests (Pasta) 8ffdf7f Merge #7398: backport: compact block relay hardening (bitcoin#26898, bitcoin#27626, bitcoin#27743, bitcoin#26969, bitcoin#29412, bitcoin#32646, bitcoin#33296) (Pasta) 2915142 backport: bitcoin#27608 - p2p: Avoid prematurely clearing download state for other peers (PastaClaw) 90b5473 Merge #7396: fix: run of circular-dependencies with python3.15 (Pasta) b003cdc Merge #7395: ci: update GitHub Actions pins for Node 24 (pasta) 97c3dd1 Merge #7394: fix: stabilize par help text in manpages (pasta) 8f8616b Merge #7372: backport: bitcoin#32693: depends: fix cmake compatibility error for freetype (pasta) 48f72be Merge #7360: fix: empty platformP2PPort deprecated field in protx listdiff results (pasta) a8cccff Merge #7298: fix(qt): keep PoSe score visible when hiding banned masternodes (pasta) Pull request description: ## Issue being fixed or feature implemented Merges master (v23.1.8) back into develop so develop carries the v23.1.8 release and, most importantly, the three remotely reachable crash fixes shipped on top of it. Without this, develop-based nodes remain vulnerable to all three crashes. ## What was done? Merged `upstream/master` into `develop`. The genuinely new payload is: - **Three remote-crash fixes** (with their regression tests): - skip already-removed conflicts when a ProTx key change clears the mempool (`txmempool.cpp`) - reject unregistered LLMQ types from `qsigshare` before quorum lookup (`llmq/blockprocessor.cpp`, `llmq/quorumsman.cpp`) - reject parentless quorum base blocks instead of terminating (`llmq/commitment.cpp`, `llmq/utils.cpp`, `validation.{cpp,h}`) - **Release bookkeeping**: v23.1.8 release notes, archived 23.1.7 notes, flatpak release entry, regenerated v23.1.8 man pages, and the `configure.ac` version bump (develop keeps `IS_RELEASE=false` and its own configure flags). Everything else on master since the last merge (the v23.1.x security-hardening train, #7259–#7465 and #7398) was dual-merged and already exists on develop as its own merge commits, so all conflicts from those files resolve to develop's side. Deliberate adaptations, itemized in the merge commit message: - The `qsigshare` LLMQ-type gate is ported into develop's `net_signing.cpp` and the parentless-base DKG check into develop's `net_dkg.cpp` (develop moved message processing out of `signing_shares.cpp`/`dkgsessionmgr.cpp`). - The defence-in-depth `find()` lookup is additionally applied to `CQuorumManager::GetCachedMutableQuorum()`, a develop-only method reached with a wire-supplied LLMQ type from the `QDATA` handler. - The new mempool regression test is adapted to develop's `CreateProRegTx`/`CreateProUpServTx`/`CreateProUpRevTx` helper signatures and `MemPoolOptionsForTest`. - `src/active/quorums.cpp` (deleted by develop's ActiveContext refactor) stays deleted; develop's #7416 equivalent already covers the new layout. ## How Has This Been Tested? Built with `--enable-debug` on macOS (arm64). Ran the new/extended suites — `evo_deterministicmns_tests`, `llmq_invalid_type_tests`, `evo_utils_tests` — plus adjacent ones (`llmq_signing_tests`, `llmq_dkg_tests`, `llmq_blockprocessor_tests`, `llmq_commitment_tests`, `llmq_utils_tests`, `mempool_tests`, `validation_tests`): all pass. The three regression tests abort the process on unpatched code. ## Breaking Changes None. `ChainstateManager::IsQuorumTypeEnabled()` loosens its `pindexPrev` parameter from `gsl::not_null` to a plain pointer (null now returns false instead of aborting); all existing callers are unaffected. ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have added or updated relevant unit/integration/functional/e2e tests - [x] I have made corresponding changes to the documentation - [ ] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: UdjinM6: utACK e15bb64 Tree-SHA512: 0897f0e1267c4083ef505127ceb18309e310caf36a066674ea298d66836afb86c762532e7cc68d6c0761142b2e5b291b497496b7e82d0f7ce60549761c0ebdd8
Depends on #7439. Please review only the three CoinJoin-specific commits here.
Issue being fixed or feature implemented
CoinJoin server messages could deserialize or process peer-controlled input/output vectors before enforcing CoinJoin session bounds. This hardens the final-signature and entry intake paths by separating the wire-safety bound from the per-entry semantic bound.
What was done?
DSSIGNFINALTXonly during signing and only from an active session participant.DSSIGNFINALTXinput deserialization at the largest complete CoinJoin size: currently 20 participants × 9 inputs = 180.CCoinJoinEntryvectors, rejecting larger declarations before vector materialization.AddEntry().MAX + 1input rule, oversized-output flag, and asymmetric input/output deserialization behavior.The reusable bounded-vector deserialization primitive is introduced separately in #7439.
How Has This Been Tested?
make -C src -j15 test/test_dash./src/test/test_dash --run_test=coinjoin_inouts_tests(8/8 passed)test/lint/lint-whitespace.pyLogPrintformat-string lintclang-format-diff.pygit diff --check9474fc5e2a1..48a1eb95838): ship, 0 findingsBreaking Changes
None.
Checklist