cosmos-sdk/docs/spec/governance/transactions.md

195 lines
5.8 KiB
Markdown
Raw Normal View History

2018-02-26 07:35:09 -08:00
# Implementation (2/2)
## Transactions
### Proposal Submission
Proposals can be submitted by any Atom holder via a `TxGovSubmitProposal`
transaction.
```go
type TxGovSubmitProposal struct {
Title string // Title of the proposal
Description string // Description of the proposal
Type ProposalType // Type of proposal
2018-06-04 08:20:07 -07:00
InitialDeposit sdk.Coins // Initial deposit paid by sender. Must be strictly positive.
2018-02-26 07:35:09 -08:00
}
```
**State modifications:**
* Generate new `proposalID`
* Create new `Proposal`
* Initialise `Proposals` attributes
* Decrease balance of sender by `InitialDeposit`
* If `MinDeposit` is reached:
2018-06-04 08:20:07 -07:00
* Push `proposalID` in `ProposalProcessingQueue`
2018-02-26 07:35:09 -08:00
A `TxGovSubmitProposal` transaction can be handled according to the following
pseudocode.
```go
// PSEUDOCODE //
// Check if TxGovSubmitProposal is valid. If it is, create proposal //
upon receiving txGovSubmitProposal from sender do
2018-06-04 08:20:07 -07:00
if !correctlyFormatted(txGovSubmitProposal)
2018-02-26 07:35:09 -08:00
// check if proposal is correctly formatted. Includes fee payment.
throw
initialDeposit = txGovSubmitProposal.InitialDeposit
2018-06-04 08:20:07 -07:00
if (initialDeposit.Atoms <= 0) OR (sender.AtomBalance < initialDeposit.Atoms)
// InitialDeposit is negative or null OR sender has insufficient funds
throw
2018-06-04 08:20:07 -07:00
sender.AtomBalance -= initialDeposit.Atoms
proposalID = generate new proposalID
proposal = NewProposal()
proposal.Title = txGovSubmitProposal.Title
proposal.Description = txGovSubmitProposal.Description
proposal.Type = txGovSubmitProposal.Type
proposal.TotalDeposit = initialDeposit
proposal.SubmitBlock = CurrentBlock
proposal.Deposits.append({initialDeposit, sender})
proposal.Submitter = sender
2018-06-04 08:20:07 -07:00
proposal.YesVotes = 0
proposal.NoVotes = 0
proposal.NoWithVetoVotes = 0
proposal.AbstainVotes = 0
activeProcedure = load(params, 'ActiveProcedure')
2018-06-04 08:20:07 -07:00
if (initialDeposit < activeProcedure.MinDeposit)
// MinDeposit is not reached
2018-02-26 07:35:09 -08:00
2018-06-04 08:20:07 -07:00
proposal.CurrentStatus = ProposalStatusOpen
2018-02-26 07:35:09 -08:00
else
// MinDeposit is reached
2018-06-04 08:20:07 -07:00
proposal.CurrentStatus = ProposalStatusActive
proposal.VotingStartBlock = CurrentBlock
ProposalProcessingQueue.push(proposalID)
2018-02-26 07:35:09 -08:00
2018-06-05 07:43:56 -07:00
store(Proposals, <proposalID|'proposal'>, proposal) // Store proposal in Proposals mapping
return proposalID
2018-02-26 07:35:09 -08:00
```
### Deposit
Once a proposal is submitted, if
`Proposal.TotalDeposit < ActiveProcedure.MinDeposit`, Atom holders can send
2018-02-26 07:35:09 -08:00
`TxGovDeposit` transactions to increase the proposal's deposit.
```go
type TxGovDeposit struct {
2018-06-04 08:20:07 -07:00
ProposalID int64 // ID of the proposal
Deposit sdk.Coins // Number of Atoms to add to the proposal's deposit
2018-02-26 07:35:09 -08:00
}
```
**State modifications:**
* Decrease balance of sender by `deposit`
* Add `deposit` of sender in `proposal.Deposits`
* Increase `proposal.TotalDeposit` by sender's `deposit`
2018-02-26 07:35:09 -08:00
* If `MinDeposit` is reached:
* Push `proposalID` in `ProposalProcessingQueueEnd`
A `TxGovDeposit` transaction has to go through a number of checks to be valid.
These checks are outlined in the following pseudocode.
```go
// PSEUDOCODE //
// Check if TxGovDeposit is valid. If it is, increase deposit and check if MinDeposit is reached
upon receiving txGovDeposit from sender do
// check if proposal is correctly formatted. Includes fee payment.
2018-06-04 08:20:07 -07:00
if !correctlyFormatted(txGovDeposit)
2018-02-26 07:35:09 -08:00
throw
2018-06-05 07:43:56 -07:00
proposal = load(Proposals, <txGovDeposit.ProposalID|'proposal'>) // proposal is a const key, proposalID is variable
2018-02-26 07:35:09 -08:00
2018-06-04 08:20:07 -07:00
if (proposal == nil)
// There is no proposal for this proposalID
throw
2018-06-04 08:20:07 -07:00
activeProcedure = load(params, 'ActiveProcedure')
2018-06-05 07:43:56 -07:00
if (txGovDeposit.Deposit.Atoms <= 0) OR (sender.AtomBalance < txGovDeposit.Deposit.Atoms) OR (proposal.CurrentStatus != ProposalStatusOpen)
2018-06-04 08:20:07 -07:00
// deposit is negative or null
// OR sender has insufficient funds
2018-06-05 07:43:56 -07:00
// OR proposal is not open for deposit anymore
2018-06-04 08:20:07 -07:00
throw
2018-06-05 07:43:56 -07:00
if (CurrentBlock >= proposal.SubmitBlock + activeProcedure.MaxDepositPeriod)
proposal.CurrentStatus = ProposalStatusClosed
2018-06-05 07:43:56 -07:00
else
// sender can deposit
sender.AtomBalance -= txGovDeposit.Deposit.Atoms
proposal.Deposits.append({txGovVote.Deposit, sender})
proposal.TotalDeposit.Plus(txGovDeposit.Deposit)
if (proposal.TotalDeposit >= activeProcedure.MinDeposit)
// MinDeposit is reached, vote opens
proposal.VotingStartBlock = CurrentBlock
proposal.CurrentStatus = ProposalStatusActive
ProposalProcessingQueue.push(txGovDeposit.ProposalID)
store(Proposals, <txGovVote.ProposalID|'proposal'>, proposal)
2018-02-26 07:35:09 -08:00
```
### Vote
Once `ActiveProcedure.MinDeposit` is reached, voting period starts. From there,
bonded Atom holders are able to send `TxGovVote` transactions to cast their
vote on the proposal.
```go
type TxGovVote struct {
2018-06-05 07:43:56 -07:00
ProposalID int64 // proposalID of the proposal
2018-06-04 08:20:07 -07:00
Vote byte // option from OptionSet chosen by the voter
2018-02-26 07:35:09 -08:00
}
```
**State modifications:**
2018-06-04 08:20:07 -07:00
* Record `Vote` of sender
*Note: Gas cost for this message has to take into account the future tallying of the vote in EndBlocker*
2018-02-26 07:35:09 -08:00
Next is a pseudocode proposal of the way `TxGovVote` transactions are
2018-02-26 07:35:09 -08:00
handled:
```go
// PSEUDOCODE //
// Check if TxGovVote is valid. If it is, count vote//
upon receiving txGovVote from sender do
// check if proposal is correctly formatted. Includes fee payment.
2018-06-04 08:20:07 -07:00
if !correctlyFormatted(txGovDeposit)
2018-02-26 07:35:09 -08:00
throw
2018-06-05 07:43:56 -07:00
proposal = load(Proposals, <txGovDeposit.ProposalID|'proposal'>)
2018-02-26 07:35:09 -08:00
2018-06-04 08:20:07 -07:00
if (proposal == nil)
// There is no proposal for this proposalID
throw
2018-02-26 07:35:09 -08:00
2018-06-05 07:43:56 -07:00
if (proposal.CurrentStatus == ProposalStatusActive)
2018-02-26 07:35:09 -08:00
2018-06-05 07:43:56 -07:00
// Sender can vote
2018-02-26 07:35:09 -08:00
2018-06-05 07:43:56 -07:00
store(Governance, <txGovVote.ProposalID|'addresses'|sender>, txGovVote.Vote) // Voters can vote multiple times. Re-voting overrides previous vote. This is ok because tallying is done once at the end.
2018-02-26 07:35:09 -08:00
```