Merge PR #1914: tallyResults added to state

* tallyResults added to state
* fixed bug with tallyresult equals
This commit is contained in:
Sunny Aggarwal 2018-08-08 06:28:52 -04:00 committed by Christopher Goes
parent f653bed8c9
commit 4582de4902
7 changed files with 93 additions and 33 deletions

View File

@ -45,6 +45,7 @@ FEATURES
* [gov] Add slashing for validators who do not vote on a proposal
* [cli] added `gov query-proposals` command to CLI. Can filter by `depositer`, `voter`, and `status`
* [core] added BaseApp.Seal - ability to seal baseapp parameters once they've been set
* [gov] added TallyResult type that gets added stored in Proposal after tallying is finished
IMPROVEMENTS
* [baseapp] Allow any alphanumeric character in route

View File

@ -124,6 +124,7 @@ func TestTickPassedDepositPeriod(t *testing.T) {
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
require.NotNil(t, keeper.ActiveProposalQueuePeek(ctx))
require.False(t, shouldPopActiveProposalQueue(ctx, keeper))
}
func TestTickPassedVotingPeriod(t *testing.T) {
@ -166,6 +167,7 @@ func TestTickPassedVotingPeriod(t *testing.T) {
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()))
}
func TestSlashing(t *testing.T) {
@ -204,6 +206,8 @@ func TestSlashing(t *testing.T) {
EndBlocker(ctx, keeper)
require.False(t, keeper.GetProposal(ctx, proposalID).GetTallyResult().Equals(EmptyTallyResult()))
endTotalPower := keeper.ds.GetValidatorSet().TotalPower(ctx)
val0End := keeper.ds.GetValidatorSet().Validator(ctx, addrs[0]).GetPower().Quo(endTotalPower)
val1End := keeper.ds.GetValidatorSet().Validator(ctx, addrs[1]).GetPower().Quo(endTotalPower)

View File

@ -111,9 +111,6 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
resTags.AppendTag(tags.ProposalID, proposalIDBytes)
}
var passes bool
var nonVotingVals []sdk.AccAddress
// Check if earliest Active Proposal ended voting period yet
for shouldPopActiveProposalQueue(ctx, keeper) {
activeProposal := keeper.ActiveProposalQueuePop(ctx)
@ -124,7 +121,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
continue
}
passes, nonVotingVals = tally(ctx, keeper, activeProposal)
passes, tallyResults, nonVotingVals := tally(ctx, keeper, activeProposal)
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(activeProposal.GetProposalID())
var action []byte
if passes {
@ -136,6 +133,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
activeProposal.SetStatus(StatusRejected)
action = tags.ActionProposalRejected
}
activeProposal.SetTallyResult(tallyResults)
keeper.SetProposal(ctx, activeProposal)
for _, valAddr := range nonVotingVals {

View File

@ -71,6 +71,7 @@ func (keeper Keeper) NewTextProposal(ctx sdk.Context, title string, description
Description: description,
ProposalType: proposalType,
Status: StatusDepositPeriod,
TallyResult: EmptyTallyResult(),
TotalDeposit: sdk.Coins{},
SubmitBlock: ctx.BlockHeight(),
VotingStartBlock: -1, // TODO: Make Time

View File

@ -27,6 +27,9 @@ type Proposal interface {
GetStatus() ProposalStatus
SetStatus(ProposalStatus)
GetTallyResult() TallyResult
SetTallyResult(TallyResult)
GetSubmitBlock() int64
SetSubmitBlock(int64)
@ -39,17 +42,18 @@ type Proposal interface {
// 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.GetSubmitBlock() != proposalB.GetSubmitBlock() ||
!(proposalA.GetTotalDeposit().IsEqual(proposalB.GetTotalDeposit())) ||
proposalA.GetVotingStartBlock() != proposalB.GetVotingStartBlock() {
return false
if proposalA.GetProposalID() == proposalB.GetProposalID() &&
proposalA.GetTitle() == proposalB.GetTitle() &&
proposalA.GetDescription() == proposalB.GetDescription() &&
proposalA.GetProposalType() == proposalB.GetProposalType() &&
proposalA.GetStatus() == proposalB.GetStatus() &&
proposalA.GetTallyResult().Equals(proposalB.GetTallyResult()) &&
proposalA.GetSubmitBlock() == proposalB.GetSubmitBlock() &&
proposalA.GetTotalDeposit().IsEqual(proposalB.GetTotalDeposit()) &&
proposalA.GetVotingStartBlock() == proposalB.GetVotingStartBlock() {
return true
}
return true
return false
}
//-----------------------------------------------------------
@ -60,7 +64,8 @@ type TextProposal struct {
Description string `json:"description"` // Description of the proposal
ProposalType ProposalKind `json:"proposal_type"` // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal}
Status ProposalStatus `json:"proposal_status"` // Status of the Proposal {Pending, Active, Passed, Rejected}
Status ProposalStatus `json:"proposal_status"` // Status of the Proposal {Pending, Active, Passed, Rejected}
TallyResult TallyResult `json:"tally_result"` // Result of Tallys
SubmitBlock int64 `json:"submit_block"` // 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
@ -82,6 +87,8 @@ func (tp TextProposal) GetProposalType() ProposalKind { return tp.P
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) GetTallyResult() TallyResult { return tp.TallyResult }
func (tp *TextProposal) SetTallyResult(tallyResult TallyResult) { tp.TallyResult = tallyResult }
func (tp TextProposal) GetSubmitBlock() int64 { return tp.SubmitBlock }
func (tp *TextProposal) SetSubmitBlock(submitBlock int64) { tp.SubmitBlock = submitBlock }
func (tp TextProposal) GetTotalDeposit() sdk.Coins { return tp.TotalDeposit }
@ -286,3 +293,33 @@ func (status ProposalStatus) Format(s fmt.State, verb rune) {
s.Write([]byte(fmt.Sprintf("%v", byte(status))))
}
}
//-----------------------------------------------------------
// Tally Results
type TallyResult struct {
Yes sdk.Rat `json:"yes"`
Abstain sdk.Rat `json:"abstain"`
No sdk.Rat `json:"no"`
NoWithVeto sdk.Rat `json:"no_with_veto"`
}
// checks if two proposals are equal
func EmptyTallyResult() TallyResult {
return TallyResult{
Yes: sdk.ZeroRat(),
Abstain: sdk.ZeroRat(),
No: sdk.ZeroRat(),
NoWithVeto: sdk.ZeroRat(),
}
}
// checks if two proposals are equal
func (resultA TallyResult) Equals(resultB TallyResult) bool {
if resultA.Yes.Equal(resultB.Yes) &&
resultA.Abstain.Equal(resultB.Abstain) &&
resultA.No.Equal(resultB.No) &&
resultA.NoWithVeto.Equal(resultB.NoWithVeto) {
return true
}
return false
}

View File

@ -13,7 +13,7 @@ type validatorGovInfo struct {
Vote VoteOption // Vote of the validator
}
func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, nonVoting []sdk.AccAddress) {
func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tallyResults TallyResult, nonVoting []sdk.AccAddress) {
results := make(map[VoteOption]sdk.Rat)
results[OptionYes] = sdk.ZeroRat()
results[OptionAbstain] = sdk.ZeroRat()
@ -83,18 +83,25 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, nonV
tallyingProcedure := keeper.GetTallyingProcedure(ctx)
tallyResults = TallyResult{
Yes: results[OptionYes],
Abstain: results[OptionAbstain],
No: results[OptionNo],
NoWithVeto: results[OptionNoWithVeto],
}
// If no one votes, proposal fails
if totalVotingPower.Sub(results[OptionAbstain]).Equal(sdk.ZeroRat()) {
return false, nonVoting
return false, tallyResults, nonVoting
}
// If more than 1/3 of voters veto, proposal fails
if results[OptionNoWithVeto].Quo(totalVotingPower).GT(tallyingProcedure.Veto) {
return false, nonVoting
return false, tallyResults, nonVoting
}
// If more than 1/2 of non-abstaining voters vote Yes, proposal passes
if results[OptionYes].Quo(totalVotingPower.Sub(results[OptionAbstain])).GT(tallyingProcedure.Threshold) {
return true, nonVoting
return true, tallyResults, nonVoting
}
// If more than 1/2 of non-abstaining voters vote No, proposal fails
return false, nonVoting
return false, tallyResults, nonVoting
}

View File

@ -40,9 +40,10 @@ func TestTallyNoOneVotes(t *testing.T) {
proposal.SetStatus(StatusVotingPeriod)
keeper.SetProposal(ctx, proposal)
passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
require.False(t, passes)
require.True(t, tallyResults.Equals(EmptyTallyResult()))
}
func TestTallyOnlyValidatorsAllYes(t *testing.T) {
@ -63,9 +64,10 @@ func TestTallyOnlyValidatorsAllYes(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionYes)
require.Nil(t, err)
passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
require.True(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
}
func TestTallyOnlyValidators51No(t *testing.T) {
@ -86,7 +88,7 @@ func TestTallyOnlyValidators51No(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionNo)
require.Nil(t, err)
passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, _, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
require.False(t, passes)
}
@ -111,9 +113,10 @@ func TestTallyOnlyValidators51Yes(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo)
require.Nil(t, err)
passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
require.True(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
}
func TestTallyOnlyValidatorsVetoed(t *testing.T) {
@ -136,9 +139,10 @@ func TestTallyOnlyValidatorsVetoed(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNoWithVeto)
require.Nil(t, err)
passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
require.False(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
}
func TestTallyOnlyValidatorsAbstainPasses(t *testing.T) {
@ -161,9 +165,10 @@ func TestTallyOnlyValidatorsAbstainPasses(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionYes)
require.Nil(t, err)
passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
require.True(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
}
func TestTallyOnlyValidatorsAbstainFails(t *testing.T) {
@ -186,9 +191,10 @@ func TestTallyOnlyValidatorsAbstainFails(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo)
require.Nil(t, err)
passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
require.False(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
}
func TestTallyOnlyValidatorsNonVoter(t *testing.T) {
@ -209,11 +215,12 @@ func TestTallyOnlyValidatorsNonVoter(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo)
require.Nil(t, err)
passes, nonVoting := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults, nonVoting := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
require.False(t, passes)
require.Equal(t, 1, len(nonVoting))
require.Equal(t, addrs[0], nonVoting[0])
require.False(t, tallyResults.Equals(EmptyTallyResult()))
}
func TestTallyDelgatorOverride(t *testing.T) {
@ -241,9 +248,10 @@ func TestTallyDelgatorOverride(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[3], OptionNo)
require.Nil(t, err)
passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
require.False(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
}
func TestTallyDelgatorInherit(t *testing.T) {
@ -269,10 +277,11 @@ func TestTallyDelgatorInherit(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionYes)
require.Nil(t, err)
passes, nonVoting := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults, nonVoting := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
require.True(t, passes)
require.Equal(t, 0, len(nonVoting))
require.False(t, tallyResults.Equals(EmptyTallyResult()))
}
func TestTallyDelgatorMultipleOverride(t *testing.T) {
@ -302,9 +311,10 @@ func TestTallyDelgatorMultipleOverride(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[3], OptionNo)
require.Nil(t, err)
passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
require.False(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
}
func TestTallyDelgatorMultipleInherit(t *testing.T) {
@ -338,9 +348,10 @@ func TestTallyDelgatorMultipleInherit(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo)
require.Nil(t, err)
passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
require.False(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
}
func TestTallyRevokedValidator(t *testing.T) {
@ -371,7 +382,8 @@ func TestTallyRevokedValidator(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo)
require.Nil(t, err)
passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
require.True(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
}