feat(qt): add governance voting functionality to Qt wallet#6690
feat(qt): add governance voting functionality to Qt wallet#6690PastaPastaPasta merged 11 commits intodashpay:developfrom
Conversation
WalkthroughThis change set introduces direct governance proposal voting capabilities to the Qt GUI. Users with masternode voting keys can now cast "Yes", "No", or "Abstain" votes from the governance tab via a right-click context menu. The UI is updated to display the count of votable masternodes in the wallet. Core and interface changes add new methods for signing and submitting governance votes, including wallet support for signing votes using either a special transaction payload or standard message signing, depending on the network. Supporting code updates integrate wallet and masternode data, error handling, and UI feedback for the voting process. Additionally, some governance vote methods were moved inline in the header for efficiency, and obsolete vote signing functions were removed and replaced with the new wallet signing method. ✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
src/qt/governancelist.cpp (1)
1-639:⚠️ Potential issueFix code formatting to match project standards.
The CI pipeline indicates formatting issues. Please run clang-format on this file to ensure consistent code style.
#!/bin/bash # Check if clang-format is available and show the formatting differences if command -v clang-format &> /dev/null; then echo "Checking formatting differences for src/qt/governancelist.cpp..." clang-format --style=file src/qt/governancelist.cpp | diff -u src/qt/governancelist.cpp - else echo "clang-format not found. Please install it to check formatting." fi🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check
[error] 1-1000: Clang format differences found. The file does not conform to the required code style. Please run clang-format to fix formatting issues.
🧹 Nitpick comments (2)
doc/release-notes/release-notes-6690.md (1)
4-5: Minor grammatical improvements for better readability.The release notes accurately document the new governance voting features. Consider these minor improvements for clarity:
-- Added governance proposal voting functionality to the Qt interface. Users with masternode voting keys can now vote on governance proposals directly from the governance tab via right-click context menu (#6690). -- Added masternode count display to governance tab showing how many masternodes the wallet can vote with (#6690). +- Added governance proposal voting functionality to the Qt interface. Users with masternode voting keys can now vote on governance proposals directly from the governance tab via the right-click context menu (#6690). +- Added masternode count display to the governance tab, showing how many masternodes the wallet can vote with (#6690).🧰 Tools
🪛 LanguageTool
[uncategorized] ~4-~4: You might be missing the article “the” here.
Context: ...ls directly from the governance tab via right-click context menu (#6690). - Added mas...(AI_EN_LECTOR_MISSING_DETERMINER_THE)
[uncategorized] ~5-~5: Possible missing comma found.
Context: ... masternode count display to governance tab showing how many masternodes the wallet...(AI_HYDRA_LEO_MISSING_COMMA)
src/qt/governancelist.cpp (1)
511-512: Consider validating the vote outcome parameter.While the function is currently only called with valid outcomes, adding validation would make it more robust.
void GovernanceList::voteForProposal(vote_outcome_enum_t outcome) { + // Validate outcome + if (outcome != VOTE_OUTCOME_YES && outcome != VOTE_OUTCOME_NO && outcome != VOTE_OUTCOME_ABSTAIN) { + QMessageBox::warning(this, tr("Voting Failed"), + tr("Invalid vote outcome.")); + return; + } + if (!walletModel) {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📥 Commits
Reviewing files that changed from the base of the PR and between 7520644 and 4f41f9be5587601259b9d343675c6aec89d60db8.
📒 Files selected for processing (9)
doc/release-notes/release-notes-6690.md(1 hunks)src/interfaces/node.h(2 hunks)src/interfaces/wallet.h(1 hunks)src/node/interfaces.cpp(2 hunks)src/qt/forms/governancelist.ui(1 hunks)src/qt/governancelist.cpp(6 hunks)src/qt/governancelist.h(5 hunks)src/qt/walletview.cpp(1 hunks)src/wallet/interfaces.cpp(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
src/interfaces/node.h (1)
src/node/interfaces.cpp (2)
vote(145-157)vote(145-145)
src/qt/walletview.cpp (1)
src/qt/governancelist.h (1)
walletModel(44-44)
src/node/interfaces.cpp (1)
src/interfaces/node.h (11)
vote(71-71)context(59-59)context(59-59)context(72-72)context(72-72)context(81-81)context(81-81)context(94-94)context(94-94)context(363-363)context(363-363)
src/wallet/interfaces.cpp (2)
src/interfaces/wallet.h (1)
hash(118-118)src/wallet/wallet.h (7)
hash(501-501)hash(551-551)hash(554-554)hash(557-557)hash(559-559)hash(618-618)hash(658-658)
🪛 LanguageTool
doc/release-notes/release-notes-6690.md
[uncategorized] ~4-~4: You might be missing the article “the” here.
Context: ...ls directly from the governance tab via right-click context menu (#6690). - Added mas...
(AI_EN_LECTOR_MISSING_DETERMINER_THE)
[uncategorized] ~5-~5: Possible missing comma found.
Context: ... masternode count display to governance tab showing how many masternodes the wallet...
(AI_HYDRA_LEO_MISSING_COMMA)
🪛 GitHub Actions: Clang Diff Format Check
src/qt/governancelist.cpp
[error] 1-1000: Clang format differences found. The file does not conform to the required code style. Please run clang-format to fix formatting issues.
⏰ Context from checks skipped due to timeout of 90000ms (6)
- GitHub Check: x86_64-w64-mingw32 / Build depends
- GitHub Check: x86_64-apple-darwin / Build depends
- GitHub Check: x86_64-pc-linux-gnu_nowallet / Build depends
- GitHub Check: x86_64-pc-linux-gnu_multiprocess / Build depends
- GitHub Check: arm-linux-gnueabihf / Build depends
- GitHub Check: x86_64-pc-linux-gnu / Build depends
🔇 Additional comments (18)
src/interfaces/wallet.h (1)
117-118: LGTM! Clean interface extension for governance voting support.The new
signSpecialTxPayloadmethod follows established interface patterns and provides the necessary signing capability for governance vote transactions. The method signature is well-designed with appropriate parameter types and return semantics.src/interfaces/node.h (2)
31-31: LGTM! Proper forward declaration placement.The forward declaration for
CGovernanceVoteis correctly positioned with other class declarations and follows the established pattern in the file.
71-71: LGTM! Well-designed interface method for vote processing.The
processVoteAndRelaymethod follows established interface patterns with appropriate parameter types and error handling. The implementation insrc/node/interfaces.cpplines 145-157 shows proper validation of required managers and comprehensive error reporting.src/qt/walletview.cpp (1)
111-111: LGTM! Proper wallet model initialization for governance voting.The addition of
setWalletModel(walletModel)for the governance list page follows the established pattern used by other components (likemasternodeListPageon line 106). This ensures the governance list has proper access to wallet functionality needed for vote signing and submission.src/wallet/interfaces.cpp (1)
192-195: LGTM! Clean interface implementation.The
signSpecialTxPayloadmethod correctly implements the pure virtual interface method by delegating to the underlying wallet'sSignSpecialTxPayloadmethod. The implementation follows the established pattern used by other methods in theWalletImplclass.src/qt/forms/governancelist.ui (1)
76-115: LGTM! Well-structured UI layout changes.The addition of masternode count display elements is properly implemented:
- The expanding spacer provides flexible layout adjustment
- The new label pair ("Masternode Count:" and count display) follows the existing pattern used for "Proposal Count:"
- Spacing adjustments accommodate the new elements appropriately
src/node/interfaces.cpp (3)
14-14: LGTM! Necessary include for governance exception handling.The include for
governance/exceptions.his required for theCGovernanceExceptiontype used in theprocessVoteAndRelaymethod implementation.
17-17: LGTM! Required include for governance vote types.The include for
governance/vote.his necessary for theCGovernanceVoteparameter type in theprocessVoteAndRelaymethod.
145-157: LGTM! Robust implementation with proper error handling.The
processVoteAndRelaymethod implementation is well-structured:
- Dependency validation: Properly checks for required components (governance manager, connection manager, peer manager) before proceeding
- Exception handling: Uses
CGovernanceExceptionto capture and extract error messages from the underlying governance system- Error reporting: Provides clear error messages both for processing failures and missing dependencies
- Return semantics: Correctly returns boolean success/failure status
The implementation follows the established pattern used by other methods in the
GOVImplclass.src/qt/governancelist.h (8)
9-9: LGTM! Required include for voting functionality.The include for
governance/vote.his necessary for thevote_outcome_enum_ttype used in thevoteForProposalmethod signature.
22-22: LGTM! Standard include for container usage.The
<map>include is required for thestd::map<uint256, CKeyID> votableMasternodesmember variable.
33-33: LGTM! Proper forward declaration.The forward declaration for
WalletModelis appropriate since the class only uses a pointer toWalletModelin the interface, avoiding unnecessary header dependencies.
44-44: LGTM! Clean public interface addition.The
setWalletModelmethod provides a clean way to inject the wallet model dependency into the governance list widget, following the same pattern assetClientModel.
48-48: LGTM! Properly initialized member.The
walletModelmember is appropriately declared as a pointer with nullptr initialization, consistent with the existingclientModelmember.
57-62: LGTM! Well-designed voting interface.The voting-related additions are well-structured:
- Data member:
votableMasternodesmap efficiently tracks eligible masternodes by their proTxHash to voting key mapping- Helper methods:
updateVotingCapability()provides centralized logic for determining voting eligibilitycanVote()offers a simple inline check using the votable masternodes statevoteForProposal()encapsulates the core voting logic with parameterized outcomeThe design promotes clean separation of concerns and reusability.
68-68: LGTM! Consistent with existing update pattern.The
updateMasternodeCount()slot follows the same naming and signature pattern as the existingupdateProposalCount()method.
71-75: LGTM! Complete voting action interface.The voting slots provide a complete set of actions for all possible vote outcomes:
voteYes()- for supporting proposalsvoteNo()- for opposing proposalsvoteAbstain()- for neutral stanceThis covers all standard governance voting options and will integrate well with context menu actions.
src/qt/governancelist.cpp (1)
588-599:⚠️ Potential issueFix incorrect PKHash usage in vote signing.
The code uses
PKHash(votingKeyID)butvotingKeyIDis already aCKeyID(which is a hash). This double-hashing would cause signing to fail on non-testnet networks.// Other networks use SignMessage std::string strMessage = vote.GetSignatureString(); std::string signature; - SigningResult result = walletModel->wallet().signMessage(strMessage, PKHash(votingKeyID), signature); + SigningResult result = walletModel->wallet().signMessage(strMessage, votingKeyID, signature); if (result == SigningResult::OK) {Likely an incorrect or invalid review comment.
src/qt/forms/governancelist.ui
Outdated
There was a problem hiding this comment.
maybe add hint with some explanation of what this count for?
src/qt/governancelist.cpp
Outdated
There was a problem hiding this comment.
let's re-use helper from rpc code here?
static bool SignVote(const CWallet& wallet, const CKeyID& keyID, CGovernanceVote& vote)
There was a problem hiding this comment.
Hmm, I didn't think it made sense to directly use RPC code in qt; seems to violate separation concepts
There was a problem hiding this comment.
yes, that's right; reference to RPC headers is not good. but you can move this helper to src/wallet/ or src/governance/.
There was a problem hiding this comment.
see 20effe0, moving to src/governance causes circular dependency
|
It would be nice to show voting status for wallets with masternodes if it could be easily done - like "x yes votes, x no votes, x abstain votes" or something. |
Please further describe where / how this would / should be displayed |
With an additional column in the table that would only be displayed if the wallet contained masternode voting keys? |
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
CI failed |
src/governance/vote.cpp
Outdated
src/governance/vote.h
Outdated
There was a problem hiding this comment.
nit:; should revert this changes too
src/wallet/wallet.cpp
Outdated
There was a problem hiding this comment.
wallet/wallet.cpp:2050:39: error: member access into incomplete type 'CGovernanceVote'
2050 | if (!SignSpecialTxPayload(vote.GetSignatureHash(), keyID, signature)) {
| ^
./validationinterface.h:22:7: note: forward declaration of 'CGovernanceVote'
22 | class CGovernanceVote;
| ^
missing vote.h include
5e2d04f to
1cb74e7
Compare
knst
left a comment
There was a problem hiding this comment.
LGTM 1cb74e75aa0090c5cfca0ec7e70ff31bf63193c8
|
This pull request has conflicts, please rebase. |
|
This pull request has conflicts, please rebase. |
- Add right-click context menu to governance proposals with Vote Yes/No/Abstain options - Implement voting capability detection based on masternode voting keys in wallet - Add vote signing and submission logic matching RPC implementation - Handle testnet-specific signing (SignSpecialTxPayload) vs mainnet (SignMessage) - Add processVoteAndRelay interface method between Qt and core - Update wallet interfaces to support special transaction payload signing - Show voting results in dialog with success/failure counts and error details Users can now vote on governance proposals directly from the GUI if they have masternode voting keys in their wallet, eliminating the need to use CLI commands.
- Display number of masternodes wallet can vote with - Position masternode count next to proposal count on the right - Update count when masternode list changes - Helps users understand their voting capability at a glance
- Remove trailing whitespace in wallet.h documentation - Remove unnecessary CWallet forward declaration from vote.h - Add missing governance/vote.h include in wallet.cpp
The methods GetSignatureString() and GetSignatureHash() were only available in libbitcoin_node.a but were being called from wallet.cpp. This caused undefined reference errors when linking dash-wallet since it doesn't link against libbitcoin_node. Moving these simple methods to the header as inline functions resolves the linking issue without requiring wallet binaries to link against the entire node library.
d74f0dc to
cf4e9e6
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
doc/release-notes/release-notes-6690.md (2)
1-2: Standardise header style with existing release-notes filesMost previous release-notes sections use ATX (
###) headers instead of underline style. Aligning with that convention avoids visual inconsistency and prevents accidental linter warnings about underline length.-GUI changes ----------- +### GUI Changes
4-5: Minor wording & article fixes; also removes superfluous PR numberGrammar-check and CI both flagged these lines. The tweaks below read more fluently and should satisfy whitespace/spell-check linters.
-- Added governance proposal voting functionality to the Qt interface. Users with masternode voting keys can now vote on governance proposals directly from the governance tab via right-click context menu (#6690). -- Added masternode count display to governance tab showing how many masternodes the wallet can vote with (#6690). +- Added governance-proposal voting functionality to the Qt interface. Users with masternode voting keys can now cast votes directly from the governance tab via **the** right-click context menu. +- Added a masternode-count display on the governance tab, indicating how many masternodes the wallet can vote with.(optional) If you prefer to keep the PR reference, append it once at the end of the file rather than in every bullet.
Ensure
codespellpasses after these edits.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📥 Commits
Reviewing files that changed from the base of the PR and between d74f0dcfcd1dd4dbf5a1d41f12609aa4cae95fc8 and cf4e9e6.
📒 Files selected for processing (11)
doc/release-notes/release-notes-6690.md(1 hunks)src/governance/vote.cpp(0 hunks)src/governance/vote.h(4 hunks)src/interfaces/node.h(2 hunks)src/interfaces/wallet.h(1 hunks)src/node/interfaces.cpp(2 hunks)src/qt/forms/governancelist.ui(1 hunks)src/qt/governancelist.cpp(6 hunks)src/qt/governancelist.h(5 hunks)src/qt/walletview.cpp(1 hunks)src/rpc/governance.cpp(1 hunks)
💤 Files with no reviewable changes (1)
- src/governance/vote.cpp
🚧 Files skipped from review as they are similar to previous changes (9)
- src/qt/walletview.cpp
- src/interfaces/wallet.h
- src/qt/forms/governancelist.ui
- src/interfaces/node.h
- src/governance/vote.h
- src/rpc/governance.cpp
- src/node/interfaces.cpp
- src/qt/governancelist.h
- src/qt/governancelist.cpp
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: kwvg
PR: dashpay/dash#6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
Learnt from: kwvg
PR: dashpay/dash#6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
doc/release-notes/release-notes-6690.md (1)
Learnt from: kwvg
PR: dashpay/dash#6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
🪛 LanguageTool
doc/release-notes/release-notes-6690.md
[grammar] ~1-~1: Use proper spacing conventions.
Context: GUI changes ----------- - Added governance proposal voting functio...
(QB_NEW_EN_OTHER_ERROR_IDS_000007)
[grammar] ~4-~4: Use articles correctly.
Context: ...ls directly from the governance tab via right-click context menu (#6690). - Added masternod...
(QB_NEW_EN_OTHER_ERROR_IDS_000004)
[grammar] ~4-~4: Use proper spacing conventions.
Context: ...ab via right-click context menu (#6690). - Added masternode count display to govern...
(QB_NEW_EN_OTHER_ERROR_IDS_000007)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: x86_64-w64-mingw32 / Build depends
- GitHub Check: x86_64-pc-linux-gnu_multiprocess / Build depends
- GitHub Check: x86_64-apple-darwin / Build depends
- GitHub Check: x86_64-pc-linux-gnu_nowallet / Build depends
- GitHub Check: x86_64-pc-linux-gnu / Build depends
- GitHub Check: arm-linux-gnueabihf / Build depends
|
rebase + fixes looks clean Consider clang-format for cf4e9e6 |
…Qt wallet cf4e9e6 fix: move CGovernanceVote inline methods to header for wallet linkage (pasta) 6f0723a chore: run clang-format (pasta) 2db939e fix: address PR review comments (pasta) bd0f59e feat(governance): implement SignGovernanceVote method in CWallet for vote signing (pasta) 13b4117 feat(governance): refactor vote signing logic into a helper function (pasta) 778a0b1 feat(gui): add tooltip for masternode count display in governance tab (pasta) 81d6648 chore: apply clang-format (pasta) edfe1ee refactor(governance): avoid recursion in wallet unlock handling (pasta) 24240a6 docs: add release notes for governance voting GUI feature (pasta) 0caee40 feat(gui): add masternode count display to governance tab (pasta) 5ac8475 feat(gui): add governance voting functionality to Qt wallet (pasta) Pull request description: ## Issue being fixed or feature implemented - Why is this change required? Currently, users must use CLI commands (gobject vote-many) to vote on governance proposals, which is not user-friendly for non-technical users who prefer the GUI wallet. - What problem does it solve? This eliminates the need to use command-line tools for governance voting, making the voting process accessible to all GUI wallet users who own masternodes. ## What was done? This PR adds complete governance voting functionality to the Qt wallet interface: - Added right-click context menu to governance proposals table with "Vote Yes", "Vote No", and "Vote Abstain" options - Implemented voting capability detection that checks if the wallet contains any masternode voting keys - Added vote signing and submission logic that matches the existing RPC implementation (gobject vote-many) - Implemented network-specific signing: - Testnet: Uses SignSpecialTxPayload with vote.GetSignatureHash() - Other networks: Uses SignMessage with vote.GetSignatureString() - Extended interfaces: - Added processVoteAndRelay method to the GOV interface (interfaces/node.h) - Added signSpecialTxPayload method to the wallet interface (interfaces/wallet.h) - Added comprehensive error handling with detailed feedback showing success/failure counts and specific error messages - Implemented wallet unlock handling that prompts for passphrase when needed - Updates vote counts in the governance list after voting ## How Has This Been Tested? - Tested on testnet with multiple masternodes in wallet - Verified voting capability detection correctly identifies wallets with/without voting keys - Confirmed votes are successfully submitted and accepted by the network - Tested wallet unlock flow with encrypted wallets - Verified testnet-specific signing works correctly - Confirmed vote counts update in the governance list after voting Testing environment: macOS, testnet, wallet with 3 masternode voting keys https://github.com/user-attachments/assets/de777bf7-2e05-4751-9e56-98e273703e66 ## Breaking Changes None - this PR only adds new functionality to the GUI without modifying existing behavior. ## Checklist: - [x] I have performed a self-review of my own code - [x] 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 (@thephez) - [x] I have assigned this pull request to a milestone (for repository code-owners and collaborators only) ACKs for top commit: UdjinM6: light ACK cf4e9e6 Tree-SHA512: aec92043e2432f66d071dccf91d127b91728d35e84ad1ca9fe88c1e15b5c2545a6730108833e7f19f2ef69ac5fdaf4d08288ce9ea0051d123f5a07f2c5f1c91c
Issue being fixed or feature implemented
What was done?
This PR adds complete governance voting functionality to the Qt wallet interface:
How Has This Been Tested?
Testing environment: macOS, testnet, wallet with 3 masternode voting keys
Screen.Recording.2025-05-26.at.13.51.49.mov
Breaking Changes
None - this PR only adds new functionality to the GUI without modifying existing behavior.
Checklist: