Fix Governance state import (#3223)

This commit is contained in:
Jack Zampolin 2019-01-07 14:24:04 -08:00 committed by GitHub
parent 20f6ff3e60
commit b6ee053b1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 161 additions and 36 deletions

View File

@ -21,7 +21,7 @@ BREAKING CHANGES
* [\#3176](https://github.com/cosmos/cosmos-sdk/issues/3176) `tx/sign` endpoint now expects `BaseReq` fields as nested object.
* SDK
* [stake] \#2513 Validator power type from Dec -> Int
* [stake] \#2513 Validator power type from Dec -> Int
* [stake] \#3233 key and value now contain duplicate fields to simplify code
* [\#3064](https://github.com/cosmos/cosmos-sdk/issues/3064) Sanitize `sdk.Coin` denom. Coins denoms are now case insensitive, i.e. 100fooToken equals to 100FOOTOKEN.
@ -86,12 +86,13 @@ BUG FIXES
* Gaia CLI (`gaiacli`)
* \#3141 Fix the bug in GetAccount when `len(res) == 0` and `err == nil`
* Gaia
* \#3148 Fix `gaiad export` by adding a boolean to `NewGaiaApp` determining whether or not to load the latest version
* \#3181 Correctly reset total accum update height and jailed-validator bond height / unbonding height on export-for-zero-height
* [\#3172](https://github.com/cosmos/cosmos-sdk/pull/3172) Fix parsing `gaiad.toml`
when it already exists.
* \#3223 Fix unset governance proposal queues when importing state from old chain
* [#3187](https://github.com/cosmos/cosmos-sdk/issues/3187) Fix `gaiad export`
by resetting each validator's slashing period.

View File

@ -13,7 +13,7 @@ import (
)
func TestTickExpiredDepositPeriod(t *testing.T) {
mapp, keeper, _, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, _, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
govHandler := NewHandler(keeper)
@ -55,7 +55,7 @@ func TestTickExpiredDepositPeriod(t *testing.T) {
}
func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
mapp, keeper, _, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, _, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
govHandler := NewHandler(keeper)
@ -111,7 +111,7 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
}
func TestTickPassedDepositPeriod(t *testing.T) {
mapp, keeper, _, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, _, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
govHandler := NewHandler(keeper)
@ -152,7 +152,7 @@ func TestTickPassedDepositPeriod(t *testing.T) {
}
func TestTickPassedVotingPeriod(t *testing.T) {
mapp, keeper, _, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, _, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
SortAddresses(addrs)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})

View File

@ -60,6 +60,58 @@ func DefaultGenesisState() GenesisState {
}
}
// Checks whether 2 GenesisState structs are equivalent.
func (data GenesisState) Equal(data2 GenesisState) bool {
if data.StartingProposalID != data.StartingProposalID ||
!data.DepositParams.Equal(data2.DepositParams) ||
data.VotingParams != data2.VotingParams ||
data.TallyParams != data2.TallyParams {
return false
}
if len(data.Deposits) != len(data2.Deposits) {
return false
}
for i := range data.Deposits {
deposit1 := data.Deposits[i]
deposit2 := data2.Deposits[i]
if deposit1.ProposalID != deposit2.ProposalID ||
!deposit1.Deposit.Equals(deposit2.Deposit) {
return false
}
}
if len(data.Votes) != len(data2.Votes) {
return false
}
for i := range data.Votes {
vote1 := data.Votes[i]
vote2 := data2.Votes[i]
if vote1.ProposalID != vote2.ProposalID ||
!vote1.Vote.Equals(vote2.Vote) {
return false
}
}
if len(data.Proposals) != len(data2.Proposals) {
return false
}
for i := range data.Proposals {
if data.Proposals[i] != data.Proposals[i] {
return false
}
}
return true
}
// Returns if a GenesisState is empty or has data in it
func (data GenesisState) IsEmpty() bool {
emptyGenState := GenesisState{}
return data.Equal(emptyGenState)
}
// ValidateGenesis TODO https://github.com/cosmos/cosmos-sdk/issues/3007
func ValidateGenesis(data GenesisState) error {
threshold := data.TallyParams.Threshold
@ -110,6 +162,12 @@ 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() {
case StatusDepositPeriod:
k.InsertInactiveProposalQueue(ctx, proposal.GetDepositEndTime(), proposal.GetProposalID())
case StatusVotingPeriod:
k.InsertActiveProposalQueue(ctx, proposal.GetVotingEndTime(), proposal.GetProposalID())
}
k.SetProposal(ctx, proposal)
}
}

54
x/gov/genesis_test.go Normal file
View File

@ -0,0 +1,54 @@
package gov
import (
"testing"
"github.com/cosmos/cosmos-sdk/x/mock"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
)
func TestImportExportQueues(t *testing.T) {
// Generate mock app and keepers
mapp, keeper, _, addrs, _, _ := getMockApp(t, 2, GenesisState{}, nil)
SortAddresses(addrs)
mapp.BeginBlock(abci.RequestBeginBlock{})
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()
proposal2 := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
proposalID2 := proposal2.GetProposalID()
_, 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)
genAccs := mock.GetAllAccounts(mapp.AccountKeeper, ctx)
// Export the state and import it into a new Mock App
genState := ExportGenesis(ctx, keeper)
mapp2, keeper2, _, _, _, _ := getMockApp(t, 2, genState, genAccs)
mapp2.BeginBlock(abci.RequestBeginBlock{})
ctx2 := mapp2.BaseApp.NewContext(false, abci.Header{})
// Jump the time forward past the DepositPeriod and VotingPeriod
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)
// 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)
}

View File

@ -13,7 +13,7 @@ import (
)
func TestGetSetProposal(t *testing.T) {
mapp, keeper, _, _, _, _ := getMockApp(t, 0)
mapp, keeper, _, _, _, _ := getMockApp(t, 0, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
@ -26,7 +26,7 @@ func TestGetSetProposal(t *testing.T) {
}
func TestIncrementProposalNumber(t *testing.T) {
mapp, keeper, _, _, _, _ := getMockApp(t, 0)
mapp, keeper, _, _, _, _ := getMockApp(t, 0, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
@ -41,7 +41,7 @@ func TestIncrementProposalNumber(t *testing.T) {
}
func TestActivateVotingPeriod(t *testing.T) {
mapp, keeper, _, _, _, _ := getMockApp(t, 0)
mapp, keeper, _, _, _, _ := getMockApp(t, 0, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
@ -62,7 +62,7 @@ func TestActivateVotingPeriod(t *testing.T) {
}
func TestDeposits(t *testing.T) {
mapp, keeper, _, addrs, _, _ := getMockApp(t, 2)
mapp, keeper, _, addrs, _, _ := getMockApp(t, 2, GenesisState{}, nil)
SortAddresses(addrs)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
@ -149,7 +149,7 @@ func TestDeposits(t *testing.T) {
}
func TestVotes(t *testing.T) {
mapp, keeper, _, addrs, _, _ := getMockApp(t, 2)
mapp, keeper, _, addrs, _, _ := getMockApp(t, 2, GenesisState{}, nil)
SortAddresses(addrs)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
@ -205,7 +205,7 @@ func TestVotes(t *testing.T) {
}
func TestProposalQueues(t *testing.T) {
mapp, keeper, _, _, _, _ := getMockApp(t, 0)
mapp, keeper, _, _, _, _ := getMockApp(t, 0, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
mapp.InitChainer(ctx, abci.RequestInitChain{})

View File

@ -12,6 +12,11 @@ type DepositParams struct {
MaxDepositPeriod time.Duration `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months
}
// Checks equality of DepositParams
func (dp DepositParams) Equal(dp2 DepositParams) bool {
return dp.MinDeposit.IsEqual(dp2.MinDeposit) && dp.MaxDepositPeriod == dp2.MaxDepositPeriod
}
// Param around Tallying votes in governance
type TallyParams struct {
Quorum sdk.Dec `json:"quorum"` // Minimum percentage of total stake needed to vote for a result to be considered valid

View File

@ -170,7 +170,7 @@ func getQueriedTally(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sd
func testQueryParams(t *testing.T) {
cdc := codec.New()
mapp, keeper, _, _, _, _ := getMockApp(t, 1000)
mapp, keeper, _, _, _, _ := getMockApp(t, 1000, GenesisState{}, nil)
querier := NewQuerier(keeper)
ctx := mapp.NewContext(false, abci.Header{})
@ -179,7 +179,7 @@ func testQueryParams(t *testing.T) {
func testQueries(t *testing.T) {
cdc := codec.New()
mapp, keeper, _, addrs, _, _ := getMockApp(t, 1000)
mapp, keeper, _, addrs, _, _ := getMockApp(t, 1000, GenesisState{}, nil)
querier := NewQuerier(keeper)
handler := NewHandler(keeper)
ctx := mapp.NewContext(false, abci.Header{})

View File

@ -36,7 +36,7 @@ func createValidators(t *testing.T, stakeHandler sdk.Handler, ctx sdk.Context, a
}
func TestTallyNoOneVotes(t *testing.T) {
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
stakeHandler := stake.NewHandler(sk)
@ -61,7 +61,7 @@ func TestTallyNoOneVotes(t *testing.T) {
}
func TestTallyNoQuorum(t *testing.T) {
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
stakeHandler := stake.NewHandler(sk)
@ -87,7 +87,7 @@ func TestTallyNoQuorum(t *testing.T) {
}
func TestTallyOnlyValidatorsAllYes(t *testing.T) {
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
stakeHandler := stake.NewHandler(sk)
@ -117,7 +117,7 @@ func TestTallyOnlyValidatorsAllYes(t *testing.T) {
}
func TestTallyOnlyValidators51No(t *testing.T) {
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
stakeHandler := stake.NewHandler(sk)
@ -146,7 +146,7 @@ func TestTallyOnlyValidators51No(t *testing.T) {
}
func TestTallyOnlyValidators51Yes(t *testing.T) {
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
stakeHandler := stake.NewHandler(sk)
@ -178,7 +178,7 @@ func TestTallyOnlyValidators51Yes(t *testing.T) {
}
func TestTallyOnlyValidatorsVetoed(t *testing.T) {
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
stakeHandler := stake.NewHandler(sk)
@ -210,7 +210,7 @@ func TestTallyOnlyValidatorsVetoed(t *testing.T) {
}
func TestTallyOnlyValidatorsAbstainPasses(t *testing.T) {
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
stakeHandler := stake.NewHandler(sk)
@ -242,7 +242,7 @@ func TestTallyOnlyValidatorsAbstainPasses(t *testing.T) {
}
func TestTallyOnlyValidatorsAbstainFails(t *testing.T) {
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
stakeHandler := stake.NewHandler(sk)
@ -274,7 +274,7 @@ func TestTallyOnlyValidatorsAbstainFails(t *testing.T) {
}
func TestTallyOnlyValidatorsNonVoter(t *testing.T) {
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
stakeHandler := stake.NewHandler(sk)
@ -304,7 +304,7 @@ func TestTallyOnlyValidatorsNonVoter(t *testing.T) {
}
func TestTallyDelgatorOverride(t *testing.T) {
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
stakeHandler := stake.NewHandler(sk)
@ -341,7 +341,7 @@ func TestTallyDelgatorOverride(t *testing.T) {
}
func TestTallyDelgatorInherit(t *testing.T) {
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
stakeHandler := stake.NewHandler(sk)
@ -376,7 +376,7 @@ func TestTallyDelgatorInherit(t *testing.T) {
}
func TestTallyDelgatorMultipleOverride(t *testing.T) {
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
stakeHandler := stake.NewHandler(sk)
@ -415,7 +415,7 @@ func TestTallyDelgatorMultipleOverride(t *testing.T) {
}
func TestTallyDelgatorMultipleInherit(t *testing.T) {
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
stakeHandler := stake.NewHandler(sk)
@ -462,7 +462,7 @@ func TestTallyDelgatorMultipleInherit(t *testing.T) {
}
func TestTallyJailedValidator(t *testing.T) {
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10, GenesisState{}, nil)
mapp.BeginBlock(abci.RequestBeginBlock{})
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
stakeHandler := stake.NewHandler(sk)

View File

@ -12,6 +12,7 @@ import (
"github.com/tendermint/tendermint/crypto"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/mock"
"github.com/cosmos/cosmos-sdk/x/stake"
@ -19,8 +20,8 @@ import (
)
// initialize the mock application for this module
func getMockApp(t *testing.T, numGenAccs int) (*mock.App, Keeper, stake.Keeper, []sdk.AccAddress, []crypto.PubKey, []crypto.PrivKey) {
mapp := mock.NewApp()
func getMockApp(t *testing.T, numGenAccs int, genState GenesisState, genAccs []auth.Account) (mapp *mock.App, keeper Keeper, sk stake.Keeper, addrs []sdk.AccAddress, pubKeys []crypto.PubKey, privKeys []crypto.PrivKey) {
mapp = mock.NewApp()
stake.RegisterCodec(mapp.Cdc)
RegisterCodec(mapp.Cdc)
@ -31,18 +32,20 @@ func getMockApp(t *testing.T, numGenAccs int) (*mock.App, Keeper, stake.Keeper,
pk := mapp.ParamsKeeper
ck := bank.NewBaseKeeper(mapp.AccountKeeper)
sk := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, ck, pk.Subspace(stake.DefaultParamspace), stake.DefaultCodespace)
keeper := NewKeeper(mapp.Cdc, keyGov, pk, pk.Subspace("testgov"), ck, sk, DefaultCodespace)
sk = stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, ck, pk.Subspace(stake.DefaultParamspace), stake.DefaultCodespace)
keeper = NewKeeper(mapp.Cdc, keyGov, pk, pk.Subspace("testgov"), ck, sk, DefaultCodespace)
mapp.Router().AddRoute(RouterKey, NewHandler(keeper))
mapp.QueryRouter().AddRoute(QuerierRoute, NewQuerier(keeper))
mapp.SetEndBlocker(getEndBlocker(keeper))
mapp.SetInitChainer(getInitChainer(mapp, keeper, sk))
mapp.SetInitChainer(getInitChainer(mapp, keeper, sk, genState))
require.NoError(t, mapp.CompleteSetup(keyStake, tkeyStake, keyGov))
genAccs, addrs, pubKeys, privKeys := mock.CreateGenAccounts(numGenAccs, sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 42)})
if genAccs == nil || len(genAccs) == 0 {
genAccs, addrs, pubKeys, privKeys = mock.CreateGenAccounts(numGenAccs, sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 42)})
}
mock.SetGenesis(mapp, genAccs)
@ -60,7 +63,7 @@ func getEndBlocker(keeper Keeper) sdk.EndBlocker {
}
// gov and stake initchainer
func getInitChainer(mapp *mock.App, keeper Keeper, stakeKeeper stake.Keeper) sdk.InitChainer {
func getInitChainer(mapp *mock.App, keeper Keeper, stakeKeeper stake.Keeper, genState GenesisState) sdk.InitChainer {
return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
mapp.InitChainer(ctx, req)
@ -71,7 +74,11 @@ func getInitChainer(mapp *mock.App, keeper Keeper, stakeKeeper stake.Keeper) sdk
if err != nil {
panic(err)
}
InitGenesis(ctx, keeper, DefaultGenesisState())
if genState.IsEmpty() {
InitGenesis(ctx, keeper, DefaultGenesisState())
} else {
InitGenesis(ctx, keeper, genState)
}
return abci.ResponseInitChain{
Validators: validators,
}