Governance
Overview
The PoA module integrates with Cosmos SDK governance to restrict participation to authorized validators only. Unlike standard governance that uses bonded tokens for voting weight, PoA governance uses validator power as the basis for voting.Validator-Only Governance
The PoA module restricts governance participation to authorized validators only through governance hooks. Governance Hooks (x/poa/keeper/hooks.go)
The module implements govtypes.GovHooks:
- AfterProposalSubmission: Only authorized validators can submit proposals
- AfterProposalDeposit: Only authorized validators can deposit on proposals
- AfterProposalVote: Only authorized validators can vote
- Registered in PoA module
- Power > 0
- Has valid operator address
- If non-validator attempts governance action → transaction fails
- If validator has power = 0 → transaction fails
- Error: “voter X is not an active PoA validator”
x/poa/keeper/governance.go:92
Voting Power
Custom Vote Tallying (x/poa/keeper/governance.go:18). An example of the wiring can be found in the SimApp.
Standard governance uses staked tokens as voting weight. PoA governance uses validator power:
- Vote Collection: System iterates all votes on a proposal
- Validator Check: For each vote, verify voter is active PoA validator
- Weight Calculation: Use validator’s power as voting weight
- Weighted Options: Supports split votes, exactly like x/staking in traditional POS governance (e.g., 70% Yes, 30% Abstain)
- Tally Results: Sum weighted votes by option
Vote Tallying Algorithm
Voting Power Formula: Where:- = voting power of validator
- = validator power (consensus weight)
- = vote weight from validator for option
- = weight assigned to option by validator (where )
- = total votes for option
- Sum over all validators who voted
Example
Validator A: , votes 100% YesProposal Lifecycle
1. Proposal Submission
MsgSubmitProposal (standard x/gov module) When a proposal is submitted:- Standard governance validates the proposal content
AfterProposalSubmissionhook is called- PoA module checks if proposer is authorized validator:
- Look up proposer by operator address
- Verify validator exists and has
- If not active, reject with error
- If valid, proposal enters deposit period
2. Deposit Period
MsgDeposit (standard x/gov module) When a deposit is made:- Standard governance processes the deposit
AfterProposalDeposithook is called- PoA module checks if depositor is authorized validator
- If deposit threshold reached, proposal moves to voting period
3. Voting Period
MsgVote or MsgVoteWeighted (standard x/gov module) When a vote is cast:- Standard governance records the vote
AfterProposalVotehook is called- PoA module validates voter is authorized validator
- If invalid, transaction fails
Yes: Support the proposalNo: Oppose the proposalNoWithVeto: Oppose and veto (can burn deposits if threshold met)Abstain: Participate in quorum without taking a position
4. Vote Tallying
At the end of the voting period, the custom tally function is called: NewPoACalculateVoteResultsAndVotingPowerFn (x/poa/keeper/governance.go:18)
- Iterate all votes on the proposal
- For each vote, look up the validator by voter address
- If validator is not active (), skip the vote
- Otherwise, use validator power as voting weight
- For weighted votes, distribute power across options
- Sum all weighted votes by option
- Apply standard governance thresholds:
- Quorum: Minimum participation percentage
- Threshold: Minimum “Yes” percentage to pass
- Veto: Maximum “NoWithVeto” percentage before rejection
Implementation Details
Governance Hooks
Location:x/poa/keeper/hooks.go
The module implements the govtypes.GovHooks interface:
- Extracts the operator address from the context
- Looks up the validator by operator address
- Checks if validator exists and has power > 0
- Returns error if validation fails
Custom Tally Function
Location:x/poa/keeper/governance.go:18
The tally function replaces the standard governance tally:
Governance Parameters
The standard governance module parameters still apply:- MinDeposit: Minimum tokens required to enter voting period
- MaxDepositPeriod: Time limit for reaching minimum deposit
- VotingPeriod: Duration of the voting period
- Quorum: Minimum participation rate (fraction of total power)
- Threshold: Minimum “Yes” rate to pass (fraction of non-abstain votes)
- VetoThreshold: Maximum “NoWithVeto” rate before rejection
Security Considerations
-
Validator Exclusivity:
- Only authorized validators (power > 0) can participate
- Prevents sybil attacks through unauthorized validator spam
- Ensures governance represents actual consensus participants
-
Power-Based Voting:
- Voting weight tied to consensus power
- Admin controls power distribution, thus controls governance indirectly
-
Admin Governance Control:
- Admin can change validator power at any time
- Admin can effectively control governance by adjusting power
- Consider multi-sig admin or governance-controlled admin changes
-
Proposal Spam Prevention:
- Restricting submissions to authorized validators reduces spam
- Deposit requirements still apply
- Validators have reputational stake in proposal quality
Comparison to Standard Governance
| Aspect | Standard Cosmos Governance | PoA Governance |
|---|---|---|
| Who can vote | Token holders (delegators + validators) | Authorized validators only |
| Voting weight | Bonded tokens | Validator power |
| Who can propose | Anyone with min deposit | Authorized validators only |
| Who can deposit | Anyone | Authorized validators only |
| Vote tallying | Sum of bonded tokens | Sum of validator power |
| Quorum calculation | % of bonded tokens | % of total validator power |
| Admin control | No direct control | Admin controls power → controls votes |
Example Governance Flow
Scenario: Validator A wants to propose a parameter change-
Submit Proposal:
- Validator A (power = 40) submits
MsgSubmitProposal - Hook verifies A is authorized validator
- Proposal enters deposit period
- Validator A (power = 40) submits
-
Reach Deposit:
- Validator B (power = 30) deposits
- Validator C (power = 30) deposits
- Deposit threshold reached → voting period starts
-
Voting:
- Validator A: 100% Yes (40 power → 40 Yes votes)
- Validator B: 60% Yes, 40% No (30 power → 18 Yes, 12 No)
- Validator C: 100% Abstain (30 power → 30 Abstain)
- Total power: 100 (all authorized validators)
-
Tally:
- Total voting power: 100 (all voted)
- Quorum: 100/100 = 100% ✓ (assuming 33% quorum)
- Results: 58 Yes, 12 No, 30 Abstain (out of 70 non-abstain)
- Threshold: 58/70 = 82.9% Yes ✓ (assuming 50% threshold)
- Proposal passes