Repository navigation
test: use single-member in functional tests: feature_mnehf, feature_notifications, p2p_instantsend - #7778
Conversation
Mine until the masternodes are confirmed for the next DKG first, like mine_quorum does, and sync blocks only. mine_quorum_single_member mined the next cycle without checking that the masternode is confirmed for it, so the first cycle after setup was skipped and the quorum only appeared one cycle later than the caller expected. Also sync of mempools could stalls when a masternode's mempool legitimately differs from the miner's.
The EHF signal only needs a recovered signature of any quorum. Using single-member quorum reduces overhead by adding extra nodes, mining heavier quorums and exchanging recovered sigs messages The blocks before the `started` check are mined up to the window boundary instead of a fixed count, since the window no longer lines up with the shorter setup.
The ChainLock and InstantSend notifications only need the locks to happen, not a multi-member quorum, and the quorum formation with four masternodes dominated the runtime. Run it with one masternode and single-member quorums.
The functional test p2p_instantsend.py is about InstantSend on the non-masternode nodes. Run them with one masternode and single-member quorums. The InstantSend after a full restart scenario needs sig shares from several restarted members, which a single-member quorum can't exercise, so it moves to feature_llmq_connections.
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
|
✅ Final review complete — no blockers (commit e308b31) |
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (5)
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review. WalkthroughThe functional tests now use smaller node and masternode setups with single-member quorum mining. The MNEHF test updates quorum selection and its window-boundary check. Post-restart peer verification and InstantSend coverage now run in the LLMQ connections test instead of the P2P InstantSend test. Priority: ⬇️ Low Estimated code review effort: 3 (Moderate) | ~25 minutes Merge Risk: ⚪ Minimal · up to The quorum setup and relocated restart checks have no established merge-blocking defect. The relay safely accepts already-known transactions; merge after normal checks pass. 🚥 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 |
thepastaclaw
left a comment
There was a problem hiding this comment.
Final validation — Phase 1 + Phase 2
The PR efficiently reduces functional-test quorum overhead, but the MnEHF duplicate-signal case can construct a payload naming one quorum while signing it with another. The signing helper independently selects a quorum from the current chain, so the transaction may fail signature validation before the duplicate-bit behavior is exercised.
🔴 1 blocking
Review provenance
Source: reviewer 1: gemini-3.8-flash-high (agent: phase1-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: dash-core-commit-history); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
normalbygpt-6.1-sol(effort low) — This is a cross-cutting functional-test refactor affecting quorum setup, mempool synchronization, and test coverage across five files, but it does not change production consensus, networking, cryptography, funds, or storage behavior. - Phase 1 reviewers:
gemini-3.8-flash-high— general (completed, effort high); agentphase1-reviewer - Phase 1 model:
gemini-3.8-flash-high— antigravity quota: weekly 90% left, 5h 45% left - Fresh verifier:
gpt-6.1-sol— final-verifier; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort high); agentphase2-reviewer,gpt-6.1-sol— dash-core-commit-history (completed, effort high); agentphase2-reviewer
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `test/functional/feature_mnehf.py`:
- [BLOCKING] test/functional/feature_mnehf.py:225: Sign the duplicate MnEHF transaction with the quorum named in its payload
This call explicitly forces the payload's `quorumHash` to the original signal's quorum, but `create_mnehf()` still calls `get_recovered_sig(request_id, msgHash)` without passing that quorum. `get_recovered_sig()` independently runs `selectquorum` against the current chain and uses the selected quorum for signing. If selection has changed, the signature is produced by a different quorum than the one encoded in the payload. `CheckMNHFTx` verifies against the payload's quorum, so `send_tx()` can fail with an invalid MnEHF signature instead of testing duplicate-bit rejection. Make the signing helper accept and use the explicitly selected quorum, or otherwise reuse the original quorum's recovered signature.
| ehf_tx_duplicate = self.send_tx(self.create_mnehf(28, pubkey)) | ||
| # Same quorum as the original signal: a quorum member never signs the same request id twice, | ||
| # so only an identical payload gets its (already existing) recovered signature | ||
| ehf_tx_duplicate = self.send_tx(self.create_mnehf(28, pubkey, quorumHash=format(mnehf_payload.quorumHash, '064x'))) |
There was a problem hiding this comment.
🔴 Blocking: Sign the duplicate MnEHF transaction with the quorum named in its payload
This call explicitly forces the payload's quorumHash to the original signal's quorum, but create_mnehf() still calls get_recovered_sig(request_id, msgHash) without passing that quorum. get_recovered_sig() independently runs selectquorum against the current chain and uses the selected quorum for signing. If selection has changed, the signature is produced by a different quorum than the one encoded in the payload. CheckMNHFTx verifies against the payload's quorum, so send_tx() can fail with an invalid MnEHF signature instead of testing duplicate-bit rejection. Make the signing helper accept and use the explicitly selected quorum, or otherwise reuse the original quorum's recovered signature.
source: gpt-6.1-sol (phase2-reviewer: general)
There was a problem hiding this comment.
The mismatch can't happen: the member has already voted on this request id
with the same msgHash, so quorum sign for the newly selected quorum is
refused ("already voted ... Not voting again", allowReSign=false) and
get_recovered_sig returns the existing recovered signature of the original
quorum, which is the one named in the payload.
That said, the pinned payload was byte-identical to the original signal, so
there is no reason to build and "sign" it again. Changed the duplicate step to
resend the original ehf_tx and dropped the quorumHash parameter from
create_mnehf.
There was a problem hiding this comment.
Agreed. Reusing the original ehf_tx avoids attempting a second signature for the same request ID and preserves the original quorum hash and recovered signature, so this resolves the mismatch concern.
Marking this resolved.
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review after discussion — commit e308b31
Standing review was CHANGES_REQUESTED; this re-review is COMMENT: no blocking findings remain.
🔴 0 blocking | 🟡 0 suggestion(s) | 💬 0 nitpick(s)
No longer blocking:
- Sign the duplicate MnEHF transaction with the quorum named in its payload
Same commit as the standing review; the inline threads above carry the per-finding outcome. This follow-up exists only to correct the verdict.
Review provenance
Source: conversation lane gpt-6.1-sol (agent: conversation); no reviewer or verifier lanes ran for this follow-up
- Verdict moved because every blocking finding on this commit was withdrawn, resolved or deferred in the inline discussion; the code was not re-reviewed
…D on the reviewed commit (#38) On dashpay/dash#7778 the full review's only finding was a blocker the author argued away. The conversation lane lifted it but posted a COMMENT, which on GitHub never clears a REQUEST_CHANGES, so a ready PR kept showing a blocking review. It also labelled an unpushed change FIXED. - A conversation follow-up now APPROVEs when no blocker and nothing above a nitpick is left of the publishing run's final verifier set, something of that set was lifted, and the run is one the pipeline would approve on (Phase 2 ok, not degraded, fresh audit ok on a later round). If only the fresh audit is missing, it posts COMMENT and re-queues the commit once. - The standing set comes from the verifier's verify2 rows, so findings dedupe carried onto other (even resolved) threads still count; open threads from earlier heads no longer do. - Live head and review state are re-read right before posting. - FIXED is replaced by FIX_PENDING in the conversation lane; it lifts nothing. - A lifted finding whose thread stays open gets a status line on the bot's own root comment (the bot cannot resolve threads without write access); dedupe strips it, and a later review that keeps the finding clears it. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…hf, feature_notifications, p2p_instantsend e308b31 test: use a single-member quorum in p2p_instantsend (Konstantin Akimov) 233a89b test: use a single-member quorum in feature_notifications (Konstantin Akimov) 49e09b9 test: use a single-member quorum in feature_mnehf (Konstantin Akimov) 2e6e5bb test: make mine_quorum_single_member usable right after setup (Konstantin Akimov) Pull request description: ## Issue being fixed or feature implemented The ChainLock and InstantSend Notifications, P2P InstantSend and EHF feature tests only need the locks & ehf to happen, not a multi-member quorum. ## What was done? - fix: make mine_quorum_single_member usable right after setup - fix: stall of single-member quorum due to mempool's sync - use a single-member quorum in feature_mnehf - use a single-member quorum in feature_notifications - use a single-member quorum in p2p_instantsend - moved testing of node's connection after restart to feature_llmq_connections ## How Has This Been Tested? CI run with tsan: https://github.com/dashpay/dash/actions/runs/36907697165/job/110532135383?pr=7778 https://github.com/dashpay/dash/actions/runs/36752482052/job/110043834012 | Test | develop (s) | PR (s) | |-----------------------------|-------------|--------| | feature_llmq_connections.py | 142 | 157 | | feature_mnehf.py | 102 | 74 | | feature_notifications.py | 44 | 31 | | p2p_instantsend.py | 100 | 56 | Local run: | Test | develop (s) | PR (s) | |-----------------------------|-------------|--------| | feature_llmq_connections.py | 80 | 88 | | feature_mnehf.py | 49 | 41 | | feature_notifications.py | 29 | 21 | | p2p_instantsend.py | 81 | 42 | | **ALL (accumulated)** | **239** | **192** | ## Breaking Changes N/A ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone Top commit has no ACKs. Tree-SHA512: 03de5bb1bbeb525848a5d0079f31e89f2906e1fde0606f5a8af9d30bb959d737bdb98ed0fe74261ceab909488b6b96cc512557aeb150105e1dce909c65f7f9a0 (cherry picked from commit 8819507)
fbe6526 Merge #7807: feat(consensus): hold EvoNode shares and multiple payouts behind a new evo_shares deployment (pasta) 57fd2d9 Merge #7776: fix: keep a pending ProUpServTx across a registrar update that keeps the operator key (pasta) ca69801 Merge #7803: fix: return non-zero amount of accounts after sethdseed (pasta) 57a8f07 Merge #7796: backport: bitcoin#26720 (remaining), partial bitcoin#29523: weight-check the knapsack exact-match selection (pasta) 4eb82f6 Merge #7786: fix(net): keep a dedicated onion listener when -bind is given and correct the bind release note (pasta) 70626a0 Merge #7793: backport: partial bitcoin#28868 (wallet: reload wallet if migration exited early, keep mixed watchonly txs) (pasta) 250a3cd Merge #7790: fix: guard cached governance object flags with the object lock (pasta) 700c195 Merge #7787: fix: only sign EHF signals inside the deployment's start/timeout window (pasta) a3b0f3c Merge #7785: fix: restore the txindex requirement when governance validation is enabled (pasta) 2d1735d Merge #7794: fix(wallet): floor the denomination gap threshold so rebalancing cannot oscillate (pasta) d9f6592 Merge #7783: fix: stop fish completion from re-running the typed dash-cli command (pasta) 89d44c8 Merge #7795: backport: bitcoin#34272, partial bitcoin#31650 (pass PSBT by const reference in PSBTInputSignedAndVerified) (pasta) a1d7411 Merge #7779: fix!: report legacy evonode Platform addresses when listdiff changes its address (pasta) 73f6ea2 Merge #7789: fix(qt): report malformed lang/font settings instead of aborting at startup (pasta) 40de493 Merge #7781: fix(rpc): use a consistent tip height in quorum dkgstatus (pasta) 7d1a90d Merge #7791: fix(net): request object votes from nPeersPerHashMax peers (pasta) 51b145c Merge #7778: test: use single-member in functional tests: feature_mnehf, feature_notifications, p2p_instantsend (pasta) Pull request description: ## Issue being fixed or feature implemented Backports for v24.0.0-rc.3. `v24.0.x` was cut at the v24.0.0-rc.2 tag (1e239d4), and develop has since moved to 24.1.0 (#7775), so rc.3 is built from this branch instead of being tagged on develop like rc.1 and rc.2. ## What was done? Cherry-picked (`git cherry-pick -m1 -x`) every develop merge since rc.2 that carries `backport-candidate-24.0.x`, plus #7778, which #7807's test needs. They are in develop merge order: - #7778 test: use single-member in functional tests: feature_mnehf, feature_notifications, p2p_instantsend (test-only. Needed because #7807's `feature_evo_shares_activation.py` depends on its `mine_quorum_single_member()` fix and fails without it.) - #7791 fix(net): request object votes from nPeersPerHashMax peers - #7781 fix(rpc): use a consistent tip height in quorum dkgstatus - #7789 fix(qt): report malformed lang/font settings instead of aborting at startup - #7779 fix!: report legacy evonode Platform addresses when listdiff changes its address - #7795 backport: bitcoin#34272, partial bitcoin#31650 (pass PSBT by const reference in PSBTInputSignedAndVerified) - #7783 fix: stop fish completion from re-running the typed dash-cli command - #7794 fix(wallet): floor the denomination gap threshold so rebalancing cannot oscillate - #7785 fix: restore the txindex requirement when governance validation is enabled - #7787 fix: only sign EHF signals inside the deployment's start/timeout window - #7790 fix: guard cached governance object flags with the object lock - #7793 backport: partial bitcoin#28868 (wallet: reload wallet if migration exited early, keep mixed watchonly txs) - #7786 fix(net): keep a dedicated onion listener when -bind is given and correct the bind release note. Includes partial bitcoin#36170 (5f40d56). Upstream's dedicated-onion-bind changes to `feature_torcontrol.py` and `p2p_private_broadcast.py` are not included, because those tests depend on upstream commits (5693833, e74d54e) that Dash does not have. - #7796 backport: bitcoin#26720 (remaining), partial bitcoin#29523: weight-check the knapsack exact-match selection - #7803 fix: return non-zero amount of accounts after sethdseed - #7776 fix: keep a pending ProUpServTx across a registrar update that keeps the operator key - #7807 feat(consensus): hold EvoNode shares and multiple payouts behind a new evo_shares deployment One pick needed conflict resolution, in a test only, described in its commit message: #7793, `test/functional/wallet_migration.py`. `test_conflict_txs()` comes from bitcoin#28542 (#7762), which is not on this branch, so it is left out. The C++ part of #7793 is identical to develop. Merged since rc.2 but intentionally not included: #7775 (24.1 version bump), #7260 and #7804 (new Qt feature and its CI fix), #7584 (refactor), routine upstream backports #7257, #7759, #7762, #7768, #7788, #7801, and test/CI-only changes #7777 and #7797. No version change is needed. `configure.ac` is already 24.0.0 with `CLIENT_VERSION_IS_RELEASE` false, so the build takes its version string from the `v24.0.0-rc.3` tag, as it did for rc.2. ## How Has This Been Tested? Built on macOS arm64 against depends with `--enable-debug --enable-werror` (dashd, dash-qt, tests). - `make check`: all unit test suites pass, including `test_dash-qt`. - Functional tests, all passing: `feature_evo_shares_activation.py`, `feature_masternode_shares.py`, `feature_mnehf.py`, `feature_governance.py --descriptors`, `feature_governance_objects.py`, `feature_governance_txindex_devnet.py`, `feature_proxy.py`, `feature_notifications.py`, `feature_llmq_connections.py`, `feature_llmq_chainlocks_automatic.py`, `feature_llmq_singlenode.py`, `p2p_instantsend.py`, `rpc_blockchain.py` (v1 and v2 transport), `rpc_netinfo.py`, `rpc_quorum.py`, `rpc_verifychainlock.py`, `wallet_hd.py` (legacy and descriptors), `wallet_migration.py`. - `feature_bind_extra.py` (from #7786) only runs on Linux and was skipped locally, so CI covers it. Every touched file was diffed against develop. The remaining differences come only from develop PRs that are not part of this backport. ## Breaking Changes Carried over from the picked PRs: - #7807: consensus change behind the new `evo_shares` deployment (bit 14). Mainnet and testnet are unaffected until it activates. Devnets with `v24` already active and an EvoNode carrying several owner payouts need to check or reset. New RPC `protx shared_register_prepare_evo`. - #7785: outside regtest, a node with `-txindex=0` and without `-disablegovernance` refuses to start again, as before v23.1.0. - #7786: carries a partial bitcoin#36170. A node started with `-bind` but no specific `-bind=<addr:port>=onion` now refuses to start while `-listenonion` is enabled. That is the default when listening, even without Tor configured. A wildcard onion bind is also refused. Such nodes need `-bind=127.0.0.1:<port>=onion` or `-listenonion=0`. Nodes without `-bind`, including those using only `-whitebind`, keep the default `127.0.0.1:9996` (`19996` testnet) onion target. See `doc/release-notes-7300.md`. - #7779: `protx listdiff` now includes `platform_p2p` and `platform_https` for a legacy-address evonode whose core P2P address changes. ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have made corresponding changes to the documentation - [ ] I have assigned this pull request to a milestone 🤖 Generated with [Claude Code](https://claude.com/claude-code) Top commit has no ACKs. Tree-SHA512: 8cb01bdb0234f31b5dd2c105b69673de148922991a7523627395c0e0ccfa22b94be5ffbecc842398d443bc90fd9baf2eee6a9cf6fcdbbd1626eb00b93726a55a
Issue being fixed or feature implemented
The ChainLock and InstantSend Notifications, P2P InstantSend and EHF feature tests only need the locks & ehf to happen, not a multi-member quorum.
What was done?
How Has This Been Tested?
CI run with tsan:
https://github.com/dashpay/dash/actions/runs/36907697165/job/110532135383?pr=7778
https://github.com/dashpay/dash/actions/runs/36752482052/job/110043834012
Local run:
Breaking Changes
N/A
Checklist: