github.com/Finschia/finschia-sdk@v0.48.1/x/gov/spec/02_state.md (about)

     1  <!--
     2  order: 2
     3  -->
     4  
     5  # State
     6  
     7  ## Parameters and base types
     8  
     9  `Parameters` define the rules according to which votes are run. There can only
    10  be one active parameter set at any given time. If governance wants to change a
    11  parameter set, either to modify a value or add/remove a parameter field, a new
    12  parameter set has to be created and the previous one rendered inactive.
    13  
    14  ### DepositParams
    15  
    16  +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/gov.proto#L127-L145
    17  
    18  ### VotingParams
    19  
    20  +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/gov.proto#L147-L156
    21  
    22  ### TallyParams
    23  
    24  +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/gov.proto#L158-L183
    25  
    26  Parameters are stored in a global `GlobalParams` KVStore.
    27  
    28  Additionally, we introduce some basic types:
    29  
    30  ```go
    31  type Vote byte
    32  
    33  const (
    34      VoteYes         = 0x1
    35      VoteNo          = 0x2
    36      VoteNoWithVeto  = 0x3
    37      VoteAbstain     = 0x4
    38  )
    39  
    40  type ProposalType  string
    41  
    42  const (
    43      ProposalTypePlainText       = "Text"
    44      ProposalTypeSoftwareUpgrade = "SoftwareUpgrade"
    45  )
    46  
    47  type ProposalStatus byte
    48  
    49  
    50  const (
    51  	StatusNil           ProposalStatus = 0x00
    52      StatusDepositPeriod ProposalStatus = 0x01  // Proposal is submitted. Participants can deposit on it but not vote
    53      StatusVotingPeriod  ProposalStatus = 0x02  // MinDeposit is reached, participants can vote
    54      StatusPassed        ProposalStatus = 0x03  // Proposal passed and successfully executed
    55      StatusRejected      ProposalStatus = 0x04  // Proposal has been rejected
    56      StatusFailed        ProposalStatus = 0x05  // Proposal passed but failed execution
    57  )
    58  ```
    59  
    60  ## Deposit
    61  
    62  +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/gov.proto#L43-L53
    63  
    64  ## ValidatorGovInfo
    65  
    66  This type is used in a temp map when tallying
    67  
    68  ```go
    69    type ValidatorGovInfo struct {
    70      Minus     sdk.Dec
    71      Vote      Vote
    72    }
    73  ```
    74  
    75  ## Proposals
    76  
    77  `Proposal` objects are used to account votes and generally track the proposal's state. They contain `Content` which denotes
    78  what this proposal is about, and other fields, which are the mutable state of
    79  the governance process.
    80  
    81  +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/gov.proto#L55-L77
    82  
    83  ```go
    84  type Content interface {
    85  	GetTitle() string
    86  	GetDescription() string
    87  	ProposalRoute() string
    88  	ProposalType() string
    89  	ValidateBasic() sdk.Error
    90  	String() string
    91  }
    92  ```
    93  
    94  The `Content` on a proposal is an interface which contains the information about
    95  the `Proposal` such as the tile, description, and any notable changes. Also, this
    96  `Content` type can by implemented by any module. The `Content`'s `ProposalRoute`
    97  returns a string which must be used to route the `Content`'s `Handler` in the
    98  governance keeper. This allows the governance keeper to execute proposal logic
    99  implemented by any module. If a proposal passes, the handler is executed. Only
   100  if the handler is successful does the state get persisted and the proposal finally
   101  passes. Otherwise, the proposal is rejected.
   102  
   103  ```go
   104  type Handler func(ctx sdk.Context, content Content) sdk.Error
   105  ```
   106  
   107  The `Handler` is responsible for actually executing the proposal and processing
   108  any state changes specified by the proposal. It is executed only if a proposal
   109  passes during `EndBlock`.
   110  
   111  We also mention a method to update the tally for a given proposal:
   112  
   113  ```go
   114    func (proposal Proposal) updateTally(vote byte, amount sdk.Dec)
   115  ```
   116  
   117  ## Stores
   118  
   119  _Stores are KVStores in the multi-store. The key to find the store is the first
   120  parameter in the list_`
   121  
   122  We will use one KVStore `Governance` to store two mappings:
   123  
   124  - A mapping from `proposalID|'proposal'` to `Proposal`.
   125  - A mapping from `proposalID|'addresses'|address` to `Vote`. This mapping allows
   126    us to query all addresses that voted on the proposal along with their vote by
   127    doing a range query on `proposalID:addresses`.
   128  
   129  For pseudocode purposes, here are the two function we will use to read or write in stores:
   130  
   131  - `load(StoreKey, Key)`: Retrieve item stored at key `Key` in store found at key `StoreKey` in the multistore
   132  - `store(StoreKey, Key, value)`: Write value `Value` at key `Key` in store found at key `StoreKey` in the multistore
   133  
   134  ## Proposal Processing Queue
   135  
   136  **Store:**
   137  
   138  - `ProposalProcessingQueue`: A queue `queue[proposalID]` containing all the
   139    `ProposalIDs` of proposals that reached `MinDeposit`. During each `EndBlock`,
   140    all the proposals that have reached the end of their voting period are processed.
   141    To process a finished proposal, the application tallies the votes, computes the
   142    votes of each validator and checks if every validator in the validator set has
   143    voted. If the proposal is accepted, deposits are refunded. Finally, the proposal
   144    content `Handler` is executed.
   145  
   146  And the pseudocode for the `ProposalProcessingQueue`:
   147  
   148  ```go
   149    in EndBlock do
   150  
   151      for finishedProposalID in GetAllFinishedProposalIDs(block.Time)
   152        proposal = load(Governance, <proposalID|'proposal'>) // proposal is a const key
   153  
   154        validators = Keeper.getAllValidators()
   155        tmpValMap := map(sdk.AccAddress)ValidatorGovInfo
   156  
   157        // Initiate mapping at 0. This is the amount of shares of the validator's vote that will be overridden by their delegator's votes
   158        for each validator in validators
   159          tmpValMap(validator.OperatorAddr).Minus = 0
   160  
   161        // Tally
   162        voterIterator = rangeQuery(Governance, <proposalID|'addresses'>) //return all the addresses that voted on the proposal
   163        for each (voterAddress, vote) in voterIterator
   164          delegations = stakingKeeper.getDelegations(voterAddress) // get all delegations for current voter
   165  
   166          for each delegation in delegations
   167            // make sure delegation.Shares does NOT include shares being unbonded
   168            tmpValMap(delegation.ValidatorAddr).Minus += delegation.Shares
   169            proposal.updateTally(vote, delegation.Shares)
   170  
   171          _, isVal = stakingKeeper.getValidator(voterAddress)
   172          if (isVal)
   173            tmpValMap(voterAddress).Vote = vote
   174  
   175        tallyingParam = load(GlobalParams, 'TallyingParam')
   176  
   177        // Update tally if validator voted they voted
   178        for each validator in validators
   179          if tmpValMap(validator).HasVoted
   180            proposal.updateTally(tmpValMap(validator).Vote, (validator.TotalShares - tmpValMap(validator).Minus))
   181  
   182  
   183  
   184        // Check if proposal is accepted or rejected
   185        totalNonAbstain := proposal.YesVotes + proposal.NoVotes + proposal.NoWithVetoVotes
   186        if (proposal.Votes.YesVotes/totalNonAbstain > tallyingParam.Threshold AND proposal.Votes.NoWithVetoVotes/totalNonAbstain  < tallyingParam.Veto)
   187          //  proposal was accepted at the end of the voting period
   188          //  refund deposits (non-voters already punished)
   189          for each (amount, depositor) in proposal.Deposits
   190            depositor.AtomBalance += amount
   191  
   192          stateWriter, err := proposal.Handler()
   193          if err != nil
   194              // proposal passed but failed during state execution
   195              proposal.CurrentStatus = ProposalStatusFailed
   196           else
   197              // proposal pass and state is persisted
   198              proposal.CurrentStatus = ProposalStatusAccepted
   199              stateWriter.save()
   200        else
   201          // proposal was rejected
   202          proposal.CurrentStatus = ProposalStatusRejected
   203  
   204        store(Governance, <proposalID|'proposal'>, proposal)
   205  ```