Merge PR #3779: Split Proposal Interface
This commit is contained in:
parent
8d6d8adb5f
commit
465bb02d6a
|
@ -680,7 +680,7 @@ func TestDeposit(t *testing.T) {
|
|||
// query proposal
|
||||
totalCoins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromTendermintPower(10))}
|
||||
proposal = getProposal(t, port, proposalID)
|
||||
require.True(t, proposal.GetTotalDeposit().IsEqual(totalCoins))
|
||||
require.True(t, proposal.TotalDeposit.IsEqual(totalCoins))
|
||||
|
||||
// query deposit
|
||||
deposit := getDeposit(t, port, proposalID, addr)
|
||||
|
@ -718,7 +718,7 @@ func TestVote(t *testing.T) {
|
|||
// query proposal
|
||||
proposal := getProposal(t, port, proposalID)
|
||||
require.Equal(t, "Test", proposal.GetTitle())
|
||||
require.Equal(t, gov.StatusVotingPeriod, proposal.GetStatus())
|
||||
require.Equal(t, gov.StatusVotingPeriod, proposal.Status)
|
||||
|
||||
// vote
|
||||
resultTx = doVote(t, port, seed, name1, pw, addr, proposalID, "Yes", fees)
|
||||
|
@ -855,13 +855,13 @@ func TestProposalsQuery(t *testing.T) {
|
|||
// Only proposals #1 should be in Deposit Period
|
||||
proposals := getProposalsFilterStatus(t, port, gov.StatusDepositPeriod)
|
||||
require.Len(t, proposals, 1)
|
||||
require.Equal(t, proposalID1, proposals[0].GetProposalID())
|
||||
require.Equal(t, proposalID1, proposals[0].ProposalID)
|
||||
|
||||
// Only proposals #2 and #3 should be in Voting Period
|
||||
proposals = getProposalsFilterStatus(t, port, gov.StatusVotingPeriod)
|
||||
require.Len(t, proposals, 2)
|
||||
require.Equal(t, proposalID2, proposals[0].GetProposalID())
|
||||
require.Equal(t, proposalID3, proposals[1].GetProposalID())
|
||||
require.Equal(t, proposalID2, proposals[0].ProposalID)
|
||||
require.Equal(t, proposalID3, proposals[1].ProposalID)
|
||||
|
||||
// Addr1 votes on proposals #2 & #3
|
||||
resultTx = doVote(t, port, seeds[0], names[0], passwords[0], addrs[0], proposalID2, "Yes", fees)
|
||||
|
@ -875,31 +875,31 @@ func TestProposalsQuery(t *testing.T) {
|
|||
|
||||
// Test query all proposals
|
||||
proposals = getProposalsAll(t, port)
|
||||
require.Equal(t, proposalID1, (proposals[0]).GetProposalID())
|
||||
require.Equal(t, proposalID2, (proposals[1]).GetProposalID())
|
||||
require.Equal(t, proposalID3, (proposals[2]).GetProposalID())
|
||||
require.Equal(t, proposalID1, (proposals[0]).ProposalID)
|
||||
require.Equal(t, proposalID2, (proposals[1]).ProposalID)
|
||||
require.Equal(t, proposalID3, (proposals[2]).ProposalID)
|
||||
|
||||
// Test query deposited by addr1
|
||||
proposals = getProposalsFilterDepositor(t, port, addrs[0])
|
||||
require.Equal(t, proposalID1, (proposals[0]).GetProposalID())
|
||||
require.Equal(t, proposalID1, (proposals[0]).ProposalID)
|
||||
|
||||
// Test query deposited by addr2
|
||||
proposals = getProposalsFilterDepositor(t, port, addrs[1])
|
||||
require.Equal(t, proposalID2, (proposals[0]).GetProposalID())
|
||||
require.Equal(t, proposalID3, (proposals[1]).GetProposalID())
|
||||
require.Equal(t, proposalID2, (proposals[0]).ProposalID)
|
||||
require.Equal(t, proposalID3, (proposals[1]).ProposalID)
|
||||
|
||||
// Test query voted by addr1
|
||||
proposals = getProposalsFilterVoter(t, port, addrs[0])
|
||||
require.Equal(t, proposalID2, (proposals[0]).GetProposalID())
|
||||
require.Equal(t, proposalID3, (proposals[1]).GetProposalID())
|
||||
require.Equal(t, proposalID2, (proposals[0]).ProposalID)
|
||||
require.Equal(t, proposalID3, (proposals[1]).ProposalID)
|
||||
|
||||
// Test query voted by addr2
|
||||
proposals = getProposalsFilterVoter(t, port, addrs[1])
|
||||
require.Equal(t, proposalID3, (proposals[0]).GetProposalID())
|
||||
require.Equal(t, proposalID3, (proposals[0]).ProposalID)
|
||||
|
||||
// Test query voted and deposited by addr1
|
||||
proposals = getProposalsFilterVoterDepositor(t, port, addrs[0], addrs[0])
|
||||
require.Equal(t, proposalID2, (proposals[0]).GetProposalID())
|
||||
require.Equal(t, proposalID2, (proposals[0]).ProposalID)
|
||||
|
||||
// Test query votes on Proposal 2
|
||||
votes := getVotes(t, port, proposalID2)
|
||||
|
|
|
@ -463,12 +463,12 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
|||
|
||||
// Ensure propsal is directly queryable
|
||||
proposal1 := f.QueryGovProposal(1)
|
||||
require.Equal(t, uint64(1), proposal1.GetProposalID())
|
||||
require.Equal(t, gov.StatusDepositPeriod, proposal1.GetStatus())
|
||||
require.Equal(t, uint64(1), proposal1.ProposalID)
|
||||
require.Equal(t, gov.StatusDepositPeriod, proposal1.Status)
|
||||
|
||||
// Ensure query proposals returns properly
|
||||
proposalsQuery = f.QueryGovProposals()
|
||||
require.Equal(t, uint64(1), proposalsQuery[0].GetProposalID())
|
||||
require.Equal(t, uint64(1), proposalsQuery[0].ProposalID)
|
||||
|
||||
// Query the deposits on the proposal
|
||||
deposit := f.QueryGovDeposit(1, fooAddr)
|
||||
|
@ -507,8 +507,8 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
|||
|
||||
// Fetch the proposal and ensure it is now in the voting period
|
||||
proposal1 = f.QueryGovProposal(1)
|
||||
require.Equal(t, uint64(1), proposal1.GetProposalID())
|
||||
require.Equal(t, gov.StatusVotingPeriod, proposal1.GetStatus())
|
||||
require.Equal(t, uint64(1), proposal1.ProposalID)
|
||||
require.Equal(t, gov.StatusVotingPeriod, proposal1.Status)
|
||||
|
||||
// Test vote generate only
|
||||
success, stdout, stderr = f.TxGovVote(1, gov.OptionYes, keyFoo, "--generate-only")
|
||||
|
@ -544,7 +544,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
|||
|
||||
// Ensure the proposal returns as in the voting period
|
||||
proposalsQuery = f.QueryGovProposals("--status=VotingPeriod")
|
||||
require.Equal(t, uint64(1), proposalsQuery[0].GetProposalID())
|
||||
require.Equal(t, uint64(1), proposalsQuery[0].ProposalID)
|
||||
|
||||
// submit a second test proposal
|
||||
f.TxGovSubmitProposal(keyFoo, "Text", "Apples", "test", sdk.NewCoin(denom, proposalTokens), "-y")
|
||||
|
@ -552,7 +552,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
|||
|
||||
// Test limit on proposals query
|
||||
proposalsQuery = f.QueryGovProposals("--limit=1")
|
||||
require.Equal(t, uint64(2), proposalsQuery[0].GetProposalID())
|
||||
require.Equal(t, uint64(2), proposalsQuery[0].ProposalID)
|
||||
|
||||
f.Cleanup()
|
||||
}
|
||||
|
|
|
@ -84,13 +84,11 @@ This type is used in a temp map when tallying
|
|||
|
||||
## Proposals
|
||||
|
||||
`Proposals` are an item to be voted on.
|
||||
`Proposals` are an item to be voted on. It contains the `ProposalContent` which denotes what this proposal is about, and the other fields, which are the mutable state of the governance process.
|
||||
|
||||
```go
|
||||
type Proposal struct {
|
||||
Title string // Title of the proposal
|
||||
Description string // Description of the proposal
|
||||
Type ProposalType // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal}
|
||||
ProposalContent // Proposal content interface
|
||||
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
|
||||
|
@ -108,6 +106,17 @@ type Proposal struct {
|
|||
}
|
||||
```
|
||||
|
||||
`ProposalContent`s are an interface which contains the information about the `Proposal` where it is provided from an external source, including the proposer. Governance process itself does not evaluate about the internal content.
|
||||
|
||||
```go
|
||||
type ProposalContent interface {
|
||||
GetTitle() string
|
||||
GetDescription() string
|
||||
ProposalType() ProposalKind
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
We also mention a method to update the tally for a given proposal:
|
||||
|
||||
```go
|
||||
|
|
|
@ -226,7 +226,7 @@ $ gaiacli query gov votes 1
|
|||
var proposal gov.Proposal
|
||||
cdc.MustUnmarshalJSON(res, &proposal)
|
||||
|
||||
propStatus := proposal.GetStatus()
|
||||
propStatus := proposal.Status
|
||||
if !(propStatus == gov.StatusVotingPeriod || propStatus == gov.StatusDepositPeriod) {
|
||||
res, err = gcutils.QueryVotesByTxQuery(cdc, cliCtx, params)
|
||||
} else {
|
||||
|
@ -339,7 +339,7 @@ $ gaiacli query gov deposits 1
|
|||
var proposal gov.Proposal
|
||||
cdc.MustUnmarshalJSON(res, &proposal)
|
||||
|
||||
propStatus := proposal.GetStatus()
|
||||
propStatus := proposal.Status
|
||||
if !(propStatus == gov.StatusVotingPeriod || propStatus == gov.StatusDepositPeriod) {
|
||||
res, err = gcutils.QueryDepositsByTxQuery(cdc, cliCtx, params)
|
||||
} else {
|
||||
|
|
|
@ -266,7 +266,7 @@ func queryDepositsHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Ha
|
|||
|
||||
// For inactive proposals we must query the txs directly to get the deposits
|
||||
// as they're no longer in state.
|
||||
propStatus := proposal.GetStatus()
|
||||
propStatus := proposal.Status
|
||||
if !(propStatus == gov.StatusVotingPeriod || propStatus == gov.StatusDepositPeriod) {
|
||||
res, err = gcutils.QueryDepositsByTxQuery(cdc, cliCtx, params)
|
||||
} else {
|
||||
|
@ -489,7 +489,7 @@ func queryVotesOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext)
|
|||
|
||||
// For inactive proposals we must query the txs directly to get the votes
|
||||
// as they're no longer in state.
|
||||
propStatus := proposal.GetStatus()
|
||||
propStatus := proposal.Status
|
||||
if !(propStatus == gov.StatusVotingPeriod || propStatus == gov.StatusDepositPeriod) {
|
||||
res, err = gcutils.QueryVotesByTxQuery(cdc, cliCtx, params)
|
||||
} else {
|
||||
|
|
|
@ -12,8 +12,9 @@ func RegisterCodec(cdc *codec.Codec) {
|
|||
cdc.RegisterConcrete(MsgDeposit{}, "cosmos-sdk/MsgDeposit", nil)
|
||||
cdc.RegisterConcrete(MsgVote{}, "cosmos-sdk/MsgVote", nil)
|
||||
|
||||
cdc.RegisterInterface((*Proposal)(nil), nil)
|
||||
cdc.RegisterConcrete(&TextProposal{}, "gov/TextProposal", nil)
|
||||
cdc.RegisterInterface((*ProposalContent)(nil), nil)
|
||||
cdc.RegisterConcrete(TextProposal{}, "gov/TextProposal", nil)
|
||||
cdc.RegisterConcrete(SoftwareUpgradeProposal{}, "gov/SoftwareUpgradeProposal", nil)
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -18,7 +18,10 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) sdk.Tags {
|
|||
var proposalID uint64
|
||||
|
||||
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(inactiveIterator.Value(), &proposalID)
|
||||
inactiveProposal := keeper.GetProposal(ctx, proposalID)
|
||||
inactiveProposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("proposal %d does not exist", proposalID))
|
||||
}
|
||||
|
||||
keeper.DeleteProposal(ctx, proposalID)
|
||||
keeper.DeleteDeposits(ctx, proposalID) // delete any associated deposits (burned)
|
||||
|
@ -28,10 +31,10 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) sdk.Tags {
|
|||
|
||||
logger.Info(
|
||||
fmt.Sprintf("proposal %d (%s) didn't meet minimum deposit of %s (had only %s); deleted",
|
||||
inactiveProposal.GetProposalID(),
|
||||
inactiveProposal.ProposalID,
|
||||
inactiveProposal.GetTitle(),
|
||||
keeper.GetDepositParams(ctx).MinDeposit,
|
||||
inactiveProposal.GetTotalDeposit(),
|
||||
inactiveProposal.TotalDeposit,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -43,28 +46,31 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) sdk.Tags {
|
|||
var proposalID uint64
|
||||
|
||||
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(activeIterator.Value(), &proposalID)
|
||||
activeProposal := keeper.GetProposal(ctx, proposalID)
|
||||
activeProposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("proposal %d does not exist", proposalID))
|
||||
}
|
||||
passes, tallyResults := tally(ctx, keeper, activeProposal)
|
||||
|
||||
var tagValue string
|
||||
if passes {
|
||||
keeper.RefundDeposits(ctx, activeProposal.GetProposalID())
|
||||
activeProposal.SetStatus(StatusPassed)
|
||||
keeper.RefundDeposits(ctx, activeProposal.ProposalID)
|
||||
activeProposal.Status = StatusPassed
|
||||
tagValue = tags.ActionProposalPassed
|
||||
} else {
|
||||
keeper.DeleteDeposits(ctx, activeProposal.GetProposalID())
|
||||
activeProposal.SetStatus(StatusRejected)
|
||||
keeper.DeleteDeposits(ctx, activeProposal.ProposalID)
|
||||
activeProposal.Status = StatusRejected
|
||||
tagValue = tags.ActionProposalRejected
|
||||
}
|
||||
|
||||
activeProposal.SetFinalTallyResult(tallyResults)
|
||||
activeProposal.FinalTallyResult = tallyResults
|
||||
keeper.SetProposal(ctx, activeProposal)
|
||||
keeper.RemoveFromActiveProposalQueue(ctx, activeProposal.GetVotingEndTime(), activeProposal.GetProposalID())
|
||||
keeper.RemoveFromActiveProposalQueue(ctx, activeProposal.VotingEndTime, activeProposal.ProposalID)
|
||||
|
||||
logger.Info(
|
||||
fmt.Sprintf(
|
||||
"proposal %d (%s) tallied; passed: %v",
|
||||
activeProposal.GetProposalID(), activeProposal.GetTitle(), passes,
|
||||
activeProposal.ProposalID, activeProposal.GetTitle(), passes,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
@ -208,7 +208,9 @@ func TestTickPassedVotingPeriod(t *testing.T) {
|
|||
require.True(t, activeQueue.Valid())
|
||||
var activeProposalID uint64
|
||||
keeper.cdc.UnmarshalBinaryLengthPrefixed(activeQueue.Value(), &activeProposalID)
|
||||
require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, activeProposalID).GetStatus())
|
||||
proposal, ok := keeper.GetProposal(ctx, activeProposalID)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, StatusVotingPeriod, proposal.Status)
|
||||
depositsIterator := keeper.GetDeposits(ctx, proposalID)
|
||||
require.True(t, depositsIterator.Valid())
|
||||
depositsIterator.Close()
|
||||
|
|
|
@ -122,11 +122,11 @@ func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) {
|
|||
k.setVote(ctx, vote.ProposalID, vote.Vote.Voter, vote.Vote)
|
||||
}
|
||||
for _, proposal := range data.Proposals {
|
||||
switch proposal.GetStatus() {
|
||||
switch proposal.Status {
|
||||
case StatusDepositPeriod:
|
||||
k.InsertInactiveProposalQueue(ctx, proposal.GetDepositEndTime(), proposal.GetProposalID())
|
||||
k.InsertInactiveProposalQueue(ctx, proposal.DepositEndTime, proposal.ProposalID)
|
||||
case StatusVotingPeriod:
|
||||
k.InsertActiveProposalQueue(ctx, proposal.GetVotingEndTime(), proposal.GetProposalID())
|
||||
k.InsertActiveProposalQueue(ctx, proposal.VotingEndTime, proposal.ProposalID)
|
||||
}
|
||||
k.SetProposal(ctx, proposal)
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ func ExportGenesis(ctx sdk.Context, k Keeper) GenesisState {
|
|||
var votes []VoteWithMetadata
|
||||
proposals := k.GetProposalsFiltered(ctx, nil, nil, StatusNil, 0)
|
||||
for _, proposal := range proposals {
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposalID := proposal.ProposalID
|
||||
depositsIterator := k.GetDeposits(ctx, proposalID)
|
||||
defer depositsIterator.Close()
|
||||
for ; depositsIterator.Valid(); depositsIterator.Next() {
|
||||
|
|
|
@ -33,9 +33,12 @@ func TestEqualProposals(t *testing.T) {
|
|||
|
||||
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
||||
|
||||
// Create two proposals
|
||||
proposal1 := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposal2 := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
// Submit two proposals
|
||||
proposal := testProposal()
|
||||
proposal1, err := keeper.SubmitProposal(ctx, proposal)
|
||||
require.NoError(t, err)
|
||||
proposal2, err := keeper.SubmitProposal(ctx, proposal)
|
||||
require.NoError(t, err)
|
||||
|
||||
// They are similar but their IDs should be different
|
||||
require.NotEqual(t, proposal1, proposal2)
|
||||
|
@ -48,11 +51,15 @@ func TestEqualProposals(t *testing.T) {
|
|||
require.False(t, state1.Equal(state2))
|
||||
|
||||
// Now make proposals identical by setting both IDs to 55
|
||||
proposal1.SetProposalID(55)
|
||||
proposal2.SetProposalID(55)
|
||||
proposal1.ProposalID = 55
|
||||
proposal2.ProposalID = 55
|
||||
require.Equal(t, proposal1, proposal1)
|
||||
require.True(t, ProposalEqual(proposal1, proposal2))
|
||||
|
||||
// Reassign proposals into state
|
||||
state1.Proposals[0] = proposal1
|
||||
state2.Proposals[0] = proposal2
|
||||
|
||||
// State should be identical now..
|
||||
require.Equal(t, state1, state2)
|
||||
require.True(t, state1.Equal(state2))
|
||||
|
@ -69,17 +76,24 @@ func TestImportExportQueues(t *testing.T) {
|
|||
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
||||
|
||||
// Create two proposals, put the second into the voting period
|
||||
proposal1 := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID1 := proposal1.GetProposalID()
|
||||
proposal := testProposal()
|
||||
proposal1, err := keeper.SubmitProposal(ctx, proposal)
|
||||
require.NoError(t, err)
|
||||
proposalID1 := proposal1.ProposalID
|
||||
|
||||
proposal2 := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID2 := proposal2.GetProposalID()
|
||||
proposal2, err := keeper.SubmitProposal(ctx, proposal)
|
||||
require.NoError(t, err)
|
||||
proposalID2 := proposal2.ProposalID
|
||||
|
||||
_, votingStarted := keeper.AddDeposit(ctx, proposalID2, addrs[0], keeper.GetDepositParams(ctx).MinDeposit)
|
||||
require.True(t, votingStarted)
|
||||
|
||||
require.True(t, keeper.GetProposal(ctx, proposalID1).GetStatus() == StatusDepositPeriod)
|
||||
require.True(t, keeper.GetProposal(ctx, proposalID2).GetStatus() == StatusVotingPeriod)
|
||||
proposal1, ok := keeper.GetProposal(ctx, proposalID1)
|
||||
require.True(t, ok)
|
||||
proposal2, ok = keeper.GetProposal(ctx, proposalID2)
|
||||
require.True(t, ok)
|
||||
require.True(t, proposal1.Status == StatusDepositPeriod)
|
||||
require.True(t, proposal2.Status == StatusVotingPeriod)
|
||||
|
||||
genAccs := mapp.AccountKeeper.GetAllAccounts(ctx)
|
||||
|
||||
|
@ -96,12 +110,19 @@ func TestImportExportQueues(t *testing.T) {
|
|||
ctx2 = ctx2.WithBlockTime(ctx2.BlockHeader().Time.Add(keeper2.GetDepositParams(ctx2).MaxDepositPeriod).Add(keeper2.GetVotingParams(ctx2).VotingPeriod))
|
||||
|
||||
// Make sure that they are still in the DepositPeriod and VotingPeriod respectively
|
||||
require.True(t, keeper2.GetProposal(ctx2, proposalID1).GetStatus() == StatusDepositPeriod)
|
||||
require.True(t, keeper2.GetProposal(ctx2, proposalID2).GetStatus() == StatusVotingPeriod)
|
||||
proposal1, ok = keeper2.GetProposal(ctx2, proposalID1)
|
||||
require.True(t, ok)
|
||||
proposal2, ok = keeper2.GetProposal(ctx2, proposalID2)
|
||||
require.True(t, ok)
|
||||
require.True(t, proposal1.Status == StatusDepositPeriod)
|
||||
require.True(t, proposal2.Status == StatusVotingPeriod)
|
||||
|
||||
// Run the endblocker. Check to make sure that proposal1 is removed from state, and proposal2 is finished VotingPeriod.
|
||||
EndBlocker(ctx2, keeper2)
|
||||
|
||||
require.Nil(t, keeper2.GetProposal(ctx2, proposalID1))
|
||||
require.True(t, keeper2.GetProposal(ctx2, proposalID2).GetStatus() == StatusRejected)
|
||||
proposal1, ok = keeper2.GetProposal(ctx2, proposalID1)
|
||||
require.False(t, ok)
|
||||
proposal2, ok = keeper2.GetProposal(ctx2, proposalID2)
|
||||
require.True(t, ok)
|
||||
require.True(t, proposal2.Status == StatusRejected)
|
||||
}
|
||||
|
|
|
@ -25,8 +25,20 @@ func NewHandler(keeper Keeper) sdk.Handler {
|
|||
}
|
||||
|
||||
func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitProposal) sdk.Result {
|
||||
proposal := keeper.NewTextProposal(ctx, msg.Title, msg.Description, msg.ProposalType)
|
||||
proposalID := proposal.GetProposalID()
|
||||
var content ProposalContent
|
||||
switch msg.ProposalType {
|
||||
case ProposalTypeText:
|
||||
content = NewTextProposal(msg.Title, msg.Description)
|
||||
case ProposalTypeSoftwareUpgrade:
|
||||
content = NewSoftwareUpgradeProposal(msg.Title, msg.Description)
|
||||
default:
|
||||
return ErrInvalidProposalType(keeper.codespace, msg.ProposalType).Result()
|
||||
}
|
||||
proposal, err := keeper.SubmitProposal(ctx, content)
|
||||
if err != nil {
|
||||
return err.Result()
|
||||
}
|
||||
proposalID := proposal.ProposalID
|
||||
proposalIDStr := fmt.Sprintf("%d", proposalID)
|
||||
|
||||
err, votingStarted := keeper.AddDeposit(ctx, proposalID, msg.Proposer, msg.InitialDeposit)
|
||||
|
|
|
@ -95,57 +95,58 @@ func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, paramsKeeper params.Keeper,
|
|||
}
|
||||
|
||||
// Proposals
|
||||
|
||||
// Creates a NewProposal
|
||||
func (keeper Keeper) NewTextProposal(ctx sdk.Context, title string, description string, proposalType ProposalKind) Proposal {
|
||||
func (keeper Keeper) SubmitProposal(ctx sdk.Context, content ProposalContent) (proposal Proposal, err sdk.Error) {
|
||||
proposalID, err := keeper.getNewProposalID(ctx)
|
||||
if err != nil {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
var proposal Proposal = &TextProposal{
|
||||
ProposalID: proposalID,
|
||||
Title: title,
|
||||
Description: description,
|
||||
ProposalType: proposalType,
|
||||
|
||||
submitTime := ctx.BlockHeader().Time
|
||||
depositPeriod := keeper.GetDepositParams(ctx).MaxDepositPeriod
|
||||
|
||||
proposal = Proposal{
|
||||
ProposalContent: content,
|
||||
ProposalID: proposalID,
|
||||
|
||||
Status: StatusDepositPeriod,
|
||||
FinalTallyResult: EmptyTallyResult(),
|
||||
TotalDeposit: sdk.NewCoins(),
|
||||
SubmitTime: ctx.BlockHeader().Time,
|
||||
SubmitTime: submitTime,
|
||||
DepositEndTime: submitTime.Add(depositPeriod),
|
||||
}
|
||||
|
||||
depositPeriod := keeper.GetDepositParams(ctx).MaxDepositPeriod
|
||||
proposal.SetDepositEndTime(proposal.GetSubmitTime().Add(depositPeriod))
|
||||
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
keeper.InsertInactiveProposalQueue(ctx, proposal.GetDepositEndTime(), proposalID)
|
||||
return proposal
|
||||
keeper.InsertInactiveProposalQueue(ctx, proposal.DepositEndTime, proposalID)
|
||||
return
|
||||
}
|
||||
|
||||
// Get Proposal from store by ProposalID
|
||||
func (keeper Keeper) GetProposal(ctx sdk.Context, proposalID uint64) Proposal {
|
||||
func (keeper Keeper) GetProposal(ctx sdk.Context, proposalID uint64) (proposal Proposal, ok bool) {
|
||||
store := ctx.KVStore(keeper.storeKey)
|
||||
bz := store.Get(KeyProposal(proposalID))
|
||||
if bz == nil {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
var proposal Proposal
|
||||
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposal)
|
||||
return proposal
|
||||
return proposal, true
|
||||
}
|
||||
|
||||
// Implements sdk.AccountKeeper.
|
||||
func (keeper Keeper) SetProposal(ctx sdk.Context, proposal Proposal) {
|
||||
store := ctx.KVStore(keeper.storeKey)
|
||||
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposal)
|
||||
store.Set(KeyProposal(proposal.GetProposalID()), bz)
|
||||
store.Set(KeyProposal(proposal.ProposalID), bz)
|
||||
}
|
||||
|
||||
// Implements sdk.AccountKeeper.
|
||||
func (keeper Keeper) DeleteProposal(ctx sdk.Context, proposalID uint64) {
|
||||
store := ctx.KVStore(keeper.storeKey)
|
||||
proposal := keeper.GetProposal(ctx, proposalID)
|
||||
keeper.RemoveFromInactiveProposalQueue(ctx, proposal.GetDepositEndTime(), proposalID)
|
||||
keeper.RemoveFromActiveProposalQueue(ctx, proposal.GetVotingEndTime(), proposalID)
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
if !ok {
|
||||
panic("DeleteProposal cannot fail to GetProposal")
|
||||
}
|
||||
keeper.RemoveFromInactiveProposalQueue(ctx, proposal.DepositEndTime, proposalID)
|
||||
keeper.RemoveFromActiveProposalQueue(ctx, proposal.VotingEndTime, proposalID)
|
||||
store.Delete(KeyProposal(proposalID))
|
||||
}
|
||||
|
||||
|
@ -182,13 +183,13 @@ func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddr
|
|||
}
|
||||
}
|
||||
|
||||
proposal := keeper.GetProposal(ctx, proposalID)
|
||||
if proposal == nil {
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if validProposalStatus(status) {
|
||||
if proposal.GetStatus() != status {
|
||||
if proposal.Status != status {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -245,14 +246,14 @@ func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID uint64,
|
|||
}
|
||||
|
||||
func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) {
|
||||
proposal.SetVotingStartTime(ctx.BlockHeader().Time)
|
||||
proposal.VotingStartTime = ctx.BlockHeader().Time
|
||||
votingPeriod := keeper.GetVotingParams(ctx).VotingPeriod
|
||||
proposal.SetVotingEndTime(proposal.GetVotingStartTime().Add(votingPeriod))
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
proposal.VotingEndTime = proposal.VotingStartTime.Add(votingPeriod)
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
keeper.RemoveFromInactiveProposalQueue(ctx, proposal.GetDepositEndTime(), proposal.GetProposalID())
|
||||
keeper.InsertActiveProposalQueue(ctx, proposal.GetVotingEndTime(), proposal.GetProposalID())
|
||||
keeper.RemoveFromInactiveProposalQueue(ctx, proposal.DepositEndTime, proposal.ProposalID)
|
||||
keeper.InsertActiveProposalQueue(ctx, proposal.VotingEndTime, proposal.ProposalID)
|
||||
}
|
||||
|
||||
// Params
|
||||
|
@ -294,11 +295,11 @@ func (keeper Keeper) setTallyParams(ctx sdk.Context, tallyParams TallyParams) {
|
|||
|
||||
// Adds a vote on a specific proposal
|
||||
func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, option VoteOption) sdk.Error {
|
||||
proposal := keeper.GetProposal(ctx, proposalID)
|
||||
if proposal == nil {
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
if !ok {
|
||||
return ErrUnknownProposal(keeper.codespace, proposalID)
|
||||
}
|
||||
if proposal.GetStatus() != StatusVotingPeriod {
|
||||
if proposal.Status != StatusVotingPeriod {
|
||||
return ErrInactiveProposal(keeper.codespace, proposalID)
|
||||
}
|
||||
|
||||
|
@ -369,13 +370,13 @@ func (keeper Keeper) setDeposit(ctx sdk.Context, proposalID uint64, depositorAdd
|
|||
// Activates voting period when appropriate
|
||||
func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress, depositAmount sdk.Coins) (sdk.Error, bool) {
|
||||
// Checks to see if proposal exists
|
||||
proposal := keeper.GetProposal(ctx, proposalID)
|
||||
if proposal == nil {
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
if !ok {
|
||||
return ErrUnknownProposal(keeper.codespace, proposalID), false
|
||||
}
|
||||
|
||||
// Check if proposal is still depositable
|
||||
if (proposal.GetStatus() != StatusDepositPeriod) && (proposal.GetStatus() != StatusVotingPeriod) {
|
||||
if (proposal.Status != StatusDepositPeriod) && (proposal.Status != StatusVotingPeriod) {
|
||||
return ErrAlreadyFinishedProposal(keeper.codespace, proposalID), false
|
||||
}
|
||||
|
||||
|
@ -387,12 +388,12 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAdd
|
|||
}
|
||||
|
||||
// Update proposal
|
||||
proposal.SetTotalDeposit(proposal.GetTotalDeposit().Add(depositAmount))
|
||||
proposal.TotalDeposit = proposal.TotalDeposit.Add(depositAmount)
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
// Check if deposit has provided sufficient total funds to transition the proposal into the voting period
|
||||
activatedVotingPeriod := false
|
||||
if proposal.GetStatus() == StatusDepositPeriod && proposal.GetTotalDeposit().IsAllGTE(keeper.GetDepositParams(ctx).MinDeposit) {
|
||||
if proposal.Status == StatusDepositPeriod && proposal.TotalDeposit.IsAllGTE(keeper.GetDepositParams(ctx).MinDeposit) {
|
||||
keeper.activateVotingPeriod(ctx, proposal)
|
||||
activatedVotingPeriod = true
|
||||
}
|
||||
|
|
|
@ -19,11 +19,14 @@ func TestGetSetProposal(t *testing.T) {
|
|||
|
||||
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
tp := testProposal()
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
gotProposal := keeper.GetProposal(ctx, proposalID)
|
||||
gotProposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
require.True(t, ProposalEqual(proposal, gotProposal))
|
||||
}
|
||||
|
||||
|
@ -35,14 +38,16 @@ func TestIncrementProposalNumber(t *testing.T) {
|
|||
|
||||
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
||||
|
||||
keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposal6 := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
tp := testProposal()
|
||||
keeper.SubmitProposal(ctx, tp)
|
||||
keeper.SubmitProposal(ctx, tp)
|
||||
keeper.SubmitProposal(ctx, tp)
|
||||
keeper.SubmitProposal(ctx, tp)
|
||||
keeper.SubmitProposal(ctx, tp)
|
||||
proposal6, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, uint64(6), proposal6.GetProposalID())
|
||||
require.Equal(t, uint64(6), proposal6.ProposalID)
|
||||
}
|
||||
|
||||
func TestActivateVotingPeriod(t *testing.T) {
|
||||
|
@ -52,19 +57,25 @@ func TestActivateVotingPeriod(t *testing.T) {
|
|||
mapp.BeginBlock(abci.RequestBeginBlock{Header: header})
|
||||
|
||||
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
|
||||
require.True(t, proposal.GetVotingStartTime().Equal(time.Time{}))
|
||||
tp := testProposal()
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.True(t, proposal.VotingStartTime.Equal(time.Time{}))
|
||||
|
||||
keeper.activateVotingPeriod(ctx, proposal)
|
||||
|
||||
require.True(t, proposal.GetVotingStartTime().Equal(ctx.BlockHeader().Time))
|
||||
require.True(t, proposal.VotingStartTime.Equal(ctx.BlockHeader().Time))
|
||||
|
||||
activeIterator := keeper.ActiveProposalQueueIterator(ctx, proposal.GetVotingEndTime())
|
||||
proposal, ok := keeper.GetProposal(ctx, proposal.ProposalID)
|
||||
require.True(t, ok)
|
||||
|
||||
activeIterator := keeper.ActiveProposalQueueIterator(ctx, proposal.VotingEndTime)
|
||||
require.True(t, activeIterator.Valid())
|
||||
var proposalID uint64
|
||||
keeper.cdc.UnmarshalBinaryLengthPrefixed(activeIterator.Value(), &proposalID)
|
||||
require.Equal(t, proposalID, proposal.GetProposalID())
|
||||
require.Equal(t, proposalID, proposal.ProposalID)
|
||||
activeIterator.Close()
|
||||
}
|
||||
|
||||
|
@ -76,8 +87,11 @@ func TestDeposits(t *testing.T) {
|
|||
mapp.BeginBlock(abci.RequestBeginBlock{Header: header})
|
||||
|
||||
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
|
||||
tp := testProposal()
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
|
||||
fourStake := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromTendermintPower(4)))
|
||||
fiveStake := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromTendermintPower(5)))
|
||||
|
@ -87,12 +101,14 @@ func TestDeposits(t *testing.T) {
|
|||
|
||||
expTokens := sdk.TokensFromTendermintPower(42)
|
||||
require.Equal(t, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, expTokens)), addr0Initial)
|
||||
require.True(t, proposal.GetTotalDeposit().IsEqual(sdk.NewCoins()))
|
||||
require.True(t, proposal.TotalDeposit.IsEqual(sdk.NewCoins()))
|
||||
|
||||
// Check no deposits at beginning
|
||||
deposit, found := keeper.GetDeposit(ctx, proposalID, addrs[1])
|
||||
require.False(t, found)
|
||||
require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(time.Time{}))
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
require.True(t, proposal.VotingStartTime.Equal(time.Time{}))
|
||||
|
||||
// Check first deposit
|
||||
err, votingStarted := keeper.AddDeposit(ctx, proposalID, addrs[0], fourStake)
|
||||
|
@ -102,7 +118,9 @@ func TestDeposits(t *testing.T) {
|
|||
require.True(t, found)
|
||||
require.Equal(t, fourStake, deposit.Amount)
|
||||
require.Equal(t, addrs[0], deposit.Depositor)
|
||||
require.Equal(t, fourStake, keeper.GetProposal(ctx, proposalID).GetTotalDeposit())
|
||||
proposal, ok = keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, fourStake, proposal.TotalDeposit)
|
||||
require.Equal(t, addr0Initial.Sub(fourStake), keeper.ck.GetCoins(ctx, addrs[0]))
|
||||
|
||||
// Check a second deposit from same address
|
||||
|
@ -113,7 +131,9 @@ func TestDeposits(t *testing.T) {
|
|||
require.True(t, found)
|
||||
require.Equal(t, fourStake.Add(fiveStake), deposit.Amount)
|
||||
require.Equal(t, addrs[0], deposit.Depositor)
|
||||
require.Equal(t, fourStake.Add(fiveStake), keeper.GetProposal(ctx, proposalID).GetTotalDeposit())
|
||||
proposal, ok = keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, fourStake.Add(fiveStake), proposal.TotalDeposit)
|
||||
require.Equal(t, addr0Initial.Sub(fourStake).Sub(fiveStake), keeper.ck.GetCoins(ctx, addrs[0]))
|
||||
|
||||
// Check third deposit from a new address
|
||||
|
@ -124,11 +144,15 @@ func TestDeposits(t *testing.T) {
|
|||
require.True(t, found)
|
||||
require.Equal(t, addrs[1], deposit.Depositor)
|
||||
require.Equal(t, fourStake, deposit.Amount)
|
||||
require.Equal(t, fourStake.Add(fiveStake).Add(fourStake), keeper.GetProposal(ctx, proposalID).GetTotalDeposit())
|
||||
proposal, ok = keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, fourStake.Add(fiveStake).Add(fourStake), proposal.TotalDeposit)
|
||||
require.Equal(t, addr1Initial.Sub(fourStake), keeper.ck.GetCoins(ctx, addrs[1]))
|
||||
|
||||
// Check that proposal moved to voting period
|
||||
require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(ctx.BlockHeader().Time))
|
||||
proposal, ok = keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
require.True(t, proposal.VotingStartTime.Equal(ctx.BlockHeader().Time))
|
||||
|
||||
// Test deposit iterator
|
||||
depositsIterator := keeper.GetDeposits(ctx, proposalID)
|
||||
|
@ -164,10 +188,13 @@ func TestVotes(t *testing.T) {
|
|||
mapp.BeginBlock(abci.RequestBeginBlock{Header: header})
|
||||
|
||||
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
tp := testProposal()
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
// Test first vote
|
||||
|
@ -224,20 +251,25 @@ func TestProposalQueues(t *testing.T) {
|
|||
mapp.InitChainer(ctx, abci.RequestInitChain{})
|
||||
|
||||
// create test proposals
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
tp := testProposal()
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
|
||||
inactiveIterator := keeper.InactiveProposalQueueIterator(ctx, proposal.GetDepositEndTime())
|
||||
inactiveIterator := keeper.InactiveProposalQueueIterator(ctx, proposal.DepositEndTime)
|
||||
require.True(t, inactiveIterator.Valid())
|
||||
var proposalID uint64
|
||||
keeper.cdc.UnmarshalBinaryLengthPrefixed(inactiveIterator.Value(), &proposalID)
|
||||
require.Equal(t, proposalID, proposal.GetProposalID())
|
||||
require.Equal(t, proposalID, proposal.ProposalID)
|
||||
inactiveIterator.Close()
|
||||
|
||||
keeper.activateVotingPeriod(ctx, proposal)
|
||||
|
||||
activeIterator := keeper.ActiveProposalQueueIterator(ctx, proposal.GetVotingEndTime())
|
||||
proposal, ok := keeper.GetProposal(ctx, proposal.ProposalID)
|
||||
require.True(t, ok)
|
||||
|
||||
activeIterator := keeper.ActiveProposalQueueIterator(ctx, proposal.VotingEndTime)
|
||||
require.True(t, activeIterator.Valid())
|
||||
keeper.cdc.UnmarshalBinaryLengthPrefixed(activeIterator.Value(), &proposalID)
|
||||
require.Equal(t, proposalID, proposal.GetProposalID())
|
||||
require.Equal(t, proposalID, proposal.ProposalID)
|
||||
activeIterator.Close()
|
||||
}
|
||||
|
|
|
@ -9,81 +9,12 @@ import (
|
|||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// Proposal interface
|
||||
type Proposal interface {
|
||||
GetProposalID() uint64
|
||||
SetProposalID(uint64)
|
||||
// Proposal is a struct used by gov module internally
|
||||
// embedds ProposalContent with additional fields to record the status of the proposal process
|
||||
type Proposal struct {
|
||||
ProposalContent `json:"proposal_content"` // Proposal content interface
|
||||
|
||||
GetTitle() string
|
||||
SetTitle(string)
|
||||
|
||||
GetDescription() string
|
||||
SetDescription(string)
|
||||
|
||||
GetProposalType() ProposalKind
|
||||
SetProposalType(ProposalKind)
|
||||
|
||||
GetStatus() ProposalStatus
|
||||
SetStatus(ProposalStatus)
|
||||
|
||||
GetFinalTallyResult() TallyResult
|
||||
SetFinalTallyResult(TallyResult)
|
||||
|
||||
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)
|
||||
|
||||
String() string
|
||||
}
|
||||
|
||||
// Proposals is an array of proposal
|
||||
type Proposals []Proposal
|
||||
|
||||
func (p Proposals) String() string {
|
||||
out := "ID - (Status) [Type] Title\n"
|
||||
for _, prop := range p {
|
||||
out += fmt.Sprintf("%d - (%s) [%s] %s\n",
|
||||
prop.GetProposalID(), prop.GetStatus(),
|
||||
prop.GetProposalType(), prop.GetTitle())
|
||||
}
|
||||
return strings.TrimSpace(out)
|
||||
}
|
||||
|
||||
// checks if two proposals are equal
|
||||
func ProposalEqual(proposalA Proposal, proposalB Proposal) bool {
|
||||
if proposalA.GetProposalID() == proposalB.GetProposalID() &&
|
||||
proposalA.GetTitle() == proposalB.GetTitle() &&
|
||||
proposalA.GetDescription() == proposalB.GetDescription() &&
|
||||
proposalA.GetProposalType() == proposalB.GetProposalType() &&
|
||||
proposalA.GetStatus() == proposalB.GetStatus() &&
|
||||
proposalA.GetFinalTallyResult().Equals(proposalB.GetFinalTallyResult()) &&
|
||||
proposalA.GetSubmitTime().Equal(proposalB.GetSubmitTime()) &&
|
||||
proposalA.GetDepositEndTime().Equal(proposalB.GetDepositEndTime()) &&
|
||||
proposalA.GetTotalDeposit().IsEqual(proposalB.GetTotalDeposit()) &&
|
||||
proposalA.GetVotingStartTime().Equal(proposalB.GetVotingStartTime()) &&
|
||||
proposalA.GetVotingEndTime().Equal(proposalB.GetVotingEndTime()) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Text Proposals
|
||||
type TextProposal struct {
|
||||
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}
|
||||
ProposalID uint64 `json:"proposal_id"` // ID of the proposal
|
||||
|
||||
Status ProposalStatus `json:"proposal_status"` // Status of the Proposal {Pending, Active, Passed, Rejected}
|
||||
FinalTallyResult TallyResult `json:"final_tally_result"` // Result of Tallys
|
||||
|
@ -96,55 +27,83 @@ type TextProposal struct {
|
|||
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 (p Proposal) String() string {
|
||||
return fmt.Sprintf(`Proposal %d:
|
||||
Title: %s
|
||||
Type: %s
|
||||
Status: %s
|
||||
Submit Time: %s
|
||||
Deposit End Time: %s
|
||||
Total Deposit: %s
|
||||
Voting Start Time: %s
|
||||
Voting End Time: %s`, p.ProposalID, p.GetTitle(), p.ProposalType(),
|
||||
p.Status, p.SubmitTime, p.DepositEndTime,
|
||||
p.TotalDeposit, p.VotingStartTime, p.VotingEndTime)
|
||||
}
|
||||
|
||||
// ProposalContent is an interface that has title, description, and proposaltype
|
||||
// that the governance module can use to identify them and generate human readable messages
|
||||
// ProposalContent can have additional fields, which will handled by ProposalHandlers
|
||||
// via type assertion, e.g. parameter change amount in ParameterChangeProposal
|
||||
type ProposalContent interface {
|
||||
GetTitle() string
|
||||
GetDescription() string
|
||||
ProposalType() ProposalKind
|
||||
}
|
||||
|
||||
// Proposals is an array of proposal
|
||||
type Proposals []Proposal
|
||||
|
||||
// nolint
|
||||
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 }
|
||||
func (tp *TextProposal) SetDescription(description string) { tp.Description = description }
|
||||
func (tp TextProposal) GetProposalType() ProposalKind { return tp.ProposalType }
|
||||
func (tp *TextProposal) SetProposalType(proposalType ProposalKind) { tp.ProposalType = proposalType }
|
||||
func (tp TextProposal) GetStatus() ProposalStatus { return tp.Status }
|
||||
func (tp *TextProposal) SetStatus(status ProposalStatus) { tp.Status = status }
|
||||
func (tp TextProposal) GetFinalTallyResult() TallyResult { return tp.FinalTallyResult }
|
||||
func (tp *TextProposal) SetFinalTallyResult(tallyResult TallyResult) {
|
||||
tp.FinalTallyResult = tallyResult
|
||||
}
|
||||
func (tp TextProposal) GetSubmitTime() time.Time { return tp.SubmitTime }
|
||||
func (tp *TextProposal) SetSubmitTime(submitTime time.Time) { tp.SubmitTime = submitTime }
|
||||
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
|
||||
func (p Proposals) String() string {
|
||||
out := "ID - (Status) [Type] Title\n"
|
||||
for _, prop := range p {
|
||||
out += fmt.Sprintf("%d - (%s) [%s] %s\n",
|
||||
prop.ProposalID, prop.Status,
|
||||
prop.ProposalType(), prop.GetTitle())
|
||||
}
|
||||
return strings.TrimSpace(out)
|
||||
}
|
||||
|
||||
func (tp TextProposal) String() string {
|
||||
return fmt.Sprintf(`Proposal %d:
|
||||
Title: %s
|
||||
Type: %s
|
||||
Status: %s
|
||||
Submit Time: %s
|
||||
Deposit End Time: %s
|
||||
Total Deposit: %s
|
||||
Voting Start Time: %s
|
||||
Voting End Time: %s`, tp.ProposalID, tp.Title, tp.ProposalType,
|
||||
tp.Status, tp.SubmitTime, tp.DepositEndTime,
|
||||
tp.TotalDeposit, tp.VotingStartTime, tp.VotingEndTime)
|
||||
// Text Proposals
|
||||
type TextProposal struct {
|
||||
Title string `json:"title"` // Title of the proposal
|
||||
Description string `json:"description"` // Description of the proposal
|
||||
}
|
||||
|
||||
func NewTextProposal(title, description string) TextProposal {
|
||||
return TextProposal{
|
||||
Title: title,
|
||||
Description: description,
|
||||
}
|
||||
}
|
||||
|
||||
// Implements Proposal Interface
|
||||
var _ ProposalContent = TextProposal{}
|
||||
|
||||
// nolint
|
||||
func (tp TextProposal) GetTitle() string { return tp.Title }
|
||||
func (tp TextProposal) GetDescription() string { return tp.Description }
|
||||
func (tp TextProposal) ProposalType() ProposalKind { return ProposalTypeText }
|
||||
|
||||
// Software Upgrade Proposals
|
||||
type SoftwareUpgradeProposal struct {
|
||||
TextProposal
|
||||
}
|
||||
|
||||
func NewSoftwareUpgradeProposal(title, description string) SoftwareUpgradeProposal {
|
||||
return SoftwareUpgradeProposal{
|
||||
TextProposal: NewTextProposal(title, description),
|
||||
}
|
||||
}
|
||||
|
||||
// Implements Proposal Interface
|
||||
var _ ProposalContent = SoftwareUpgradeProposal{}
|
||||
|
||||
// nolint
|
||||
func (sup SoftwareUpgradeProposal) ProposalType() ProposalKind { return ProposalTypeSoftwareUpgrade }
|
||||
|
||||
// ProposalQueue
|
||||
type ProposalQueue []uint64
|
||||
|
||||
|
|
|
@ -99,8 +99,8 @@ func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper
|
|||
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
|
||||
}
|
||||
|
||||
proposal := keeper.GetProposal(ctx, params.ProposalID)
|
||||
if proposal == nil {
|
||||
proposal, ok := keeper.GetProposal(ctx, params.ProposalID)
|
||||
if !ok {
|
||||
return nil, ErrUnknownProposal(DefaultCodespace, params.ProposalID)
|
||||
}
|
||||
|
||||
|
@ -205,17 +205,17 @@ func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke
|
|||
|
||||
proposalID := params.ProposalID
|
||||
|
||||
proposal := keeper.GetProposal(ctx, proposalID)
|
||||
if proposal == nil {
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
if !ok {
|
||||
return nil, ErrUnknownProposal(DefaultCodespace, proposalID)
|
||||
}
|
||||
|
||||
var tallyResult TallyResult
|
||||
|
||||
if proposal.GetStatus() == StatusDepositPeriod {
|
||||
if proposal.Status == StatusDepositPeriod {
|
||||
tallyResult = EmptyTallyResult()
|
||||
} else if proposal.GetStatus() == StatusPassed || proposal.GetStatus() == StatusRejected {
|
||||
tallyResult = proposal.GetFinalTallyResult()
|
||||
} else if proposal.Status == StatusPassed || proposal.Status == StatusRejected {
|
||||
tallyResult = proposal.FinalTallyResult
|
||||
} else {
|
||||
// proposal is in voting period
|
||||
_, tallyResult = tally(ctx, keeper, proposal)
|
||||
|
|
|
@ -227,12 +227,12 @@ func testQueries(t *testing.T) {
|
|||
// Only proposal #1 should be in Deposit Period
|
||||
proposals := getQueriedProposals(t, ctx, cdc, querier, nil, nil, StatusDepositPeriod, 0)
|
||||
require.Len(t, proposals, 1)
|
||||
require.Equal(t, proposalID1, proposals[0].GetProposalID())
|
||||
require.Equal(t, proposalID1, proposals[0].ProposalID)
|
||||
// Only proposals #2 and #3 should be in Voting Period
|
||||
proposals = getQueriedProposals(t, ctx, cdc, querier, nil, nil, StatusVotingPeriod, 0)
|
||||
require.Len(t, proposals, 2)
|
||||
require.Equal(t, proposalID2, proposals[0].GetProposalID())
|
||||
require.Equal(t, proposalID3, proposals[1].GetProposalID())
|
||||
require.Equal(t, proposalID2, proposals[0].ProposalID)
|
||||
require.Equal(t, proposalID3, proposals[1].ProposalID)
|
||||
|
||||
// Addrs[0] votes on proposals #2 & #3
|
||||
handler(ctx, NewMsgVote(addrs[0], proposalID2, OptionYes))
|
||||
|
@ -243,8 +243,8 @@ func testQueries(t *testing.T) {
|
|||
|
||||
// Test query voted by addrs[0]
|
||||
proposals = getQueriedProposals(t, ctx, cdc, querier, nil, addrs[0], StatusNil, 0)
|
||||
require.Equal(t, proposalID2, (proposals[0]).GetProposalID())
|
||||
require.Equal(t, proposalID3, (proposals[1]).GetProposalID())
|
||||
require.Equal(t, proposalID2, (proposals[0]).ProposalID)
|
||||
require.Equal(t, proposalID3, (proposals[1]).ProposalID)
|
||||
|
||||
// Test query votes on Proposal 2
|
||||
votes := getQueriedVotes(t, ctx, cdc, querier, proposalID2)
|
||||
|
@ -263,26 +263,26 @@ func testQueries(t *testing.T) {
|
|||
|
||||
// Test query all proposals
|
||||
proposals = getQueriedProposals(t, ctx, cdc, querier, nil, nil, StatusNil, 0)
|
||||
require.Equal(t, proposalID1, (proposals[0]).GetProposalID())
|
||||
require.Equal(t, proposalID2, (proposals[1]).GetProposalID())
|
||||
require.Equal(t, proposalID3, (proposals[2]).GetProposalID())
|
||||
require.Equal(t, proposalID1, (proposals[0]).ProposalID)
|
||||
require.Equal(t, proposalID2, (proposals[1]).ProposalID)
|
||||
require.Equal(t, proposalID3, (proposals[2]).ProposalID)
|
||||
|
||||
// Test query voted by addrs[1]
|
||||
proposals = getQueriedProposals(t, ctx, cdc, querier, nil, addrs[1], StatusNil, 0)
|
||||
require.Equal(t, proposalID3, (proposals[0]).GetProposalID())
|
||||
require.Equal(t, proposalID3, (proposals[0]).ProposalID)
|
||||
|
||||
// Test query deposited by addrs[0]
|
||||
proposals = getQueriedProposals(t, ctx, cdc, querier, addrs[0], nil, StatusNil, 0)
|
||||
require.Equal(t, proposalID1, (proposals[0]).GetProposalID())
|
||||
require.Equal(t, proposalID1, (proposals[0]).ProposalID)
|
||||
|
||||
// Test query deposited by addr2
|
||||
proposals = getQueriedProposals(t, ctx, cdc, querier, addrs[1], nil, StatusNil, 0)
|
||||
require.Equal(t, proposalID2, (proposals[0]).GetProposalID())
|
||||
require.Equal(t, proposalID3, (proposals[1]).GetProposalID())
|
||||
require.Equal(t, proposalID2, (proposals[0]).ProposalID)
|
||||
require.Equal(t, proposalID3, (proposals[1]).ProposalID)
|
||||
|
||||
// Test query voted AND deposited by addr1
|
||||
proposals = getQueriedProposals(t, ctx, cdc, querier, addrs[0], addrs[0], StatusNil, 0)
|
||||
require.Equal(t, proposalID2, (proposals[0]).GetProposalID())
|
||||
require.Equal(t, proposalID2, (proposals[0]).ProposalID)
|
||||
|
||||
// Test Tally Query
|
||||
tally := getQueriedTally(t, ctx, cdc, querier, proposalID2)
|
||||
|
|
|
@ -49,7 +49,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall
|
|||
})
|
||||
|
||||
// iterate over all the votes
|
||||
votesIterator := keeper.GetVotes(ctx, proposal.GetProposalID())
|
||||
votesIterator := keeper.GetVotes(ctx, proposal.ProposalID)
|
||||
defer votesIterator.Close()
|
||||
for ; votesIterator.Valid(); votesIterator.Next() {
|
||||
vote := &Vote{}
|
||||
|
|
|
@ -53,12 +53,16 @@ func TestTallyNoOneVotes(t *testing.T) {
|
|||
createValidators(t, stakingHandler, ctx, valAddrs, []int64{5, 5})
|
||||
staking.EndBlocker(ctx, sk)
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
tp := TextProposal{"Test", "description"}
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
passes, tallyResults := tally(ctx, keeper, proposal)
|
||||
|
||||
require.False(t, passes)
|
||||
require.True(t, tallyResults.Equals(EmptyTallyResult()))
|
||||
|
@ -81,15 +85,19 @@ func TestTallyNoQuorum(t *testing.T) {
|
|||
createValidators(t, stakingHandler, ctx, valAddrs, []int64{2, 5})
|
||||
staking.EndBlocker(ctx, sk)
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
tp := TextProposal{"Test", "description"}
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
err := keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
require.Nil(t, err)
|
||||
|
||||
passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
passes, _ := tally(ctx, keeper, proposal)
|
||||
require.False(t, passes)
|
||||
}
|
||||
|
||||
|
@ -110,17 +118,21 @@ func TestTallyOnlyValidatorsAllYes(t *testing.T) {
|
|||
createValidators(t, stakingHandler, ctx, valAddrs, []int64{5, 5})
|
||||
staking.EndBlocker(ctx, sk)
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
tp := TextProposal{"Test", "description"}
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
err := keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionYes)
|
||||
require.Nil(t, err)
|
||||
|
||||
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
passes, tallyResults := tally(ctx, keeper, proposal)
|
||||
|
||||
require.True(t, passes)
|
||||
require.False(t, tallyResults.Equals(EmptyTallyResult()))
|
||||
|
@ -143,17 +155,21 @@ func TestTallyOnlyValidators51No(t *testing.T) {
|
|||
createValidators(t, stakingHandler, ctx, valAddrs, []int64{5, 6})
|
||||
staking.EndBlocker(ctx, sk)
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
tp := TextProposal{"Test", "description"}
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
err := keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionNo)
|
||||
require.Nil(t, err)
|
||||
|
||||
passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
passes, _ := tally(ctx, keeper, proposal)
|
||||
|
||||
require.False(t, passes)
|
||||
}
|
||||
|
@ -175,19 +191,23 @@ func TestTallyOnlyValidators51Yes(t *testing.T) {
|
|||
createValidators(t, stakingHandler, ctx, valAddrs, []int64{6, 6, 7})
|
||||
staking.EndBlocker(ctx, sk)
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
tp := TextProposal{"Test", "description"}
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
err := keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionYes)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo)
|
||||
require.Nil(t, err)
|
||||
|
||||
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
passes, tallyResults := tally(ctx, keeper, proposal)
|
||||
|
||||
require.True(t, passes)
|
||||
require.False(t, tallyResults.Equals(EmptyTallyResult()))
|
||||
|
@ -210,19 +230,23 @@ func TestTallyOnlyValidatorsVetoed(t *testing.T) {
|
|||
createValidators(t, stakingHandler, ctx, valAddrs, []int64{6, 6, 7})
|
||||
staking.EndBlocker(ctx, sk)
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
tp := TextProposal{"Test", "description"}
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
err := keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionYes)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNoWithVeto)
|
||||
require.Nil(t, err)
|
||||
|
||||
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
passes, tallyResults := tally(ctx, keeper, proposal)
|
||||
|
||||
require.False(t, passes)
|
||||
require.False(t, tallyResults.Equals(EmptyTallyResult()))
|
||||
|
@ -245,19 +269,23 @@ func TestTallyOnlyValidatorsAbstainPasses(t *testing.T) {
|
|||
createValidators(t, stakingHandler, ctx, valAddrs, []int64{6, 6, 7})
|
||||
staking.EndBlocker(ctx, sk)
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
tp := TextProposal{"Test", "description"}
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
err := keeper.AddVote(ctx, proposalID, addrs[0], OptionAbstain)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[0], OptionAbstain)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionNo)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionYes)
|
||||
require.Nil(t, err)
|
||||
|
||||
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
passes, tallyResults := tally(ctx, keeper, proposal)
|
||||
|
||||
require.True(t, passes)
|
||||
require.False(t, tallyResults.Equals(EmptyTallyResult()))
|
||||
|
@ -280,19 +308,23 @@ func TestTallyOnlyValidatorsAbstainFails(t *testing.T) {
|
|||
createValidators(t, stakingHandler, ctx, valAddrs, []int64{6, 6, 7})
|
||||
staking.EndBlocker(ctx, sk)
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
tp := TextProposal{"Test", "description"}
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
err := keeper.AddVote(ctx, proposalID, addrs[0], OptionAbstain)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[0], OptionAbstain)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionYes)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo)
|
||||
require.Nil(t, err)
|
||||
|
||||
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
passes, tallyResults := tally(ctx, keeper, proposal)
|
||||
|
||||
require.False(t, passes)
|
||||
require.False(t, tallyResults.Equals(EmptyTallyResult()))
|
||||
|
@ -315,17 +347,21 @@ func TestTallyOnlyValidatorsNonVoter(t *testing.T) {
|
|||
createValidators(t, stakingHandler, ctx, valAddrs, []int64{6, 6, 7})
|
||||
staking.EndBlocker(ctx, sk)
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
tp := TextProposal{"Test", "description"}
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
err := keeper.AddVote(ctx, proposalID, addrs[1], OptionYes)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionYes)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo)
|
||||
require.Nil(t, err)
|
||||
|
||||
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
passes, tallyResults := tally(ctx, keeper, proposal)
|
||||
|
||||
require.False(t, passes)
|
||||
require.False(t, tallyResults.Equals(EmptyTallyResult()))
|
||||
|
@ -352,12 +388,14 @@ func TestTallyDelgatorOverride(t *testing.T) {
|
|||
delegator1Msg := staking.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewCoin(sdk.DefaultBondDenom, delTokens))
|
||||
stakingHandler(ctx, delegator1Msg)
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
tp := TextProposal{"Test", "description"}
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
err := keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionYes)
|
||||
require.Nil(t, err)
|
||||
|
@ -366,7 +404,9 @@ func TestTallyDelgatorOverride(t *testing.T) {
|
|||
err = keeper.AddVote(ctx, proposalID, addrs[3], OptionNo)
|
||||
require.Nil(t, err)
|
||||
|
||||
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
passes, tallyResults := tally(ctx, keeper, proposal)
|
||||
|
||||
require.False(t, passes)
|
||||
require.False(t, tallyResults.Equals(EmptyTallyResult()))
|
||||
|
@ -393,19 +433,23 @@ func TestTallyDelgatorInherit(t *testing.T) {
|
|||
delegator1Msg := staking.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewCoin(sdk.DefaultBondDenom, delTokens))
|
||||
stakingHandler(ctx, delegator1Msg)
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
tp := TextProposal{"Test", "description"}
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
err := keeper.AddVote(ctx, proposalID, addrs[0], OptionNo)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[0], OptionNo)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionNo)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionYes)
|
||||
require.Nil(t, err)
|
||||
|
||||
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
passes, tallyResults := tally(ctx, keeper, proposal)
|
||||
|
||||
require.True(t, passes)
|
||||
require.False(t, tallyResults.Equals(EmptyTallyResult()))
|
||||
|
@ -434,12 +478,14 @@ func TestTallyDelgatorMultipleOverride(t *testing.T) {
|
|||
delegator1Msg2 := staking.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[1]), sdk.NewCoin(sdk.DefaultBondDenom, delTokens))
|
||||
stakingHandler(ctx, delegator1Msg2)
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
tp := TextProposal{"Test", "description"}
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
err := keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionYes)
|
||||
require.Nil(t, err)
|
||||
|
@ -448,7 +494,9 @@ func TestTallyDelgatorMultipleOverride(t *testing.T) {
|
|||
err = keeper.AddVote(ctx, proposalID, addrs[3], OptionNo)
|
||||
require.Nil(t, err)
|
||||
|
||||
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
passes, tallyResults := tally(ctx, keeper, proposal)
|
||||
|
||||
require.False(t, passes)
|
||||
require.False(t, tallyResults.Equals(EmptyTallyResult()))
|
||||
|
@ -490,19 +538,23 @@ func TestTallyDelgatorMultipleInherit(t *testing.T) {
|
|||
|
||||
staking.EndBlocker(ctx, sk)
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
tp := TextProposal{"Test", "description"}
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
err := keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionNo)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo)
|
||||
require.Nil(t, err)
|
||||
|
||||
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
passes, tallyResults := tally(ctx, keeper, proposal)
|
||||
|
||||
require.False(t, passes)
|
||||
require.False(t, tallyResults.Equals(EmptyTallyResult()))
|
||||
|
@ -538,19 +590,23 @@ func TestTallyJailedValidator(t *testing.T) {
|
|||
|
||||
staking.EndBlocker(ctx, sk)
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
tp := TextProposal{"Test", "description"}
|
||||
proposal, err := keeper.SubmitProposal(ctx, tp)
|
||||
require.NoError(t, err)
|
||||
proposalID := proposal.ProposalID
|
||||
proposal.Status = StatusVotingPeriod
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
|
||||
err := keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionNo)
|
||||
require.Nil(t, err)
|
||||
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo)
|
||||
require.Nil(t, err)
|
||||
|
||||
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
|
||||
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||||
require.True(t, ok)
|
||||
passes, tallyResults := tally(ctx, keeper, proposal)
|
||||
|
||||
require.True(t, passes)
|
||||
require.False(t, tallyResults.Equals(EmptyTallyResult()))
|
||||
|
|
|
@ -146,3 +146,12 @@ func SortByteArrays(src [][]byte) [][]byte {
|
|||
sort.Sort(sorted)
|
||||
return sorted
|
||||
}
|
||||
|
||||
func testProposal() TextProposal {
|
||||
return NewTextProposal("Test", "description")
|
||||
}
|
||||
|
||||
// checks if two proposals are equal (note: slow, for tests only)
|
||||
func ProposalEqual(proposalA Proposal, proposalB Proposal) bool {
|
||||
return bytes.Equal(msgCdc.MustMarshalBinaryBare(proposalA), msgCdc.MustMarshalBinaryBare(proposalB))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue