Switch gov proposal-queues to use iterators (#2638)

* switched gov proposals queue to use iterators
* update gov spec
* update proposal.Equal
* Amino api change
* switched proposalID to uint64
* renamed Gov Procedures to Params
* s/ActiveProposalQueueProposalKey/KeyActiveProposalQueueProposal/g
* numLatestProposals -> Limit
* fixed staking invariant breakage because of gov deposits
* Send deposits to DepositedCoinsAccAddr or BurnedDepositCoinsAccAddr
This commit is contained in:
Sunny Aggarwal 2018-11-06 23:33:18 -08:00 committed by Jae Kwon
parent 10e8e0312e
commit 1d3a04a61c
28 changed files with 488 additions and 519 deletions

8
Gopkg.lock generated
View File

@ -165,13 +165,12 @@
version = "v1.2.0"
[[projects]]
digest = "1:c0d19ab64b32ce9fe5cf4ddceba78d5bc9807f0016db6b1183599da3dcc24d10"
digest = "1:ea40c24cdbacd054a6ae9de03e62c5f252479b96c716375aace5c120d68647c8"
name = "github.com/hashicorp/hcl"
packages = [
".",
"hcl/ast",
"hcl/parser",
"hcl/printer",
"hcl/scanner",
"hcl/strconv",
"hcl/token",
@ -435,7 +434,7 @@
version = "v0.11.1"
[[projects]]
digest = "1:92d7d1678577fd1a6f3348168cef87880bbc710ef5f4e9a1216f45c56567d734"
digest = "1:395820b381043b9d2204e181ddf0f9147397c4a7b8f5dc3162de4cfcddf4589a"
name = "github.com/tendermint/tendermint"
packages = [
"abci/client",
@ -501,7 +500,8 @@
"version",
]
pruneopts = "UT"
revision = "ebee4377b15f2958b08994485375dd2ee8a649ac"
revision = "03e42d2e3866f01a00625f608e3bbfaeb30690de"
version = "v0.26.1-rc0"
[[projects]]
digest = "1:7886f86064faff6f8d08a3eb0e8c773648ff5a2e27730831e2bfbf07467f6666"

View File

@ -36,7 +36,7 @@
[[override]]
name = "github.com/tendermint/tendermint"
revision = "ebee4377b15f2958b08994485375dd2ee8a649ac" # TODO replace w/ 0.26.1
version = "v0.26.1-rc0" # TODO replace w/ 0.26.1
## deps without releases:
@ -84,4 +84,3 @@
[prune]
go-tests = true
unused-packages = true

View File

@ -40,6 +40,7 @@ IMPROVEMENTS
* Gaia CLI (`gaiacli`)
* Gaia
- #2637 [x/gov] Switched inactive and active proposal queues to an iterator based queue
* SDK
- \#2573 [x/distribution] add accum invariance

View File

@ -628,8 +628,8 @@ func TestSubmitProposal(t *testing.T) {
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
var proposalID int64
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID)
var proposalID uint64
cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID)
// query proposal
proposal := getProposal(t, port, proposalID)
@ -650,8 +650,8 @@ func TestDeposit(t *testing.T) {
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
var proposalID int64
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID)
var proposalID uint64
cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID)
// query proposal
proposal := getProposal(t, port, proposalID)
@ -684,8 +684,8 @@ func TestVote(t *testing.T) {
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
var proposalID int64
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID)
var proposalID uint64
cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID)
// query proposal
proposal := getProposal(t, port, proposalID)
@ -732,18 +732,18 @@ func TestProposalsQuery(t *testing.T) {
// Addr1 proposes (and deposits) proposals #1 and #2
resultTx := doSubmitProposal(t, port, seeds[0], names[0], passwords[0], addrs[0], 5)
var proposalID1 int64
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID1)
var proposalID1 uint64
cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID1)
tests.WaitForHeight(resultTx.Height+1, port)
resultTx = doSubmitProposal(t, port, seeds[0], names[0], passwords[0], addrs[0], 5)
var proposalID2 int64
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID2)
var proposalID2 uint64
cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID2)
tests.WaitForHeight(resultTx.Height+1, port)
// Addr2 proposes (and deposits) proposals #3
resultTx = doSubmitProposal(t, port, seeds[1], names[1], passwords[1], addrs[1], 5)
var proposalID3 int64
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID3)
var proposalID3 uint64
cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID3)
tests.WaitForHeight(resultTx.Height+1, port)
// Addr2 deposits on proposals #2 & #3
@ -1230,7 +1230,7 @@ func getValidatorRedelegations(t *testing.T, port string, validatorAddr sdk.ValA
// ============= Governance Module ================
func getProposal(t *testing.T, port string, proposalID int64) gov.Proposal {
func getProposal(t *testing.T, port string, proposalID uint64) gov.Proposal {
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d", proposalID), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var proposal gov.Proposal
@ -1239,7 +1239,7 @@ func getProposal(t *testing.T, port string, proposalID int64) gov.Proposal {
return proposal
}
func getDeposits(t *testing.T, port string, proposalID int64) []gov.Deposit {
func getDeposits(t *testing.T, port string, proposalID uint64) []gov.Deposit {
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/deposits", proposalID), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var deposits []gov.Deposit
@ -1248,7 +1248,7 @@ func getDeposits(t *testing.T, port string, proposalID int64) []gov.Deposit {
return deposits
}
func getDeposit(t *testing.T, port string, proposalID int64, depositerAddr sdk.AccAddress) gov.Deposit {
func getDeposit(t *testing.T, port string, proposalID uint64, depositerAddr sdk.AccAddress) gov.Deposit {
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/deposits/%s", proposalID, depositerAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var deposit gov.Deposit
@ -1257,7 +1257,7 @@ func getDeposit(t *testing.T, port string, proposalID int64, depositerAddr sdk.A
return deposit
}
func getVote(t *testing.T, port string, proposalID int64, voterAddr sdk.AccAddress) gov.Vote {
func getVote(t *testing.T, port string, proposalID uint64, voterAddr sdk.AccAddress) gov.Vote {
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/votes/%s", proposalID, voterAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var vote gov.Vote
@ -1266,7 +1266,7 @@ func getVote(t *testing.T, port string, proposalID int64, voterAddr sdk.AccAddre
return vote
}
func getVotes(t *testing.T, port string, proposalID int64) []gov.Vote {
func getVotes(t *testing.T, port string, proposalID uint64) []gov.Vote {
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/votes", proposalID), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var votes []gov.Vote
@ -1358,7 +1358,7 @@ func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerA
return results
}
func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID int64, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) {
func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID uint64, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) {
acc := getAccount(t, port, proposerAddr)
accnum := acc.GetAccountNumber()
@ -1388,7 +1388,7 @@ func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk
return results
}
func doVote(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID int64) (resultTx ctypes.ResultBroadcastTxCommit) {
func doVote(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID uint64) (resultTx ctypes.ResultBroadcastTxCommit) {
// get the account to get the sequence
acc := getAccount(t, port, proposerAddr)
accnum := acc.GetAccountNumber()

View File

@ -65,6 +65,20 @@ func ParseInt64OrReturnBadRequest(w http.ResponseWriter, s string) (n int64, ok
return n, true
}
// ParseUint64OrReturnBadRequest converts s to a uint64 value.
func ParseUint64OrReturnBadRequest(w http.ResponseWriter, s string) (n uint64, ok bool) {
var err error
n, err = strconv.ParseUint(s, 10, 64)
if err != nil {
err := fmt.Errorf("'%s' is not a valid uint64", s)
WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return n, false
}
return n, true
}
// ParseFloat64OrReturnBadRequest converts s to a float64 value. It returns a
// default value, defaultIfEmpty, if the string is empty.
func ParseFloat64OrReturnBadRequest(w http.ResponseWriter, s string, defaultIfEmpty float64) (n float64, ok bool) {

View File

@ -70,15 +70,15 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
// Random genesis states
govGenesis := gov.GenesisState{
StartingProposalID: int64(r.Intn(100)),
DepositProcedure: gov.DepositProcedure{
StartingProposalID: uint64(r.Intn(100)),
DepositParams: gov.DepositParams{
MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", int64(r.Intn(1e3)))},
MaxDepositPeriod: time.Duration(r.Intn(2*172800)) * time.Second,
},
VotingProcedure: gov.VotingProcedure{
VotingParams: gov.VotingParams{
VotingPeriod: time.Duration(r.Intn(2*172800)) * time.Second,
},
TallyingProcedure: gov.TallyingProcedure{
TallyParams: gov.TallyParams{
Threshold: sdk.NewDecWithPrec(5, 1),
Veto: sdk.NewDecWithPrec(334, 3),
GovernancePenalty: sdk.NewDecWithPrec(1, 2),
@ -166,7 +166,7 @@ func testAndRunTxs(app *GaiaApp) []simulation.WeightedOperation {
{50, distrsim.SimulateMsgWithdrawDelegatorReward(app.accountKeeper, app.distrKeeper)},
{50, distrsim.SimulateMsgWithdrawValidatorRewardsAll(app.accountKeeper, app.distrKeeper)},
{5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, app.stakeKeeper)},
{100, govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper)},
{100, govsim.SimulateMsgDeposit(app.govKeeper)},
{100, stakesim.SimulateMsgCreateValidator(app.accountKeeper, app.stakeKeeper)},
{5, stakesim.SimulateMsgEditValidator(app.stakeKeeper)},
{100, stakesim.SimulateMsgDelegate(app.accountKeeper, app.stakeKeeper)},

View File

@ -5,13 +5,14 @@ package clitest
import (
"encoding/json"
"fmt"
"github.com/tendermint/tendermint/types"
"io/ioutil"
"os"
"path"
"path/filepath"
"testing"
"github.com/tendermint/tendermint/types"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
@ -348,7 +349,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
require.Equal(t, int64(45), fooAcc.GetCoins().AmountOf("steak").Int64())
proposal1 := executeGetProposal(t, fmt.Sprintf("gaiacli query proposal --proposal-id=1 --output=json %v", flags))
require.Equal(t, int64(1), proposal1.GetProposalID())
require.Equal(t, uint64(1), proposal1.GetProposalID())
require.Equal(t, gov.StatusDepositPeriod, proposal1.GetStatus())
proposalsQuery, _ = tests.ExecuteT(t, fmt.Sprintf("gaiacli query proposals %v", flags), "")
@ -391,7 +392,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
require.Equal(t, int64(35), fooAcc.GetCoins().AmountOf("steak").Int64())
proposal1 = executeGetProposal(t, fmt.Sprintf("gaiacli query proposal --proposal-id=1 --output=json %v", flags))
require.Equal(t, int64(1), proposal1.GetProposalID())
require.Equal(t, uint64(1), proposal1.GetProposalID())
require.Equal(t, gov.StatusVotingPeriod, proposal1.GetStatus())
voteStr := fmt.Sprintf("gaiacli tx vote %v", flags)
@ -413,12 +414,12 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
tests.WaitForNextNBlocksTM(2, port)
vote := executeGetVote(t, fmt.Sprintf("gaiacli query vote --proposal-id=1 --voter=%s --output=json %v", fooAddr, flags))
require.Equal(t, int64(1), vote.ProposalID)
require.Equal(t, uint64(1), vote.ProposalID)
require.Equal(t, gov.OptionYes, vote.Option)
votes := executeGetVotes(t, fmt.Sprintf("gaiacli query votes --proposal-id=1 --output=json %v", flags))
require.Len(t, votes, 1)
require.Equal(t, int64(1), votes[0].ProposalID)
require.Equal(t, uint64(1), votes[0].ProposalID)
require.Equal(t, gov.OptionYes, votes[0].Option)
proposalsQuery, _ = tests.ExecuteT(t, fmt.Sprintf("gaiacli query proposals --status=DepositPeriod %v", flags), "")
@ -438,7 +439,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
executeWrite(t, spStr, app.DefaultKeyPass)
tests.WaitForNextNBlocksTM(2, port)
proposalsQuery, _ = tests.ExecuteT(t, fmt.Sprintf("gaiacli query proposals --latest=1 %v", flags), "")
proposalsQuery, _ = tests.ExecuteT(t, fmt.Sprintf("gaiacli query proposals --limit=1 %v", flags), "")
require.Equal(t, " 2 - Apples", proposalsQuery)
}

View File

@ -96,10 +96,12 @@ type Proposal struct {
Type ProposalType // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal}
TotalDeposit sdk.Coins // Current deposit on this proposal. Initial value is set at InitialDeposit
Deposits []Deposit // List of deposits on the proposal
SubmitTime time.Time // Time of the block where TxGovSubmitProposal was included
Submitter sdk.Address // Address of the submitter
SubmitTime time.Time // Time of the block where TxGovSubmitProposal was included
DepositEndTime time.Time // Time that the DepositPeriod of a proposal would expire
Submitter sdk.AccAddress // Address of the submitter
VotingStartTime time.Time // Time of the block where MinDeposit was reached. time.Time{} if MinDeposit is not reached
VotingStartTime time.Time // Time of the block where MinDeposit was reached. time.Time{} if MinDeposit is not reached
VotingEndTime time.Time // Time of the block that the VotingPeriod for a proposal will end.
CurrentStatus ProposalStatus // Current status of the proposal
YesVotes sdk.Dec
@ -134,46 +136,26 @@ For pseudocode purposes, here are the two function we will use to read or write
**Store:**
* `ProposalProcessingQueue`: A queue `queue[proposalID]` containing all the
`ProposalIDs` of proposals that reached `MinDeposit`. Each round, the oldest
element of `ProposalProcessingQueue` is checked during `BeginBlock` to see if
`CurrentTime == VotingStartTime + activeProcedure.VotingPeriod`. If it is,
then the application tallies the votes, compute the votes of each validator and checks if every validator in the valdiator set have voted
and, if not, applies `GovernancePenalty`. If the proposal is accepted, deposits are refunded.
After that proposal is ejected from `ProposalProcessingQueue` and the next element of the queue is evaluated.
`ProposalIDs` of proposals that reached `MinDeposit`. Each `EndBlock`, all the proposals
that have reached the end of their voting period are processed.
To process a finished proposal, the application tallies the votes, compute the votes of
each validator and checks if every validator in the valdiator set have voted.
If the proposal is accepted, deposits are refunded.
And the pseudocode for the `ProposalProcessingQueue`:
```go
in EndBlock do
checkProposal() // First call of the recursive function
// Recursive function. First call in BeginBlock
func checkProposal()
proposalID = ProposalProcessingQueue.Peek()
if (proposalID == nil)
return
for finishedProposalID in GetAllFinishedProposalIDs(block.Time)
proposal = load(Governance, <proposalID|'proposal'>) // proposal is a const key
proposal = load(Governance, <proposalID|'proposal'>) // proposal is a const key
votingProcedure = load(GlobalParams, 'VotingProcedure')
validators = Keeper.getAllValidators()
tmpValMap := map(sdk.AccAddress)ValidatorGovInfo
if (CurrentTime == proposal.VotingStartTime + votingProcedure.VotingPeriod && proposal.CurrentStatus == ProposalStatusActive)
// End of voting period, tally
ProposalProcessingQueue.pop()
validators =
Keeper.getAllValidators()
tmpValMap := map(sdk.Address)ValidatorGovInfo
// Initiate mapping at 0. Validators that remain at 0 at the end of tally will be punished
// Initiate mapping at 0. This is the amount of shares of the validator's vote that will be overridden by their delegator's votes
for each validator in validators
tmpValMap(validator).Minus = 0
tmpValMap(validator.OperatorAddr).Minus = 0
// Tally
voterIterator = rangeQuery(Governance, <proposalID|'addresses'>) //return all the addresses that voted on the proposal
@ -212,5 +194,4 @@ And the pseudocode for the `ProposalProcessingQueue`:
proposal.CurrentStatus = ProposalStatusRejected
store(Governance, <proposalID|'proposal'>, proposal)
checkProposal()
```

View File

@ -45,6 +45,8 @@ upon receiving txGovSubmitProposal from sender do
if (txGovSubmitProposal.Type != ProposalTypePlainText) OR (txGovSubmitProposal.Type != ProposalTypeSoftwareUpgrade)
sender.AtomBalance -= initialDeposit.Atoms
depositProcedure = load(GlobalParams, 'DepositProcedure')
proposalID = generate new proposalID
proposal = NewProposal()
@ -53,27 +55,15 @@ upon receiving txGovSubmitProposal from sender do
proposal.Description = txGovSubmitProposal.Description
proposal.Type = txGovSubmitProposal.Type
proposal.TotalDeposit = initialDeposit
proposal.SubmitBlock = CurrentBlock
proposal.SubmitTime = <CurrentTime>
proposal.DepositEndTime = <CurrentTime>.Add(depositProcedure.MaxDepositPeriod)
proposal.Deposits.append({initialDeposit, sender})
proposal.Submitter = sender
proposal.YesVotes = 0
proposal.NoVotes = 0
proposal.NoWithVetoVotes = 0
proposal.AbstainVotes = 0
depositProcedure = load(GlobalParams, 'DepositProcedure')
if (initialDeposit < depositProcedure.MinDeposit)
// MinDeposit is not reached
proposal.CurrentStatus = ProposalStatusOpen
else
// MinDeposit is reached
proposal.CurrentStatus = ProposalStatusActive
proposal.VotingStartBlock = CurrentBlock
ProposalProcessingQueue.push(proposalID)
proposal.CurrentStatus = ProposalStatusOpen
store(Proposals, <proposalID|'proposal'>, proposal) // Store proposal in Proposals mapping
return proposalID

View File

@ -1,6 +1,7 @@
package types
import (
"encoding/binary"
"encoding/json"
"time"
@ -36,6 +37,13 @@ func MustSortJSON(toSortJSON []byte) []byte {
return js
}
// Uint64ToBigEndian - marshals uint64 to a bigendian byte slice so it can be sorted
func Uint64ToBigEndian(i uint64) []byte {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, i)
return b
}
// Slight modification of the RFC3339Nano but it right pads all zeros and drops the time zone info
const SortableTimeFormat = "2006-01-02T15:04:05.000000000"

View File

@ -21,17 +21,17 @@ import (
)
const (
flagProposalID = "proposal-id"
flagTitle = "title"
flagDescription = "description"
flagProposalType = "type"
flagDeposit = "deposit"
flagVoter = "voter"
flagOption = "option"
flagDepositer = "depositer"
flagStatus = "status"
flagLatestProposalIDs = "latest"
flagProposal = "proposal"
flagProposalID = "proposal-id"
flagTitle = "title"
flagDescription = "description"
flagProposalType = "type"
flagDeposit = "deposit"
flagVoter = "voter"
flagOption = "option"
flagDepositer = "depositer"
flagStatus = "status"
flagNumLimit = "limit"
flagProposal = "proposal"
)
type proposal struct {
@ -170,7 +170,7 @@ func GetCmdDeposit(cdc *codec.Codec) *cobra.Command {
return err
}
proposalID := viper.GetInt64(flagProposalID)
proposalID := uint64(viper.GetInt64(flagProposalID))
amount, err := sdk.ParseCoins(viper.GetString(flagDeposit))
if err != nil {
@ -215,7 +215,7 @@ func GetCmdVote(cdc *codec.Codec) *cobra.Command {
return err
}
proposalID := viper.GetInt64(flagProposalID)
proposalID := uint64(viper.GetInt64(flagProposalID))
option := viper.GetString(flagOption)
byteVoteOption, err := gov.VoteOptionFromString(client.NormalizeVoteOption(option))
@ -256,7 +256,7 @@ func GetCmdQueryProposal(queryRoute string, cdc *codec.Codec) *cobra.Command {
Short: "Query details of a single proposal",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := viper.GetInt64(flagProposalID)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryProposalParams{
ProposalID: proposalID,
@ -291,10 +291,10 @@ func GetCmdQueryProposals(queryRoute string, cdc *codec.Codec) *cobra.Command {
bechDepositerAddr := viper.GetString(flagDepositer)
bechVoterAddr := viper.GetString(flagVoter)
strProposalStatus := viper.GetString(flagStatus)
latestProposalsIDs := viper.GetInt64(flagLatestProposalIDs)
numLimit := uint64(viper.GetInt64(flagNumLimit))
params := gov.QueryProposalsParams{
NumLatestProposals: latestProposalsIDs,
Limit: numLimit,
}
if len(bechDepositerAddr) != 0 {
@ -352,7 +352,7 @@ func GetCmdQueryProposals(queryRoute string, cdc *codec.Codec) *cobra.Command {
},
}
cmd.Flags().String(flagLatestProposalIDs, "", "(optional) limit to latest [number] proposals. Defaults to all proposals")
cmd.Flags().String(flagNumLimit, "", "(optional) limit to latest [number] proposals. Defaults to all proposals")
cmd.Flags().String(flagDepositer, "", "(optional) filter by proposals deposited on by depositer")
cmd.Flags().String(flagVoter, "", "(optional) filter by proposals voted on by voted")
cmd.Flags().String(flagStatus, "", "(optional) filter proposals by proposal status, status: deposit_period/voting_period/passed/rejected")
@ -368,7 +368,7 @@ func GetCmdQueryVote(queryRoute string, cdc *codec.Codec) *cobra.Command {
Short: "Query details of a single vote",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := viper.GetInt64(flagProposalID)
proposalID := uint64(viper.GetInt64(flagProposalID))
voterAddr, err := sdk.AccAddressFromBech32(viper.GetString(flagVoter))
if err != nil {
@ -407,7 +407,7 @@ func GetCmdQueryVotes(queryRoute string, cdc *codec.Codec) *cobra.Command {
Short: "Query votes on a proposal",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := viper.GetInt64(flagProposalID)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryVotesParams{
ProposalID: proposalID,
@ -440,7 +440,7 @@ func GetCmdQueryDeposit(queryRoute string, cdc *codec.Codec) *cobra.Command {
Short: "Query details of a deposit",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := viper.GetInt64(flagProposalID)
proposalID := uint64(viper.GetInt64(flagProposalID))
depositerAddr, err := sdk.AccAddressFromBech32(viper.GetString(flagDepositer))
if err != nil {
@ -479,7 +479,7 @@ func GetCmdQueryDeposits(queryRoute string, cdc *codec.Codec) *cobra.Command {
Short: "Query deposits on a proposal",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := viper.GetInt64(flagProposalID)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryDepositsParams{
ProposalID: proposalID,
@ -511,7 +511,7 @@ func GetCmdQueryTally(queryRoute string, cdc *codec.Codec) *cobra.Command {
Short: "Get the tally of a proposal vote",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := viper.GetInt64(flagProposalID)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryTallyParams{
ProposalID: proposalID,

View File

@ -22,7 +22,7 @@ const (
RestDepositer = "depositer"
RestVoter = "voter"
RestProposalStatus = "status"
RestNumLatest = "latest"
RestNumLimit = "limit"
storeName = "gov"
)
@ -104,7 +104,7 @@ func depositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerF
return
}
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
if !ok {
return
}
@ -143,7 +143,7 @@ func voteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc
return
}
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
if !ok {
return
}
@ -188,7 +188,7 @@ func queryProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Ha
return
}
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
if !ok {
return
}
@ -218,7 +218,7 @@ func queryDepositsHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Ha
vars := mux.Vars(r)
strProposalID := vars[RestProposalID]
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
if !ok {
return
}
@ -255,7 +255,7 @@ func queryDepositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han
return
}
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
if !ok {
return
}
@ -319,7 +319,7 @@ func queryVoteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Handle
return
}
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
if !ok {
return
}
@ -386,7 +386,7 @@ func queryVotesOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext)
return
}
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
if !ok {
return
}
@ -416,7 +416,7 @@ func queryProposalsWithParameterFn(cdc *codec.Codec, cliCtx context.CLIContext)
bechVoterAddr := r.URL.Query().Get(RestVoter)
bechDepositerAddr := r.URL.Query().Get(RestDepositer)
strProposalStatus := r.URL.Query().Get(RestProposalStatus)
strNumLatest := r.URL.Query().Get(RestNumLatest)
strNumLimit := r.URL.Query().Get(RestNumLimit)
params := gov.QueryProposalsParams{}
@ -446,12 +446,12 @@ func queryProposalsWithParameterFn(cdc *codec.Codec, cliCtx context.CLIContext)
}
params.ProposalStatus = proposalStatus
}
if len(strNumLatest) != 0 {
numLatest, ok := utils.ParseInt64OrReturnBadRequest(w, strNumLatest)
if len(strNumLimit) != 0 {
numLimit, ok := utils.ParseUint64OrReturnBadRequest(w, strNumLimit)
if !ok {
return
}
params.NumLatestProposals = numLatest
params.Limit = numLimit
}
bz, err := cdc.MarshalJSON(params)
@ -484,7 +484,7 @@ func queryTallyOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext)
return
}
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
proposalID, ok := utils.ParseUint64OrReturnBadRequest(w, strProposalID)
if !ok {
return
}

View File

@ -11,7 +11,7 @@ import (
// Vote
type Vote struct {
Voter sdk.AccAddress `json:"voter"` // address of the voter
ProposalID int64 `json:"proposal_id"` // proposalID of the proposal
ProposalID uint64 `json:"proposal_id"` // proposalID of the proposal
Option VoteOption `json:"option"` // option from OptionSet chosen by the voter
}
@ -29,7 +29,7 @@ func (voteA Vote) Empty() bool {
// Deposit
type Deposit struct {
Depositer sdk.AccAddress `json:"depositer"` // Address of the depositer
ProposalID int64 `json:"proposal_id"` // proposalID of the proposal
ProposalID uint64 `json:"proposal_id"` // proposalID of the proposal
Amount sdk.Coins `json:"amount"` // Deposit amount
}

View File

@ -16,35 +16,40 @@ func TestTickExpiredDepositPeriod(t *testing.T) {
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
govHandler := NewHandler(keeper)
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
inactiveQueue := keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
res := govHandler(ctx, newProposalMsg)
require.True(t, res.IsOK())
EndBlocker(ctx, keeper)
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newHeader := ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
ctx = ctx.WithBlockHeader(newHeader)
EndBlocker(ctx, keeper)
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newHeader = ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod)
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositParams(ctx).MaxDepositPeriod)
ctx = ctx.WithBlockHeader(newHeader)
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
require.True(t, shouldPopInactiveProposalQueue(ctx, keeper))
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.True(t, inactiveQueue.Valid())
inactiveQueue.Close()
EndBlocker(ctx, keeper)
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
}
func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
@ -53,49 +58,54 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
govHandler := NewHandler(keeper)
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
inactiveQueue := keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
res := govHandler(ctx, newProposalMsg)
require.True(t, res.IsOK())
EndBlocker(ctx, keeper)
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newHeader := ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(2) * time.Second)
ctx = ctx.WithBlockHeader(newHeader)
EndBlocker(ctx, keeper)
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newProposalMsg2 := NewMsgSubmitProposal("Test2", "test2", ProposalTypeText, addrs[1], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
res = govHandler(ctx, newProposalMsg2)
require.True(t, res.IsOK())
newHeader = ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(time.Duration(-1) * time.Second)
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(time.Duration(-1) * time.Second)
ctx = ctx.WithBlockHeader(newHeader)
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
require.True(t, shouldPopInactiveProposalQueue(ctx, keeper))
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.True(t, inactiveQueue.Valid())
inactiveQueue.Close()
EndBlocker(ctx, keeper)
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newHeader = ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(5) * time.Second)
ctx = ctx.WithBlockHeader(newHeader)
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
require.True(t, shouldPopInactiveProposalQueue(ctx, keeper))
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.True(t, inactiveQueue.Valid())
inactiveQueue.Close()
EndBlocker(ctx, keeper)
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
}
func TestTickPassedDepositPeriod(t *testing.T) {
@ -104,45 +114,39 @@ func TestTickPassedDepositPeriod(t *testing.T) {
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
govHandler := NewHandler(keeper)
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
require.Nil(t, keeper.ActiveProposalQueuePeek(ctx))
require.False(t, shouldPopActiveProposalQueue(ctx, keeper))
inactiveQueue := keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
activeQueue := keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, activeQueue.Valid())
activeQueue.Close()
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
res := govHandler(ctx, newProposalMsg)
require.True(t, res.IsOK())
var proposalID int64
keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID)
var proposalID uint64
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(res.Data, &proposalID)
EndBlocker(ctx, keeper)
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newHeader := ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
ctx = ctx.WithBlockHeader(newHeader)
EndBlocker(ctx, keeper)
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newDepositMsg := NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin("steak", 5)})
res = govHandler(ctx, newDepositMsg)
require.True(t, res.IsOK())
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
require.True(t, shouldPopInactiveProposalQueue(ctx, keeper))
require.NotNil(t, keeper.ActiveProposalQueuePeek(ctx))
EndBlocker(ctx, keeper)
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
require.NotNil(t, keeper.ActiveProposalQueuePeek(ctx))
require.False(t, shouldPopActiveProposalQueue(ctx, keeper))
activeQueue = keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, activeQueue.Valid())
activeQueue.Close()
}
func TestTickPassedVotingPeriod(t *testing.T) {
@ -152,17 +156,19 @@ func TestTickPassedVotingPeriod(t *testing.T) {
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
govHandler := NewHandler(keeper)
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
require.Nil(t, keeper.ActiveProposalQueuePeek(ctx))
require.False(t, shouldPopActiveProposalQueue(ctx, keeper))
inactiveQueue := keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
activeQueue := keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, activeQueue.Valid())
activeQueue.Close()
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 5)})
res := govHandler(ctx, newProposalMsg)
require.True(t, res.IsOK())
var proposalID int64
keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID)
var proposalID uint64
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(res.Data, &proposalID)
newHeader := ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
@ -172,24 +178,27 @@ func TestTickPassedVotingPeriod(t *testing.T) {
res = govHandler(ctx, newDepositMsg)
require.True(t, res.IsOK())
EndBlocker(ctx, keeper)
newHeader = ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod)
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(keeper.GetVotingParams(ctx).VotingPeriod)
ctx = ctx.WithBlockHeader(newHeader)
require.True(t, shouldPopActiveProposalQueue(ctx, keeper))
inactiveQueue = keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
activeQueue = keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.True(t, activeQueue.Valid())
var activeProposalID uint64
keeper.cdc.UnmarshalBinaryLengthPrefixed(activeQueue.Value(), &activeProposalID)
require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, activeProposalID).GetStatus())
depositsIterator := keeper.GetDeposits(ctx, proposalID)
require.True(t, depositsIterator.Valid())
depositsIterator.Close()
require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus())
activeQueue.Close()
EndBlocker(ctx, keeper)
require.Nil(t, keeper.ActiveProposalQueuePeek(ctx))
depositsIterator = keeper.GetDeposits(ctx, proposalID)
require.False(t, depositsIterator.Valid())
depositsIterator.Close()
require.Equal(t, StatusRejected, keeper.GetProposal(ctx, proposalID).GetStatus())
require.True(t, keeper.GetProposal(ctx, proposalID).GetTallyResult().Equals(EmptyTallyResult()))
activeQueue = keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, activeQueue.Valid())
activeQueue.Close()
}

View File

@ -26,19 +26,19 @@ const (
//----------------------------------------
// Error constructors
func ErrUnknownProposal(codespace sdk.CodespaceType, proposalID int64) sdk.Error {
func ErrUnknownProposal(codespace sdk.CodespaceType, proposalID uint64) sdk.Error {
return sdk.NewError(codespace, CodeUnknownProposal, fmt.Sprintf("Unknown proposal with id %d", proposalID))
}
func ErrInactiveProposal(codespace sdk.CodespaceType, proposalID int64) sdk.Error {
func ErrInactiveProposal(codespace sdk.CodespaceType, proposalID uint64) sdk.Error {
return sdk.NewError(codespace, CodeInactiveProposal, fmt.Sprintf("Inactive proposal with id %d", proposalID))
}
func ErrAlreadyActiveProposal(codespace sdk.CodespaceType, proposalID int64) sdk.Error {
func ErrAlreadyActiveProposal(codespace sdk.CodespaceType, proposalID uint64) sdk.Error {
return sdk.NewError(codespace, CodeAlreadyActiveProposal, fmt.Sprintf("Proposal %d has been already active", proposalID))
}
func ErrAlreadyFinishedProposal(codespace sdk.CodespaceType, proposalID int64) sdk.Error {
func ErrAlreadyFinishedProposal(codespace sdk.CodespaceType, proposalID uint64) sdk.Error {
return sdk.NewError(codespace, CodeAlreadyFinishedProposal, fmt.Sprintf("Proposal %d has already passed its voting period", proposalID))
}

View File

@ -8,18 +8,18 @@ import (
// GenesisState - all staking state that must be provided at genesis
type GenesisState struct {
StartingProposalID int64 `json:"starting_proposalID"`
DepositProcedure DepositProcedure `json:"deposit_period"`
VotingProcedure VotingProcedure `json:"voting_period"`
TallyingProcedure TallyingProcedure `json:"tallying_procedure"`
StartingProposalID uint64 `json:"starting_proposalID"`
DepositParams DepositParams `json:"deposit_params"`
VotingParams VotingParams `json:"voting_params"`
TallyParams TallyParams `json:"tally_params"`
}
func NewGenesisState(startingProposalID int64, dp DepositProcedure, vp VotingProcedure, tp TallyingProcedure) GenesisState {
func NewGenesisState(startingProposalID uint64, dp DepositParams, vp VotingParams, tp TallyParams) GenesisState {
return GenesisState{
StartingProposalID: startingProposalID,
DepositProcedure: dp,
VotingProcedure: vp,
TallyingProcedure: tp,
DepositParams: dp,
VotingParams: vp,
TallyParams: tp,
}
}
@ -27,14 +27,14 @@ func NewGenesisState(startingProposalID int64, dp DepositProcedure, vp VotingPro
func DefaultGenesisState() GenesisState {
return GenesisState{
StartingProposalID: 1,
DepositProcedure: DepositProcedure{
DepositParams: DepositParams{
MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", 10)},
MaxDepositPeriod: time.Duration(172800) * time.Second,
},
VotingProcedure: VotingProcedure{
VotingParams: VotingParams{
VotingPeriod: time.Duration(172800) * time.Second,
},
TallyingProcedure: TallyingProcedure{
TallyParams: TallyParams{
Threshold: sdk.NewDecWithPrec(5, 1),
Veto: sdk.NewDecWithPrec(334, 3),
GovernancePenalty: sdk.NewDecWithPrec(1, 2),
@ -49,22 +49,22 @@ func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) {
// TODO: Handle this with #870
panic(err)
}
k.setDepositProcedure(ctx, data.DepositProcedure)
k.setVotingProcedure(ctx, data.VotingProcedure)
k.setTallyingProcedure(ctx, data.TallyingProcedure)
k.setDepositParams(ctx, data.DepositParams)
k.setVotingParams(ctx, data.VotingParams)
k.setTallyParams(ctx, data.TallyParams)
}
// WriteGenesis - output genesis parameters
func WriteGenesis(ctx sdk.Context, k Keeper) GenesisState {
startingProposalID, _ := k.getNewProposalID(ctx)
depositProcedure := k.GetDepositProcedure(ctx)
votingProcedure := k.GetVotingProcedure(ctx)
tallyingProcedure := k.GetTallyingProcedure(ctx)
depositParams := k.GetDepositParams(ctx)
votingParams := k.GetVotingParams(ctx)
tallyParams := k.GetTallyParams(ctx)
return GenesisState{
StartingProposalID: startingProposalID,
DepositProcedure: depositProcedure,
VotingProcedure: votingProcedure,
TallyingProcedure: tallyingProcedure,
DepositParams: depositParams,
VotingParams: votingParams,
TallyParams: tallyParams,
}
}

View File

@ -33,7 +33,7 @@ func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitPropos
return err.Result()
}
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(proposal.GetProposalID())
proposalIDBytes := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposal.GetProposalID())
resTags := sdk.NewTags(
tags.Action, tags.ActionSubmitProposal,
@ -102,40 +102,35 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
resTags = sdk.NewTags()
// Delete proposals that haven't met minDeposit
for shouldPopInactiveProposalQueue(ctx, keeper) {
inactiveProposal := keeper.InactiveProposalQueuePop(ctx)
if inactiveProposal.GetStatus() != StatusDepositPeriod {
continue
}
inactiveIterator := keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
for ; inactiveIterator.Valid(); inactiveIterator.Next() {
var proposalID uint64
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(inactiveIterator.Value(), &proposalID)
inactiveProposal := keeper.GetProposal(ctx, proposalID)
keeper.RefundDeposits(ctx, proposalID)
keeper.DeleteProposal(ctx, proposalID)
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(inactiveProposal.GetProposalID())
keeper.DeleteProposal(ctx, inactiveProposal)
resTags = resTags.AppendTag(tags.Action, tags.ActionProposalDropped)
resTags = resTags.AppendTag(tags.ProposalID, proposalIDBytes)
resTags = resTags.AppendTag(tags.ProposalID, []byte(string(proposalID)))
logger.Info(
fmt.Sprintf("proposal %d (%s) didn't meet minimum deposit of %v steak (had only %v steak); deleted",
fmt.Sprintf("proposal %d (%s) didn't meet minimum deposit of %s (had only %s); deleted",
inactiveProposal.GetProposalID(),
inactiveProposal.GetTitle(),
keeper.GetDepositProcedure(ctx).MinDeposit.AmountOf("steak"),
inactiveProposal.GetTotalDeposit().AmountOf("steak"),
keeper.GetDepositParams(ctx).MinDeposit,
inactiveProposal.GetTotalDeposit(),
),
)
}
inactiveIterator.Close()
// Check if earliest Active Proposal ended voting period yet
for shouldPopActiveProposalQueue(ctx, keeper) {
activeProposal := keeper.ActiveProposalQueuePop(ctx)
proposalStartTime := activeProposal.GetVotingStartTime()
votingPeriod := keeper.GetVotingProcedure(ctx).VotingPeriod
if ctx.BlockHeader().Time.Before(proposalStartTime.Add(votingPeriod)) {
continue
}
activeIterator := keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
for ; activeIterator.Valid(); activeIterator.Next() {
var proposalID uint64
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(activeIterator.Value(), &proposalID)
activeProposal := keeper.GetProposal(ctx, proposalID)
passes, tallyResults := tally(ctx, keeper, activeProposal)
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(activeProposal.GetProposalID())
var action []byte
if passes {
keeper.RefundDeposits(ctx, activeProposal.GetProposalID())
@ -149,37 +144,15 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
activeProposal.SetTallyResult(tallyResults)
keeper.SetProposal(ctx, activeProposal)
keeper.RemoveFromActiveProposalQueue(ctx, activeProposal.GetVotingEndTime(), activeProposal.GetProposalID())
logger.Info(fmt.Sprintf("proposal %d (%s) tallied; passed: %v",
activeProposal.GetProposalID(), activeProposal.GetTitle(), passes))
resTags = resTags.AppendTag(tags.Action, action)
resTags = resTags.AppendTag(tags.ProposalID, proposalIDBytes)
resTags = resTags.AppendTag(tags.ProposalID, []byte(string(proposalID)))
}
activeIterator.Close()
return resTags
}
func shouldPopInactiveProposalQueue(ctx sdk.Context, keeper Keeper) bool {
depositProcedure := keeper.GetDepositProcedure(ctx)
peekProposal := keeper.InactiveProposalQueuePeek(ctx)
if peekProposal == nil {
return false
} else if peekProposal.GetStatus() != StatusDepositPeriod {
return true
} else if !ctx.BlockHeader().Time.Before(peekProposal.GetSubmitTime().Add(depositProcedure.MaxDepositPeriod)) {
return true
}
return false
}
func shouldPopActiveProposalQueue(ctx sdk.Context, keeper Keeper) bool {
votingProcedure := keeper.GetVotingProcedure(ctx)
peekProposal := keeper.ActiveProposalQueuePeek(ctx)
if peekProposal == nil {
return false
} else if !ctx.BlockHeader().Time.Before(peekProposal.GetVotingStartTime().Add(votingProcedure.VotingPeriod)) {
return true
}
return false
}

View File

@ -1,10 +1,14 @@
package gov
import (
"time"
codec "github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/tendermint/tendermint/crypto"
)
// Parameter store default namestore
@ -14,17 +18,20 @@ const (
// Parameter store key
var (
ParamStoreKeyDepositProcedure = []byte("depositprocedure")
ParamStoreKeyVotingProcedure = []byte("votingprocedure")
ParamStoreKeyTallyingProcedure = []byte("tallyingprocedure")
ParamStoreKeyDepositParams = []byte("depositparams")
ParamStoreKeyVotingParams = []byte("votingparams")
ParamStoreKeyTallyParams = []byte("tallyparams")
DepositedCoinsAccAddr = sdk.AccAddress(crypto.AddressHash([]byte("govDepositedCoins")))
BurnedDepositCoinsAccAddr = sdk.AccAddress(crypto.AddressHash([]byte("govBurnedDepositCoins")))
)
// Type declaration for parameters
func ParamTypeTable() params.TypeTable {
return params.NewTypeTable(
ParamStoreKeyDepositProcedure, DepositProcedure{},
ParamStoreKeyVotingProcedure, VotingProcedure{},
ParamStoreKeyTallyingProcedure, TallyingProcedure{},
ParamStoreKeyDepositParams, DepositParams{},
ParamStoreKeyVotingParams, VotingParams{},
ParamStoreKeyTallyParams, TallyParams{},
)
}
@ -92,13 +99,17 @@ func (keeper Keeper) NewTextProposal(ctx sdk.Context, title string, description
TotalDeposit: sdk.Coins{},
SubmitTime: ctx.BlockHeader().Time,
}
depositPeriod := keeper.GetDepositParams(ctx).MaxDepositPeriod
proposal.SetDepositEndTime(proposal.GetSubmitTime().Add(depositPeriod))
keeper.SetProposal(ctx, proposal)
keeper.InactiveProposalQueuePush(ctx, proposal)
keeper.InsertInactiveProposalQueue(ctx, proposal.GetDepositEndTime(), proposalID)
return proposal
}
// Get Proposal from store by ProposalID
func (keeper Keeper) GetProposal(ctx sdk.Context, proposalID int64) Proposal {
func (keeper Keeper) GetProposal(ctx sdk.Context, proposalID uint64) Proposal {
store := ctx.KVStore(keeper.storeKey)
bz := store.Get(KeyProposal(proposalID))
if bz == nil {
@ -119,13 +130,16 @@ func (keeper Keeper) SetProposal(ctx sdk.Context, proposal Proposal) {
}
// Implements sdk.AccountKeeper.
func (keeper Keeper) DeleteProposal(ctx sdk.Context, proposal Proposal) {
func (keeper Keeper) DeleteProposal(ctx sdk.Context, proposalID uint64) {
store := ctx.KVStore(keeper.storeKey)
store.Delete(KeyProposal(proposal.GetProposalID()))
proposal := keeper.GetProposal(ctx, proposalID)
keeper.RemoveFromInactiveProposalQueue(ctx, proposal.GetDepositEndTime(), proposalID)
keeper.RemoveFromActiveProposalQueue(ctx, proposal.GetVotingEndTime(), proposalID)
store.Delete(KeyProposal(proposalID))
}
// Get Proposal from store by ProposalID
func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddress, depositerAddr sdk.AccAddress, status ProposalStatus, numLatest int64) []Proposal {
func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddress, depositerAddr sdk.AccAddress, status ProposalStatus, numLatest uint64) []Proposal {
maxProposalID, err := keeper.peekCurrentProposalID(ctx)
if err != nil {
@ -134,7 +148,7 @@ func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddr
matchingProposals := []Proposal{}
if numLatest <= 0 {
if numLatest == 0 {
numLatest = maxProposalID
}
@ -169,7 +183,7 @@ func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddr
return matchingProposals
}
func (keeper Keeper) setInitialProposalID(ctx sdk.Context, proposalID int64) sdk.Error {
func (keeper Keeper) setInitialProposalID(ctx sdk.Context, proposalID uint64) sdk.Error {
store := ctx.KVStore(keeper.storeKey)
bz := store.Get(KeyNextProposalID)
if bz != nil {
@ -181,7 +195,7 @@ func (keeper Keeper) setInitialProposalID(ctx sdk.Context, proposalID int64) sdk
}
// Get the last used proposal ID
func (keeper Keeper) GetLastProposalID(ctx sdk.Context) (proposalID int64) {
func (keeper Keeper) GetLastProposalID(ctx sdk.Context) (proposalID uint64) {
proposalID, err := keeper.peekCurrentProposalID(ctx)
if err != nil {
return 0
@ -191,11 +205,11 @@ func (keeper Keeper) GetLastProposalID(ctx sdk.Context) (proposalID int64) {
}
// Gets the next available ProposalID and increments it
func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID int64, err sdk.Error) {
func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID uint64, err sdk.Error) {
store := ctx.KVStore(keeper.storeKey)
bz := store.Get(KeyNextProposalID)
if bz == nil {
return -1, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set")
return 0, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set")
}
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalID)
bz = keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID + 1)
@ -204,11 +218,11 @@ func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID int64, err sd
}
// Peeks the next available ProposalID without incrementing it
func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID int64, err sdk.Error) {
func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID uint64, err sdk.Error) {
store := ctx.KVStore(keeper.storeKey)
bz := store.Get(KeyNextProposalID)
if bz == nil {
return -1, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set")
return 0, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set")
}
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalID)
return proposalID, nil
@ -216,58 +230,62 @@ func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID int64, e
func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) {
proposal.SetVotingStartTime(ctx.BlockHeader().Time)
votingPeriod := keeper.GetVotingParams(ctx).VotingPeriod
proposal.SetVotingEndTime(proposal.GetVotingStartTime().Add(votingPeriod))
proposal.SetStatus(StatusVotingPeriod)
keeper.SetProposal(ctx, proposal)
keeper.ActiveProposalQueuePush(ctx, proposal)
keeper.RemoveFromInactiveProposalQueue(ctx, proposal.GetDepositEndTime(), proposal.GetProposalID())
keeper.InsertActiveProposalQueue(ctx, proposal.GetVotingEndTime(), proposal.GetProposalID())
}
// =====================================================
// Procedures
// Params
// Returns the current Deposit Procedure from the global param store
// Returns the current DepositParams from the global param store
// nolint: errcheck
func (keeper Keeper) GetDepositProcedure(ctx sdk.Context) DepositProcedure {
var depositProcedure DepositProcedure
keeper.paramSpace.Get(ctx, ParamStoreKeyDepositProcedure, &depositProcedure)
return depositProcedure
func (keeper Keeper) GetDepositParams(ctx sdk.Context) DepositParams {
var depositParams DepositParams
keeper.paramSpace.Get(ctx, ParamStoreKeyDepositParams, &depositParams)
return depositParams
}
// Returns the current Voting Procedure from the global param store
// nolint: errcheck
func (keeper Keeper) GetVotingProcedure(ctx sdk.Context) VotingProcedure {
var votingProcedure VotingProcedure
keeper.paramSpace.Get(ctx, ParamStoreKeyVotingProcedure, &votingProcedure)
return votingProcedure
func (keeper Keeper) GetVotingParams(ctx sdk.Context) VotingParams {
var votingParams VotingParams
keeper.paramSpace.Get(ctx, ParamStoreKeyVotingParams, &votingParams)
return votingParams
}
// Returns the current Tallying Procedure from the global param store
// nolint: errcheck
func (keeper Keeper) GetTallyingProcedure(ctx sdk.Context) TallyingProcedure {
var tallyingProcedure TallyingProcedure
keeper.paramSpace.Get(ctx, ParamStoreKeyTallyingProcedure, &tallyingProcedure)
return tallyingProcedure
func (keeper Keeper) GetTallyParams(ctx sdk.Context) TallyParams {
var tallyParams TallyParams
keeper.paramSpace.Get(ctx, ParamStoreKeyTallyParams, &tallyParams)
return tallyParams
}
// nolint: errcheck
func (keeper Keeper) setDepositProcedure(ctx sdk.Context, depositProcedure DepositProcedure) {
keeper.paramSpace.Set(ctx, ParamStoreKeyDepositProcedure, &depositProcedure)
func (keeper Keeper) setDepositParams(ctx sdk.Context, depositParams DepositParams) {
keeper.paramSpace.Set(ctx, ParamStoreKeyDepositParams, &depositParams)
}
// nolint: errcheck
func (keeper Keeper) setVotingProcedure(ctx sdk.Context, votingProcedure VotingProcedure) {
keeper.paramSpace.Set(ctx, ParamStoreKeyVotingProcedure, &votingProcedure)
func (keeper Keeper) setVotingParams(ctx sdk.Context, votingParams VotingParams) {
keeper.paramSpace.Set(ctx, ParamStoreKeyVotingParams, &votingParams)
}
// nolint: errcheck
func (keeper Keeper) setTallyingProcedure(ctx sdk.Context, tallyingProcedure TallyingProcedure) {
keeper.paramSpace.Set(ctx, ParamStoreKeyTallyingProcedure, &tallyingProcedure)
func (keeper Keeper) setTallyParams(ctx sdk.Context, tallyParams TallyParams) {
keeper.paramSpace.Set(ctx, ParamStoreKeyTallyParams, &tallyParams)
}
// =====================================================
// Votes
// Adds a vote on a specific proposal
func (keeper Keeper) AddVote(ctx sdk.Context, proposalID int64, voterAddr sdk.AccAddress, option VoteOption) sdk.Error {
func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, option VoteOption) sdk.Error {
proposal := keeper.GetProposal(ctx, proposalID)
if proposal == nil {
return ErrUnknownProposal(keeper.codespace, proposalID)
@ -291,7 +309,7 @@ func (keeper Keeper) AddVote(ctx sdk.Context, proposalID int64, voterAddr sdk.Ac
}
// Gets the vote of a specific voter on a specific proposal
func (keeper Keeper) GetVote(ctx sdk.Context, proposalID int64, voterAddr sdk.AccAddress) (Vote, bool) {
func (keeper Keeper) GetVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) (Vote, bool) {
store := ctx.KVStore(keeper.storeKey)
bz := store.Get(KeyVote(proposalID, voterAddr))
if bz == nil {
@ -302,19 +320,19 @@ func (keeper Keeper) GetVote(ctx sdk.Context, proposalID int64, voterAddr sdk.Ac
return vote, true
}
func (keeper Keeper) setVote(ctx sdk.Context, proposalID int64, voterAddr sdk.AccAddress, vote Vote) {
func (keeper Keeper) setVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, vote Vote) {
store := ctx.KVStore(keeper.storeKey)
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(vote)
store.Set(KeyVote(proposalID, voterAddr), bz)
}
// Gets all the votes on a specific proposal
func (keeper Keeper) GetVotes(ctx sdk.Context, proposalID int64) sdk.Iterator {
func (keeper Keeper) GetVotes(ctx sdk.Context, proposalID uint64) sdk.Iterator {
store := ctx.KVStore(keeper.storeKey)
return sdk.KVStorePrefixIterator(store, KeyVotesSubspace(proposalID))
}
func (keeper Keeper) deleteVote(ctx sdk.Context, proposalID int64, voterAddr sdk.AccAddress) {
func (keeper Keeper) deleteVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) {
store := ctx.KVStore(keeper.storeKey)
store.Delete(KeyVote(proposalID, voterAddr))
}
@ -323,7 +341,7 @@ func (keeper Keeper) deleteVote(ctx sdk.Context, proposalID int64, voterAddr sdk
// Deposits
// Gets the deposit of a specific depositer on a specific proposal
func (keeper Keeper) GetDeposit(ctx sdk.Context, proposalID int64, depositerAddr sdk.AccAddress) (Deposit, bool) {
func (keeper Keeper) GetDeposit(ctx sdk.Context, proposalID uint64, depositerAddr sdk.AccAddress) (Deposit, bool) {
store := ctx.KVStore(keeper.storeKey)
bz := store.Get(KeyDeposit(proposalID, depositerAddr))
if bz == nil {
@ -334,7 +352,7 @@ func (keeper Keeper) GetDeposit(ctx sdk.Context, proposalID int64, depositerAddr
return deposit, true
}
func (keeper Keeper) setDeposit(ctx sdk.Context, proposalID int64, depositerAddr sdk.AccAddress, deposit Deposit) {
func (keeper Keeper) setDeposit(ctx sdk.Context, proposalID uint64, depositerAddr sdk.AccAddress, deposit Deposit) {
store := ctx.KVStore(keeper.storeKey)
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(deposit)
store.Set(KeyDeposit(proposalID, depositerAddr), bz)
@ -342,7 +360,7 @@ func (keeper Keeper) setDeposit(ctx sdk.Context, proposalID int64, depositerAddr
// Adds or updates a deposit of a specific depositer on a specific proposal
// Activates voting period when appropriate
func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID int64, depositerAddr sdk.AccAddress, depositAmount sdk.Coins) (sdk.Error, bool) {
func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositerAddr sdk.AccAddress, depositAmount sdk.Coins) (sdk.Error, bool) {
// Checks to see if proposal exists
proposal := keeper.GetProposal(ctx, proposalID)
if proposal == nil {
@ -354,8 +372,8 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID int64, depositerAddr
return ErrAlreadyFinishedProposal(keeper.codespace, proposalID), false
}
// Subtract coins from depositer's account
_, _, err := keeper.ck.SubtractCoins(ctx, depositerAddr, depositAmount)
// Send coins from depositer's account to DepositedCoinsAccAddr account
_, err := keeper.ck.SendCoins(ctx, depositerAddr, DepositedCoinsAccAddr, depositAmount)
if err != nil {
return err, false
}
@ -367,7 +385,7 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID int64, depositerAddr
// Check if deposit tipped proposal into voting period
// Active voting period if so
activatedVotingPeriod := false
if proposal.GetStatus() == StatusDepositPeriod && proposal.GetTotalDeposit().IsGTE(keeper.GetDepositProcedure(ctx).MinDeposit) {
if proposal.GetStatus() == StatusDepositPeriod && proposal.GetTotalDeposit().IsGTE(keeper.GetDepositParams(ctx).MinDeposit) {
keeper.activateVotingPeriod(ctx, proposal)
activatedVotingPeriod = true
}
@ -386,13 +404,13 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID int64, depositerAddr
}
// Gets all the deposits on a specific proposal
func (keeper Keeper) GetDeposits(ctx sdk.Context, proposalID int64) sdk.Iterator {
func (keeper Keeper) GetDeposits(ctx sdk.Context, proposalID uint64) sdk.Iterator {
store := ctx.KVStore(keeper.storeKey)
return sdk.KVStorePrefixIterator(store, KeyDepositsSubspace(proposalID))
}
// Returns and deletes all the deposits on a specific proposal
func (keeper Keeper) RefundDeposits(ctx sdk.Context, proposalID int64) {
func (keeper Keeper) RefundDeposits(ctx sdk.Context, proposalID uint64) {
store := ctx.KVStore(keeper.storeKey)
depositsIterator := keeper.GetDeposits(ctx, proposalID)
@ -400,7 +418,7 @@ func (keeper Keeper) RefundDeposits(ctx sdk.Context, proposalID int64) {
deposit := &Deposit{}
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(depositsIterator.Value(), deposit)
_, _, err := keeper.ck.AddCoins(ctx, deposit.Depositer, deposit.Amount)
_, err := keeper.ck.SendCoins(ctx, DepositedCoinsAccAddr, deposit.Depositer, deposit.Amount)
if err != nil {
panic("should not happen")
}
@ -412,11 +430,19 @@ func (keeper Keeper) RefundDeposits(ctx sdk.Context, proposalID int64) {
}
// Deletes all the deposits on a specific proposal without refunding them
func (keeper Keeper) DeleteDeposits(ctx sdk.Context, proposalID int64) {
func (keeper Keeper) DeleteDeposits(ctx sdk.Context, proposalID uint64) {
store := ctx.KVStore(keeper.storeKey)
depositsIterator := keeper.GetDeposits(ctx, proposalID)
for ; depositsIterator.Valid(); depositsIterator.Next() {
deposit := &Deposit{}
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(depositsIterator.Value(), deposit)
_, err := keeper.ck.SendCoins(ctx, DepositedCoinsAccAddr, BurnedDepositCoinsAccAddr, deposit.Amount)
if err != nil {
panic("should not happen")
}
store.Delete(depositsIterator.Key())
}
@ -426,93 +452,40 @@ func (keeper Keeper) DeleteDeposits(ctx sdk.Context, proposalID int64) {
// =====================================================
// ProposalQueues
func (keeper Keeper) getActiveProposalQueue(ctx sdk.Context) ProposalQueue {
// Returns an iterator for all the proposals in the Active Queue that expire by endTime
func (keeper Keeper) ActiveProposalQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
store := ctx.KVStore(keeper.storeKey)
bz := store.Get(KeyActiveProposalQueue)
if bz == nil {
return nil
}
var proposalQueue ProposalQueue
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalQueue)
return proposalQueue
return store.Iterator(PrefixActiveProposalQueue, sdk.PrefixEndBytes(PrefixActiveProposalQueueTime(endTime)))
}
func (keeper Keeper) setActiveProposalQueue(ctx sdk.Context, proposalQueue ProposalQueue) {
// Inserts a ProposalID into the active proposal queue at endTime
func (keeper Keeper) InsertActiveProposalQueue(ctx sdk.Context, endTime time.Time, proposalID uint64) {
store := ctx.KVStore(keeper.storeKey)
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalQueue)
store.Set(KeyActiveProposalQueue, bz)
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID)
store.Set(KeyActiveProposalQueueProposal(endTime, proposalID), bz)
}
// Return the Proposal at the front of the ProposalQueue
func (keeper Keeper) ActiveProposalQueuePeek(ctx sdk.Context) Proposal {
proposalQueue := keeper.getActiveProposalQueue(ctx)
if len(proposalQueue) == 0 {
return nil
}
return keeper.GetProposal(ctx, proposalQueue[0])
}
// Remove and return a Proposal from the front of the ProposalQueue
func (keeper Keeper) ActiveProposalQueuePop(ctx sdk.Context) Proposal {
proposalQueue := keeper.getActiveProposalQueue(ctx)
if len(proposalQueue) == 0 {
return nil
}
frontElement, proposalQueue := proposalQueue[0], proposalQueue[1:]
keeper.setActiveProposalQueue(ctx, proposalQueue)
return keeper.GetProposal(ctx, frontElement)
}
// Add a proposalID to the back of the ProposalQueue
func (keeper Keeper) ActiveProposalQueuePush(ctx sdk.Context, proposal Proposal) {
proposalQueue := append(keeper.getActiveProposalQueue(ctx), proposal.GetProposalID())
keeper.setActiveProposalQueue(ctx, proposalQueue)
}
func (keeper Keeper) getInactiveProposalQueue(ctx sdk.Context) ProposalQueue {
// removes a proposalID from the Active Proposal Queue
func (keeper Keeper) RemoveFromActiveProposalQueue(ctx sdk.Context, endTime time.Time, proposalID uint64) {
store := ctx.KVStore(keeper.storeKey)
bz := store.Get(KeyInactiveProposalQueue)
if bz == nil {
return nil
}
var proposalQueue ProposalQueue
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalQueue)
return proposalQueue
store.Delete(KeyActiveProposalQueueProposal(endTime, proposalID))
}
func (keeper Keeper) setInactiveProposalQueue(ctx sdk.Context, proposalQueue ProposalQueue) {
// Returns an iterator for all the proposals in the Inactive Queue that expire by endTime
func (keeper Keeper) InactiveProposalQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
store := ctx.KVStore(keeper.storeKey)
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalQueue)
store.Set(KeyInactiveProposalQueue, bz)
return store.Iterator(PrefixInactiveProposalQueue, sdk.PrefixEndBytes(PrefixInactiveProposalQueueTime(endTime)))
}
// Return the Proposal at the front of the ProposalQueue
func (keeper Keeper) InactiveProposalQueuePeek(ctx sdk.Context) Proposal {
proposalQueue := keeper.getInactiveProposalQueue(ctx)
if len(proposalQueue) == 0 {
return nil
}
return keeper.GetProposal(ctx, proposalQueue[0])
// Inserts a ProposalID into the inactive proposal queue at endTime
func (keeper Keeper) InsertInactiveProposalQueue(ctx sdk.Context, endTime time.Time, proposalID uint64) {
store := ctx.KVStore(keeper.storeKey)
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID)
store.Set(KeyInactiveProposalQueueProposal(endTime, proposalID), bz)
}
// Remove and return a Proposal from the front of the ProposalQueue
func (keeper Keeper) InactiveProposalQueuePop(ctx sdk.Context) Proposal {
proposalQueue := keeper.getInactiveProposalQueue(ctx)
if len(proposalQueue) == 0 {
return nil
}
frontElement, proposalQueue := proposalQueue[0], proposalQueue[1:]
keeper.setInactiveProposalQueue(ctx, proposalQueue)
return keeper.GetProposal(ctx, frontElement)
}
// Add a proposalID to the back of the ProposalQueue
func (keeper Keeper) InactiveProposalQueuePush(ctx sdk.Context, proposal Proposal) {
proposalQueue := append(keeper.getInactiveProposalQueue(ctx), proposal.GetProposalID())
keeper.setInactiveProposalQueue(ctx, proposalQueue)
// removes a proposalID from the Inactive Proposal Queue
func (keeper Keeper) RemoveFromInactiveProposalQueue(ctx sdk.Context, endTime time.Time, proposalID uint64) {
store := ctx.KVStore(keeper.storeKey)
store.Delete(KeyInactiveProposalQueueProposal(endTime, proposalID))
}

View File

@ -1,7 +1,9 @@
package gov
import (
"bytes"
"fmt"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -10,32 +12,68 @@ import (
// Key for getting a the next available proposalID from the store
var (
KeyNextProposalID = []byte("newProposalID")
KeyActiveProposalQueue = []byte("activeProposalQueue")
KeyInactiveProposalQueue = []byte("inactiveProposalQueue")
KeyDelimiter = []byte(":")
KeyNextProposalID = []byte("newProposalID")
PrefixActiveProposalQueue = []byte("activeProposalQueue")
PrefixInactiveProposalQueue = []byte("inactiveProposalQueue")
)
// Key for getting a specific proposal from the store
func KeyProposal(proposalID int64) []byte {
func KeyProposal(proposalID uint64) []byte {
return []byte(fmt.Sprintf("proposals:%d", proposalID))
}
// Key for getting a specific deposit from the store
func KeyDeposit(proposalID int64, depositerAddr sdk.AccAddress) []byte {
func KeyDeposit(proposalID uint64, depositerAddr sdk.AccAddress) []byte {
return []byte(fmt.Sprintf("deposits:%d:%d", proposalID, depositerAddr))
}
// Key for getting a specific vote from the store
func KeyVote(proposalID int64, voterAddr sdk.AccAddress) []byte {
func KeyVote(proposalID uint64, voterAddr sdk.AccAddress) []byte {
return []byte(fmt.Sprintf("votes:%d:%d", proposalID, voterAddr))
}
// Key for getting all deposits on a proposal from the store
func KeyDepositsSubspace(proposalID int64) []byte {
func KeyDepositsSubspace(proposalID uint64) []byte {
return []byte(fmt.Sprintf("deposits:%d:", proposalID))
}
// Key for getting all votes on a proposal from the store
func KeyVotesSubspace(proposalID int64) []byte {
func KeyVotesSubspace(proposalID uint64) []byte {
return []byte(fmt.Sprintf("votes:%d:", proposalID))
}
// Returns the key for a proposalID in the activeProposalQueue
func PrefixActiveProposalQueueTime(endTime time.Time) []byte {
return bytes.Join([][]byte{
PrefixActiveProposalQueue,
sdk.FormatTimeBytes(endTime),
}, KeyDelimiter)
}
// Returns the key for a proposalID in the activeProposalQueue
func KeyActiveProposalQueueProposal(endTime time.Time, proposalID uint64) []byte {
return bytes.Join([][]byte{
PrefixActiveProposalQueue,
sdk.FormatTimeBytes(endTime),
sdk.Uint64ToBigEndian(proposalID),
}, KeyDelimiter)
}
// Returns the key for a proposalID in the activeProposalQueue
func PrefixInactiveProposalQueueTime(endTime time.Time) []byte {
return bytes.Join([][]byte{
PrefixInactiveProposalQueue,
sdk.FormatTimeBytes(endTime),
}, KeyDelimiter)
}
// Returns the key for a proposalID in the activeProposalQueue
func KeyInactiveProposalQueueProposal(endTime time.Time, proposalID uint64) []byte {
return bytes.Join([][]byte{
PrefixInactiveProposalQueue,
sdk.FormatTimeBytes(endTime),
sdk.Uint64ToBigEndian(proposalID),
}, KeyDelimiter)
}

View File

@ -36,7 +36,7 @@ func TestIncrementProposalNumber(t *testing.T) {
keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
proposal6 := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
require.Equal(t, int64(6), proposal6.GetProposalID())
require.Equal(t, uint64(6), proposal6.GetProposalID())
}
func TestActivateVotingPeriod(t *testing.T) {
@ -47,12 +47,17 @@ func TestActivateVotingPeriod(t *testing.T) {
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
require.True(t, proposal.GetVotingStartTime().Equal(time.Time{}))
require.Nil(t, keeper.ActiveProposalQueuePeek(ctx))
keeper.activateVotingPeriod(ctx, proposal)
require.True(t, proposal.GetVotingStartTime().Equal(ctx.BlockHeader().Time))
require.Equal(t, proposal.GetProposalID(), keeper.ActiveProposalQueuePeek(ctx).GetProposalID())
activeIterator := keeper.ActiveProposalQueueIterator(ctx, proposal.GetVotingEndTime())
require.True(t, activeIterator.Valid())
var proposalID uint64
keeper.cdc.UnmarshalBinaryLengthPrefixed(activeIterator.Value(), &proposalID)
require.Equal(t, proposalID, proposal.GetProposalID())
activeIterator.Close()
}
func TestDeposits(t *testing.T) {
@ -79,7 +84,6 @@ func TestDeposits(t *testing.T) {
deposit, found := keeper.GetDeposit(ctx, proposalID, addrs[1])
require.False(t, found)
require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(time.Time{}))
require.Nil(t, keeper.ActiveProposalQueuePeek(ctx))
// Check first deposit
err, votingStarted := keeper.AddDeposit(ctx, proposalID, addrs[0], fourSteak)
@ -116,8 +120,6 @@ func TestDeposits(t *testing.T) {
// Check that proposal moved to voting period
require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(ctx.BlockHeader().Time))
require.NotNil(t, keeper.ActiveProposalQueuePeek(ctx))
require.Equal(t, proposalID, keeper.ActiveProposalQueuePeek(ctx).GetProposalID())
// Test deposit iterator
depositsIterator := keeper.GetDeposits(ctx, proposalID)
@ -207,44 +209,21 @@ func TestProposalQueues(t *testing.T) {
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
mapp.InitChainer(ctx, abci.RequestInitChain{})
require.Nil(t, keeper.InactiveProposalQueuePeek(ctx))
require.Nil(t, keeper.ActiveProposalQueuePeek(ctx))
// create test proposals
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
proposal2 := keeper.NewTextProposal(ctx, "Test2", "description", ProposalTypeText)
proposal3 := keeper.NewTextProposal(ctx, "Test3", "description", ProposalTypeText)
proposal4 := keeper.NewTextProposal(ctx, "Test4", "description", ProposalTypeText)
// test pushing to inactive proposal queue
keeper.InactiveProposalQueuePush(ctx, proposal)
keeper.InactiveProposalQueuePush(ctx, proposal2)
keeper.InactiveProposalQueuePush(ctx, proposal3)
keeper.InactiveProposalQueuePush(ctx, proposal4)
inactiveIterator := keeper.InactiveProposalQueueIterator(ctx, proposal.GetDepositEndTime())
require.True(t, inactiveIterator.Valid())
var proposalID uint64
keeper.cdc.UnmarshalBinaryLengthPrefixed(inactiveIterator.Value(), &proposalID)
require.Equal(t, proposalID, proposal.GetProposalID())
inactiveIterator.Close()
// test peeking and popping from inactive proposal queue
require.Equal(t, keeper.InactiveProposalQueuePeek(ctx).GetProposalID(), proposal.GetProposalID())
require.Equal(t, keeper.InactiveProposalQueuePop(ctx).GetProposalID(), proposal.GetProposalID())
require.Equal(t, keeper.InactiveProposalQueuePeek(ctx).GetProposalID(), proposal2.GetProposalID())
require.Equal(t, keeper.InactiveProposalQueuePop(ctx).GetProposalID(), proposal2.GetProposalID())
require.Equal(t, keeper.InactiveProposalQueuePeek(ctx).GetProposalID(), proposal3.GetProposalID())
require.Equal(t, keeper.InactiveProposalQueuePop(ctx).GetProposalID(), proposal3.GetProposalID())
require.Equal(t, keeper.InactiveProposalQueuePeek(ctx).GetProposalID(), proposal4.GetProposalID())
require.Equal(t, keeper.InactiveProposalQueuePop(ctx).GetProposalID(), proposal4.GetProposalID())
keeper.activateVotingPeriod(ctx, proposal)
// test pushing to active proposal queue
keeper.ActiveProposalQueuePush(ctx, proposal)
keeper.ActiveProposalQueuePush(ctx, proposal2)
keeper.ActiveProposalQueuePush(ctx, proposal3)
keeper.ActiveProposalQueuePush(ctx, proposal4)
// test peeking and popping from active proposal queue
require.Equal(t, keeper.ActiveProposalQueuePeek(ctx).GetProposalID(), proposal.GetProposalID())
require.Equal(t, keeper.ActiveProposalQueuePop(ctx).GetProposalID(), proposal.GetProposalID())
require.Equal(t, keeper.ActiveProposalQueuePeek(ctx).GetProposalID(), proposal2.GetProposalID())
require.Equal(t, keeper.ActiveProposalQueuePop(ctx).GetProposalID(), proposal2.GetProposalID())
require.Equal(t, keeper.ActiveProposalQueuePeek(ctx).GetProposalID(), proposal3.GetProposalID())
require.Equal(t, keeper.ActiveProposalQueuePop(ctx).GetProposalID(), proposal3.GetProposalID())
require.Equal(t, keeper.ActiveProposalQueuePeek(ctx).GetProposalID(), proposal4.GetProposalID())
require.Equal(t, keeper.ActiveProposalQueuePop(ctx).GetProposalID(), proposal4.GetProposalID())
activeIterator := keeper.ActiveProposalQueueIterator(ctx, proposal.GetVotingEndTime())
require.True(t, activeIterator.Valid())
keeper.cdc.UnmarshalBinaryLengthPrefixed(activeIterator.Value(), &proposalID)
require.Equal(t, proposalID, proposal.GetProposalID())
activeIterator.Close()
}

View File

@ -84,12 +84,12 @@ func (msg MsgSubmitProposal) GetSigners() []sdk.AccAddress {
//-----------------------------------------------------------
// MsgDeposit
type MsgDeposit struct {
ProposalID int64 `json:"proposal_id"` // ID of the proposal
ProposalID uint64 `json:"proposal_id"` // ID of the proposal
Depositer sdk.AccAddress `json:"depositer"` // Address of the depositer
Amount sdk.Coins `json:"amount"` // Coins to add to the proposal's deposit
}
func NewMsgDeposit(depositer sdk.AccAddress, proposalID int64, amount sdk.Coins) MsgDeposit {
func NewMsgDeposit(depositer sdk.AccAddress, proposalID uint64, amount sdk.Coins) MsgDeposit {
return MsgDeposit{
ProposalID: proposalID,
Depositer: depositer,
@ -145,12 +145,12 @@ func (msg MsgDeposit) GetSigners() []sdk.AccAddress {
//-----------------------------------------------------------
// MsgVote
type MsgVote struct {
ProposalID int64 `json:"proposal_id"` // ID of the proposal
ProposalID uint64 `json:"proposal_id"` // ID of the proposal
Voter sdk.AccAddress `json:"voter"` // address of the voter
Option VoteOption `json:"option"` // option from OptionSet chosen by the voter
}
func NewMsgVote(voter sdk.AccAddress, proposalID int64, option VoteOption) MsgVote {
func NewMsgVote(voter sdk.AccAddress, proposalID uint64, option VoteOption) MsgVote {
return MsgVote{
ProposalID: proposalID,
Voter: voter,

View File

@ -53,13 +53,12 @@ func TestMsgSubmitProposal(t *testing.T) {
func TestMsgDeposit(t *testing.T) {
_, addrs, _, _ := mock.CreateGenAccounts(1, sdk.Coins{})
tests := []struct {
proposalID int64
proposalID uint64
depositerAddr sdk.AccAddress
depositAmount sdk.Coins
expectPass bool
}{
{0, addrs[0], coinsPos, true},
{-1, addrs[0], coinsPos, false},
{1, sdk.AccAddress{}, coinsPos, false},
{1, addrs[0], coinsZero, true},
{1, addrs[0], coinsNeg, false},
@ -80,13 +79,12 @@ func TestMsgDeposit(t *testing.T) {
func TestMsgVote(t *testing.T) {
_, addrs, _, _ := mock.CreateGenAccounts(1, sdk.Coins{})
tests := []struct {
proposalID int64
proposalID uint64
voterAddr sdk.AccAddress
option VoteOption
expectPass bool
}{
{0, addrs[0], OptionYes, true},
{-1, addrs[0], OptionYes, false},
{0, sdk.AccAddress{}, OptionYes, false},
{0, addrs[0], OptionNo, true},
{0, addrs[0], OptionNoWithVeto, true},

View File

@ -7,19 +7,19 @@ import (
)
// Procedure around Deposits for governance
type DepositProcedure struct {
type DepositParams struct {
MinDeposit sdk.Coins `json:"min_deposit"` // Minimum deposit for a proposal to enter voting period.
MaxDepositPeriod time.Duration `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months
}
// Procedure around Tallying votes in governance
type TallyingProcedure struct {
type TallyParams struct {
Threshold sdk.Dec `json:"threshold"` // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
Veto sdk.Dec `json:"veto"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
GovernancePenalty sdk.Dec `json:"governance_penalty"` // Penalty if validator does not vote
}
// Procedure around Voting in governance
type VotingProcedure struct {
type VotingParams struct {
VotingPeriod time.Duration `json:"voting_period"` // Length of the voting period.
}

View File

@ -13,8 +13,8 @@ import (
//-----------------------------------------------------------
// Proposal interface
type Proposal interface {
GetProposalID() int64
SetProposalID(int64)
GetProposalID() uint64
SetProposalID(uint64)
GetTitle() string
SetTitle(string)
@ -34,11 +34,17 @@ type Proposal interface {
GetSubmitTime() time.Time
SetSubmitTime(time.Time)
GetDepositEndTime() time.Time
SetDepositEndTime(time.Time)
GetTotalDeposit() sdk.Coins
SetTotalDeposit(sdk.Coins)
GetVotingStartTime() time.Time
SetVotingStartTime(time.Time)
GetVotingEndTime() time.Time
SetVotingEndTime(time.Time)
}
// checks if two proposals are equal
@ -50,8 +56,10 @@ func ProposalEqual(proposalA Proposal, proposalB Proposal) bool {
proposalA.GetStatus() == proposalB.GetStatus() &&
proposalA.GetTallyResult().Equals(proposalB.GetTallyResult()) &&
proposalA.GetSubmitTime().Equal(proposalB.GetSubmitTime()) &&
proposalA.GetDepositEndTime().Equal(proposalB.GetDepositEndTime()) &&
proposalA.GetTotalDeposit().IsEqual(proposalB.GetTotalDeposit()) &&
proposalA.GetVotingStartTime().Equal(proposalB.GetVotingStartTime()) {
proposalA.GetVotingStartTime().Equal(proposalB.GetVotingStartTime()) &&
proposalA.GetVotingEndTime().Equal(proposalB.GetVotingEndTime()) {
return true
}
return false
@ -60,7 +68,7 @@ func ProposalEqual(proposalA Proposal, proposalB Proposal) bool {
//-----------------------------------------------------------
// Text Proposals
type TextProposal struct {
ProposalID int64 `json:"proposal_id"` // ID of the proposal
ProposalID uint64 `json:"proposal_id"` // ID of the proposal
Title string `json:"title"` // Title of the proposal
Description string `json:"description"` // Description of the proposal
ProposalType ProposalKind `json:"proposal_type"` // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal}
@ -68,18 +76,20 @@ type TextProposal struct {
Status ProposalStatus `json:"proposal_status"` // Status of the Proposal {Pending, Active, Passed, Rejected}
TallyResult TallyResult `json:"tally_result"` // Result of Tallys
SubmitTime time.Time `json:"submit_time"` // Height of the block where TxGovSubmitProposal was included
TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit
SubmitTime time.Time `json:"submit_time"` // Time of the block where TxGovSubmitProposal was included
DepositEndTime time.Time `json:"deposit_end_time"` // Time that the Proposal would expire if deposit amount isn't met
TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit
VotingStartTime time.Time `json:"voting_start_time"` // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached
VotingStartTime time.Time `json:"voting_start_time"` // Time of the block where MinDeposit was reached. -1 if MinDeposit is not reached
VotingEndTime time.Time `json:"voting_end_time"` // Time that the VotingPeriod for this proposal will end and votes will be tallied
}
// Implements Proposal Interface
var _ Proposal = (*TextProposal)(nil)
// nolint
func (tp TextProposal) GetProposalID() int64 { return tp.ProposalID }
func (tp *TextProposal) SetProposalID(proposalID int64) { tp.ProposalID = proposalID }
func (tp TextProposal) GetProposalID() uint64 { return tp.ProposalID }
func (tp *TextProposal) SetProposalID(proposalID uint64) { tp.ProposalID = proposalID }
func (tp TextProposal) GetTitle() string { return tp.Title }
func (tp *TextProposal) SetTitle(title string) { tp.Title = title }
func (tp TextProposal) GetDescription() string { return tp.Description }
@ -92,16 +102,24 @@ func (tp TextProposal) GetTallyResult() TallyResult { return tp.T
func (tp *TextProposal) SetTallyResult(tallyResult TallyResult) { tp.TallyResult = tallyResult }
func (tp TextProposal) GetSubmitTime() time.Time { return tp.SubmitTime }
func (tp *TextProposal) SetSubmitTime(submitTime time.Time) { tp.SubmitTime = submitTime }
func (tp TextProposal) GetTotalDeposit() sdk.Coins { return tp.TotalDeposit }
func (tp *TextProposal) SetTotalDeposit(totalDeposit sdk.Coins) { tp.TotalDeposit = totalDeposit }
func (tp TextProposal) GetVotingStartTime() time.Time { return tp.VotingStartTime }
func (tp TextProposal) GetDepositEndTime() time.Time { return tp.DepositEndTime }
func (tp *TextProposal) SetDepositEndTime(depositEndTime time.Time) {
tp.DepositEndTime = depositEndTime
}
func (tp TextProposal) GetTotalDeposit() sdk.Coins { return tp.TotalDeposit }
func (tp *TextProposal) SetTotalDeposit(totalDeposit sdk.Coins) { tp.TotalDeposit = totalDeposit }
func (tp TextProposal) GetVotingStartTime() time.Time { return tp.VotingStartTime }
func (tp *TextProposal) SetVotingStartTime(votingStartTime time.Time) {
tp.VotingStartTime = votingStartTime
}
func (tp TextProposal) GetVotingEndTime() time.Time { return tp.VotingEndTime }
func (tp *TextProposal) SetVotingEndTime(votingEndTime time.Time) {
tp.VotingEndTime = votingEndTime
}
//-----------------------------------------------------------
// ProposalQueue
type ProposalQueue []int64
type ProposalQueue []uint64
//-----------------------------------------------------------
// ProposalKind

View File

@ -42,7 +42,7 @@ func NewQuerier(keeper Keeper) sdk.Querier {
// Params for query 'custom/gov/proposal'
type QueryProposalParams struct {
ProposalID int64
ProposalID uint64
}
// nolint: unparam
@ -67,7 +67,7 @@ func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper
// Params for query 'custom/gov/deposit'
type QueryDepositParams struct {
ProposalID int64
ProposalID uint64
Depositer sdk.AccAddress
}
@ -89,7 +89,7 @@ func queryDeposit(ctx sdk.Context, path []string, req abci.RequestQuery, keeper
// Params for query 'custom/gov/vote'
type QueryVoteParams struct {
ProposalID int64
ProposalID uint64
Voter sdk.AccAddress
}
@ -111,7 +111,7 @@ func queryVote(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Kee
// Params for query 'custom/gov/deposits'
type QueryDepositsParams struct {
ProposalID int64
ProposalID uint64
}
// nolint: unparam
@ -139,7 +139,7 @@ func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper
// Params for query 'custom/gov/votes'
type QueryVotesParams struct {
ProposalID int64
ProposalID uint64
}
// nolint: unparam
@ -168,10 +168,10 @@ func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke
// Params for query 'custom/gov/proposals'
type QueryProposalsParams struct {
Voter sdk.AccAddress
Depositer sdk.AccAddress
ProposalStatus ProposalStatus
NumLatestProposals int64
Voter sdk.AccAddress
Depositer sdk.AccAddress
ProposalStatus ProposalStatus
Limit uint64
}
// nolint: unparam
@ -182,7 +182,7 @@ func queryProposals(ctx sdk.Context, path []string, req abci.RequestQuery, keepe
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err2.Error()))
}
proposals := keeper.GetProposalsFiltered(ctx, params.Voter, params.Depositer, params.ProposalStatus, params.NumLatestProposals)
proposals := keeper.GetProposalsFiltered(ctx, params.Voter, params.Depositer, params.ProposalStatus, params.Limit)
bz, err2 := codec.MarshalJSONIndent(keeper.cdc, proposals)
if err2 != nil {
@ -193,19 +193,21 @@ func queryProposals(ctx sdk.Context, path []string, req abci.RequestQuery, keepe
// Params for query 'custom/gov/tally'
type QueryTallyParams struct {
ProposalID int64
ProposalID uint64
}
// nolint: unparam
func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
// TODO: Dependant on #1914
var proposalID int64
err2 := keeper.cdc.UnmarshalJSON(req.Data, proposalID)
var params QueryTallyParams
err2 := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err2 != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err2.Error()))
}
proposalID := params.ProposalID
proposal := keeper.GetProposal(ctx, proposalID)
if proposal == nil {
return nil, ErrUnknownProposal(DefaultCodespace, proposalID)

View File

@ -50,7 +50,7 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe
if err != nil {
return "", nil, err
}
action, ok := simulateHandleMsgSubmitProposal(msg, sk, handler, ctx, event)
action, ok := simulateHandleMsgSubmitProposal(msg, handler, ctx, event)
// don't schedule votes if proposal failed
if !ok {
return action, nil, nil
@ -64,11 +64,11 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe
whoVotes := r.Perm(len(accs))
// didntVote := whoVotes[numVotes:]
whoVotes = whoVotes[:numVotes]
votingPeriod := k.GetVotingProcedure(ctx).VotingPeriod
votingPeriod := k.GetVotingParams(ctx).VotingPeriod
fops := make([]simulation.FutureOperation, numVotes+1)
for i := 0; i < numVotes; i++ {
whenVote := ctx.BlockHeader().Time.Add(time.Duration(r.Int63n(int64(votingPeriod.Seconds()))) * time.Second)
fops[i] = simulation.FutureOperation{BlockTime: whenVote, Op: operationSimulateMsgVote(k, sk, accs[whoVotes[i]], proposalID)}
fops[i] = simulation.FutureOperation{BlockTime: whenVote, Op: operationSimulateMsgVote(k, accs[whoVotes[i]], proposalID)}
}
// 3) Make an operation to ensure slashes were done correctly. (Really should be a future invariant)
// TODO: Find a way to check if a validator was slashed other than just checking their balance a block
@ -80,7 +80,7 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe
// SimulateMsgSubmitProposal simulates a msg Submit Proposal
// Note: Currently doesn't ensure that the proposal txt is in JSON form
func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operation {
func SimulateMsgSubmitProposal(k gov.Keeper) simulation.Operation {
handler := gov.NewHandler(k)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOps []simulation.FutureOperation, err error) {
sender := simulation.RandomAcc(r, accs)
@ -88,22 +88,14 @@ func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operati
if err != nil {
return "", nil, err
}
action, _ = simulateHandleMsgSubmitProposal(msg, sk, handler, ctx, event)
action, _ = simulateHandleMsgSubmitProposal(msg, handler, ctx, event)
return action, nil, nil
}
}
func simulateHandleMsgSubmitProposal(msg gov.MsgSubmitProposal, sk stake.Keeper, handler sdk.Handler, ctx sdk.Context, event func(string)) (action string, ok bool) {
ctx, write := ctx.CacheContext()
result := handler(ctx, msg)
ok = result.IsOK()
if ok {
// Update pool to keep invariants
pool := sk.GetPool(ctx)
pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewDecFromInt(msg.InitialDeposit.AmountOf(denom)))
sk.SetPool(ctx, pool)
write()
}
func simulateHandleMsgSubmitProposal(msg gov.MsgSubmitProposal, handler sdk.Handler, ctx sdk.Context, event func(string)) (action string, ok bool) {
ctx, _ = ctx.CacheContext()
handler(ctx, msg)
event(fmt.Sprintf("gov/MsgSubmitProposal/%v", ok))
action = fmt.Sprintf("TestMsgSubmitProposal: ok %v, msg %s", ok, msg.GetSignBytes())
return
@ -125,7 +117,7 @@ func simulationCreateMsgSubmitProposal(r *rand.Rand, sender simulation.Account)
}
// SimulateMsgDeposit
func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation {
func SimulateMsgDeposit(k gov.Keeper) simulation.Operation {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
acc := simulation.RandomAcc(r, accs)
proposalID, ok := randomProposalID(r, k, ctx)
@ -137,15 +129,8 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation {
if msg.ValidateBasic() != nil {
return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
}
ctx, write := ctx.CacheContext()
ctx, _ = ctx.CacheContext()
result := gov.NewHandler(k)(ctx, msg)
if result.IsOK() {
// Update pool to keep invariants
pool := sk.GetPool(ctx)
pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewDecFromInt(deposit.AmountOf(denom)))
sk.SetPool(ctx, pool)
write()
}
event(fmt.Sprintf("gov/MsgDeposit/%v", result.IsOK()))
action = fmt.Sprintf("TestMsgDeposit: ok %v, msg %s", result.IsOK(), msg.GetSignBytes())
return action, nil, nil
@ -154,12 +139,12 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation {
// SimulateMsgVote
// nolint: unparam
func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation {
return operationSimulateMsgVote(k, sk, simulation.Account{}, -1)
func SimulateMsgVote(k gov.Keeper) simulation.Operation {
return operationSimulateMsgVote(k, simulation.Account{}, 0)
}
// nolint: unparam
func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, acc simulation.Account, proposalID int64) simulation.Operation {
func operationSimulateMsgVote(k gov.Keeper, acc simulation.Account, proposalID uint64) simulation.Operation {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
if acc.Equals(simulation.Account{}) {
acc = simulation.RandomAcc(r, accs)
@ -200,12 +185,12 @@ func randomDeposit(r *rand.Rand) sdk.Coins {
}
// Pick a random proposal ID
func randomProposalID(r *rand.Rand, k gov.Keeper, ctx sdk.Context) (proposalID int64, ok bool) {
func randomProposalID(r *rand.Rand, k gov.Keeper, ctx sdk.Context) (proposalID uint64, ok bool) {
lastProposalID := k.GetLastProposalID(ctx)
if lastProposalID < 1 {
return 0, false
}
proposalID = int64(r.Intn(int(lastProposalID)))
proposalID = uint64(r.Intn(int(lastProposalID)))
return proposalID, true
}

View File

@ -59,9 +59,9 @@ func TestGovWithRandomMessages(t *testing.T) {
simulation.Simulate(
t, mapp.BaseApp, appStateFn,
[]simulation.WeightedOperation{
{2, SimulateMsgSubmitProposal(govKeeper, stakeKeeper)},
{3, SimulateMsgDeposit(govKeeper, stakeKeeper)},
{20, SimulateMsgVote(govKeeper, stakeKeeper)},
{2, SimulateMsgSubmitProposal(govKeeper)},
{3, SimulateMsgDeposit(govKeeper)},
{20, SimulateMsgVote(govKeeper)},
}, []simulation.RandSetup{
setup,
}, []simulation.Invariant{
@ -75,7 +75,7 @@ func TestGovWithRandomMessages(t *testing.T) {
t, mapp.BaseApp, appStateFn,
[]simulation.WeightedOperation{
{10, SimulateSubmittingVotingAndSlashingForProposal(govKeeper, stakeKeeper)},
{5, SimulateMsgDeposit(govKeeper, stakeKeeper)},
{5, SimulateMsgDeposit(govKeeper)},
}, []simulation.RandSetup{
setup,
}, []simulation.Invariant{

View File

@ -84,7 +84,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall
totalVotingPower = totalVotingPower.Add(votingPower)
}
tallyingProcedure := keeper.GetTallyingProcedure(ctx)
tallyParams := keeper.GetTallyParams(ctx)
tallyResults = TallyResult{
Yes: results[OptionYes],
@ -98,11 +98,11 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall
return false, tallyResults
}
// If more than 1/3 of voters veto, proposal fails
if results[OptionNoWithVeto].Quo(totalVotingPower).GT(tallyingProcedure.Veto) {
if results[OptionNoWithVeto].Quo(totalVotingPower).GT(tallyParams.Veto) {
return false, tallyResults
}
// If more than 1/2 of non-abstaining voters vote Yes, proposal passes
if results[OptionYes].Quo(totalVotingPower.Sub(results[OptionAbstain])).GT(tallyingProcedure.Threshold) {
if results[OptionYes].Quo(totalVotingPower.Sub(results[OptionAbstain])).GT(tallyParams.Threshold) {
return true, tallyResults
}
// If more than 1/2 of non-abstaining voters vote No, proposal fails