From a922dad3468b4695e2ad7562d71cfc0ed87da328 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Thu, 18 Jul 2019 14:43:56 +0200 Subject: [PATCH] Merge PR #4686: v0.36 supply changes to genesis migration --- simapp/app.go | 42 +- simapp/sim_test.go | 7 +- x/auth/legacy/v0_34/types.go | 26 + x/auth/legacy/v0_36/migrate.go | 14 + x/auth/legacy/v0_36/migrate_test.go | 25 + x/auth/legacy/v0_36/types.go | 19 + x/auth/types/keys.go | 2 +- x/distribution/keeper/delegation.go | 22 +- x/distribution/legacy/v0_36/migrate.go | 75 +-- x/distribution/legacy/v0_36/migrate_test.go | 63 +++ x/distribution/legacy/v0_36/types.go | 102 +--- x/genaccounts/legacy/v0_34/types.go | 28 ++ x/genaccounts/legacy/v0_36/migrate.go | 179 +++++++ x/genaccounts/legacy/v0_36/migrate_test.go | 123 +++++ x/genaccounts/legacy/v0_36/types.go | 53 ++ x/genutil/legacy/v036/migrate.go | 71 ++- x/gov/legacy/v034/types.go | 513 -------------------- x/gov/legacy/v036/migrate.go | 76 --- x/gov/legacy/v036/types.go | 454 ----------------- x/gov/legacy/v0_34/types.go | 345 +++++++++++++ x/gov/legacy/v0_36/migrate.go | 51 ++ x/gov/legacy/v0_36/types.go | 164 +++++++ x/simulation/simulate.go | 11 + x/slashing/keeper.go | 12 +- x/staking/legacy/v0_34/types.go | 177 +++++++ x/staking/legacy/v0_36/migrate.go | 23 + x/staking/legacy/v0_36/types.go | 44 ++ x/staking/simulation/msgs.go | 2 +- x/staking/types/pool.go | 8 +- x/supply/genesis.go | 2 + x/supply/internal/keeper/bank.go | 15 +- x/supply/internal/keeper/bank_test.go | 2 +- x/supply/internal/types/supply.go | 2 +- x/supply/internal/types/supply_test.go | 2 +- x/supply/legacy/v0_36/types.go | 27 ++ 35 files changed, 1531 insertions(+), 1250 deletions(-) create mode 100644 x/auth/legacy/v0_34/types.go create mode 100644 x/auth/legacy/v0_36/migrate.go create mode 100644 x/auth/legacy/v0_36/migrate_test.go create mode 100644 x/auth/legacy/v0_36/types.go create mode 100644 x/distribution/legacy/v0_36/migrate_test.go create mode 100644 x/genaccounts/legacy/v0_34/types.go create mode 100644 x/genaccounts/legacy/v0_36/migrate.go create mode 100644 x/genaccounts/legacy/v0_36/migrate_test.go create mode 100644 x/genaccounts/legacy/v0_36/types.go delete mode 100644 x/gov/legacy/v034/types.go delete mode 100644 x/gov/legacy/v036/migrate.go delete mode 100644 x/gov/legacy/v036/types.go create mode 100644 x/gov/legacy/v0_34/types.go create mode 100644 x/gov/legacy/v0_36/migrate.go create mode 100644 x/gov/legacy/v0_36/types.go create mode 100644 x/staking/legacy/v0_34/types.go create mode 100644 x/staking/legacy/v0_36/migrate.go create mode 100644 x/staking/legacy/v0_36/types.go create mode 100644 x/supply/legacy/v0_36/types.go diff --git a/simapp/app.go b/simapp/app.go index 4defb20085..bc46e0cc24 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -56,6 +56,16 @@ var ( slashing.AppModuleBasic{}, supply.AppModuleBasic{}, ) + + // module account permissions + maccPerms = map[string][]string{ + auth.FeeCollectorName: nil, + distr.ModuleName: nil, + mint.ModuleName: {supply.Minter}, + staking.BondedPoolName: {supply.Burner, supply.Staking}, + staking.NotBondedPoolName: {supply.Burner, supply.Staking}, + gov.ModuleName: {supply.Burner}, + } ) // custom tx codec @@ -105,8 +115,10 @@ type SimApp struct { } // NewSimApp returns a reference to an initialized SimApp. -func NewSimApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, - invCheckPeriod uint, baseAppOptions ...func(*bam.BaseApp)) *SimApp { +func NewSimApp( + logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, + invCheckPeriod uint, baseAppOptions ...func(*bam.BaseApp), +) *SimApp { cdc := MakeCodec() @@ -114,7 +126,7 @@ func NewSimApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bo bApp.SetCommitMultiStoreTracer(traceStore) bApp.SetAppVersion(version.Version) - var app = &SimApp{ + app := &SimApp{ BaseApp: bApp, cdc: cdc, invCheckPeriod: invCheckPeriod, @@ -143,16 +155,6 @@ func NewSimApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bo govSubspace := app.paramsKeeper.Subspace(gov.DefaultParamspace) crisisSubspace := app.paramsKeeper.Subspace(crisis.DefaultParamspace) - // account permissions - maccPerms := map[string][]string{ - auth.FeeCollectorName: nil, - distr.ModuleName: nil, - mint.ModuleName: []string{supply.Minter}, - staking.BondedPoolName: []string{supply.Burner, supply.Staking}, - staking.NotBondedPoolName: []string{supply.Burner, supply.Staking}, - gov.ModuleName: []string{supply.Burner}, - } - // add keepers app.accountKeeper = auth.NewAccountKeeper(app.cdc, app.keyAccount, authSubspace, auth.ProtoBaseAccount) app.bankKeeper = bank.NewBaseKeeper(app.accountKeeper, bankSubspace, bank.DefaultCodespace) @@ -202,9 +204,9 @@ func NewSimApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bo // genutils must occur after staking so that pools are properly // initialized with tokens from genesis accounts. - app.mm.SetOrderInitGenesis(genaccounts.ModuleName, supply.ModuleName, distr.ModuleName, + app.mm.SetOrderInitGenesis(genaccounts.ModuleName, distr.ModuleName, staking.ModuleName, auth.ModuleName, bank.ModuleName, slashing.ModuleName, - gov.ModuleName, mint.ModuleName, crisis.ModuleName, genutil.ModuleName) + gov.ModuleName, mint.ModuleName, supply.ModuleName, crisis.ModuleName, genutil.ModuleName) app.mm.RegisterInvariants(&app.crisisKeeper) app.mm.RegisterRoutes(app.Router(), app.QueryRouter()) @@ -250,3 +252,13 @@ func (app *SimApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci. func (app *SimApp) LoadHeight(height int64) error { return app.LoadVersion(height, app.keyMain) } + +// ModuleAccountAddrs returns all the app's module account addresses. +func (app *SimApp) ModuleAccountAddrs() map[string]bool { + modAccAddrs := make(map[string]bool) + for acc := range maccPerms { + modAccAddrs[app.supplyKeeper.GetModuleAddress(acc).String()] = true + } + + return modAccAddrs +} diff --git a/simapp/sim_test.go b/simapp/sim_test.go index b882f6b9be..59a9b6d4ad 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -48,10 +48,11 @@ func init() { // helper function for populating input for SimulateFromSeed func getSimulateFromSeedInput(tb testing.TB, w io.Writer, app *SimApp) ( testing.TB, io.Writer, *baseapp.BaseApp, simulation.AppStateFn, int64, - simulation.WeightedOperations, sdk.Invariants, int, int, bool, bool, bool, bool) { + simulation.WeightedOperations, sdk.Invariants, int, int, bool, bool, bool, bool, map[string]bool) { return tb, w, app.BaseApp, appStateFn, seed, - testAndRunTxs(app), invariants(app), numBlocks, blockSize, commit, lean, onOperation, allInvariants + testAndRunTxs(app), invariants(app), numBlocks, blockSize, commit, + lean, onOperation, allInvariants, app.ModuleAccountAddrs() } func appStateFn( @@ -604,6 +605,7 @@ func TestAppStateDeterminism(t *testing.T) { false, false, false, + app.ModuleAccountAddrs(), ) appHash := app.LastCommitID().Hash appHashList[j] = appHash @@ -630,6 +632,7 @@ func BenchmarkInvariants(b *testing.B) { _, err := simulation.SimulateFromSeed( b, ioutil.Discard, app.BaseApp, appStateFn, seed, testAndRunTxs(app), []sdk.Invariant{}, numBlocks, blockSize, commit, lean, onOperation, false, + app.ModuleAccountAddrs(), ) if err != nil { fmt.Println(err) diff --git a/x/auth/legacy/v0_34/types.go b/x/auth/legacy/v0_34/types.go new file mode 100644 index 0000000000..b5699838ee --- /dev/null +++ b/x/auth/legacy/v0_34/types.go @@ -0,0 +1,26 @@ +// DONTCOVER +// nolint +package v0_34 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + ModuleName = "auth" +) + +type ( + Params struct { + MaxMemoCharacters uint64 `json:"max_memo_characters"` + TxSigLimit uint64 `json:"tx_sig_limit"` + TxSizeCostPerByte uint64 `json:"tx_size_cost_per_byte"` + SigVerifyCostED25519 uint64 `json:"sig_verify_cost_ed25519"` + SigVerifyCostSecp256k1 uint64 `json:"sig_verify_cost_secp256k1"` + } + + GenesisState struct { + CollectedFees sdk.Coins `json:"collected_fees"` + Params Params `json:"params"` + } +) diff --git a/x/auth/legacy/v0_36/migrate.go b/x/auth/legacy/v0_36/migrate.go new file mode 100644 index 0000000000..32003f1473 --- /dev/null +++ b/x/auth/legacy/v0_36/migrate.go @@ -0,0 +1,14 @@ +// DONTCOVER +// nolint +package v0_36 + +import ( + v034auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_34" +) + +// Migrate accepts exported genesis state from v0.34 and migrates it to v0.36 +// genesis state. This migration removes the CollectedFees coins from the old +// FeeCollectorKeeper. +func Migrate(oldGenState v034auth.GenesisState) GenesisState { + return NewGenesisState(oldGenState.Params) +} diff --git a/x/auth/legacy/v0_36/migrate_test.go b/x/auth/legacy/v0_36/migrate_test.go new file mode 100644 index 0000000000..c552fc809e --- /dev/null +++ b/x/auth/legacy/v0_36/migrate_test.go @@ -0,0 +1,25 @@ +package v0_36 + +import ( + "github.com/cosmos/cosmos-sdk/types" + v034auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_34" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestMigrate(t *testing.T) { + var genesisState GenesisState + require.NotPanics(t, func() { + genesisState = Migrate(v034auth.GenesisState{ + CollectedFees: types.Coins{ + { + Amount: types.NewInt(10), + Denom: "stake", + }, + }, + Params: v034auth.Params{}, // forwarded structure: filling and checking will be testing a no-op + }) + }) + require.Equal(t, genesisState, GenesisState{Params: v034auth.Params{}}) +} diff --git a/x/auth/legacy/v0_36/types.go b/x/auth/legacy/v0_36/types.go new file mode 100644 index 0000000000..1b720dff2e --- /dev/null +++ b/x/auth/legacy/v0_36/types.go @@ -0,0 +1,19 @@ +// DONTCOVER +// nolint +package v0_36 + +import v034auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_34" + +const ( + ModuleName = "auth" +) + +type ( + GenesisState struct { + Params v034auth.Params `json:"params"` + } +) + +func NewGenesisState(params v034auth.Params) GenesisState { + return GenesisState{params} +} diff --git a/x/auth/types/keys.go b/x/auth/types/keys.go index a0bc7dd06a..149fe2ba51 100644 --- a/x/auth/types/keys.go +++ b/x/auth/types/keys.go @@ -12,7 +12,7 @@ const ( StoreKey = "acc" // FeeCollectorName the root string for the fee collector account address - FeeCollectorName = "FeeCollector" + FeeCollectorName = "fee_collector" // QuerierRoute is the querier route for acc QuerierRoute = StoreKey diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index 00f6e2b2b5..1e7a9aaced 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -157,19 +157,9 @@ func (k Keeper) withdrawDelegationRewards(ctx sdk.Context, val exported.Validato val.GetOperator(), del.GetDelegatorAddr(), rewardsRaw, rewards)) } - // decrement reference count of starting period - startingInfo := k.GetDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr()) - startingPeriod := startingInfo.PreviousPeriod - k.decrementReferenceCount(ctx, del.GetValidatorAddr(), startingPeriod) - // truncate coins, return remainder to community pool coins, remainder := rewards.TruncateDecimal() - k.SetValidatorOutstandingRewards(ctx, del.GetValidatorAddr(), outstanding.Sub(rewards)) - feePool := k.GetFeePool(ctx) - feePool.CommunityPool = feePool.CommunityPool.Add(remainder) - k.SetFeePool(ctx, feePool) - // add coins to user account if !coins.IsZero() { withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, del.GetDelegatorAddr()) @@ -179,6 +169,18 @@ func (k Keeper) withdrawDelegationRewards(ctx sdk.Context, val exported.Validato } } + // update the outstanding rewards and the community pool only if the + // transaction was successful + k.SetValidatorOutstandingRewards(ctx, del.GetValidatorAddr(), outstanding.Sub(rewards)) + feePool := k.GetFeePool(ctx) + feePool.CommunityPool = feePool.CommunityPool.Add(remainder) + k.SetFeePool(ctx, feePool) + + // decrement reference count of starting period + startingInfo := k.GetDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr()) + startingPeriod := startingInfo.PreviousPeriod + k.decrementReferenceCount(ctx, del.GetValidatorAddr(), startingPeriod) + // remove delegator starting info k.DeleteDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr()) diff --git a/x/distribution/legacy/v0_36/migrate.go b/x/distribution/legacy/v0_36/migrate.go index 4898d5be6e..e2f3c8119d 100644 --- a/x/distribution/legacy/v0_36/migrate.go +++ b/x/distribution/legacy/v0_36/migrate.go @@ -8,68 +8,6 @@ import ( // genesis state. All entries are identical except for validator slashing events // which now include the period. func Migrate(oldGenState v034distr.GenesisState) GenesisState { - feePool := FeePool{CommunityPool: oldGenState.FeePool.CommunityPool} - - dwifos := make([]DelegatorWithdrawInfo, len(oldGenState.DelegatorWithdrawInfos)) - for i, info := range oldGenState.DelegatorWithdrawInfos { - dwifos[i] = DelegatorWithdrawInfo{ - DelegatorAddress: info.DelegatorAddress, - WithdrawAddress: info.WithdrawAddress, - } - } - - outRewards := make([]ValidatorOutstandingRewardsRecord, len(oldGenState.OutstandingRewards)) - for i, rew := range oldGenState.OutstandingRewards { - outRewards[i] = ValidatorOutstandingRewardsRecord{ - ValidatorAddress: rew.ValidatorAddress, - OutstandingRewards: rew.OutstandingRewards, - } - } - - accumComm := make([]ValidatorAccumulatedCommissionRecord, len(oldGenState.ValidatorAccumulatedCommissions)) - for i, comm := range oldGenState.ValidatorAccumulatedCommissions { - accumComm[i] = ValidatorAccumulatedCommissionRecord{ - ValidatorAddress: comm.ValidatorAddress, - Accumulated: comm.Accumulated, - } - } - - histRewards := make([]ValidatorHistoricalRewardsRecord, len(oldGenState.ValidatorHistoricalRewards)) - for i, rew := range oldGenState.ValidatorHistoricalRewards { - histRewards[i] = ValidatorHistoricalRewardsRecord{ - ValidatorAddress: rew.ValidatorAddress, - Period: rew.Period, - Rewards: ValidatorHistoricalRewards{ - CumulativeRewardRatio: rew.Rewards.CumulativeRewardRatio, - ReferenceCount: rew.Rewards.ReferenceCount, - }, - } - } - - currRewards := make([]ValidatorCurrentRewardsRecord, len(oldGenState.ValidatorCurrentRewards)) - for i, rew := range oldGenState.ValidatorCurrentRewards { - currRewards[i] = ValidatorCurrentRewardsRecord{ - ValidatorAddress: rew.ValidatorAddress, - Rewards: ValidatorCurrentRewards{ - Rewards: rew.Rewards.Rewards, - Period: rew.Rewards.Period, - }, - } - } - - delStartingInfos := make([]DelegatorStartingInfoRecord, len(oldGenState.DelegatorStartingInfos)) - for i, delInfo := range oldGenState.DelegatorStartingInfos { - delStartingInfos[i] = DelegatorStartingInfoRecord{ - DelegatorAddress: delInfo.DelegatorAddress, - ValidatorAddress: delInfo.ValidatorAddress, - StartingInfo: DelegatorStartingInfo{ - PreviousPeriod: delInfo.StartingInfo.PreviousPeriod, - Stake: delInfo.StartingInfo.Stake, - Height: delInfo.StartingInfo.Height, - }, - } - } - // migrate slash events which now have the period included slashEvents := make([]ValidatorSlashEventRecord, len(oldGenState.ValidatorSlashEvents)) for i, se := range oldGenState.ValidatorSlashEvents { @@ -77,17 +15,16 @@ func Migrate(oldGenState v034distr.GenesisState) GenesisState { ValidatorAddress: se.ValidatorAddress, Height: se.Height, Period: se.Event.ValidatorPeriod, - Event: ValidatorSlashEvent{ - ValidatorPeriod: se.Event.ValidatorPeriod, - Fraction: se.Event.Fraction, - }, + Event: se.Event, } } return NewGenesisState( - feePool, oldGenState.CommunityTax, oldGenState.BaseProposerReward, + oldGenState.FeePool, oldGenState.CommunityTax, oldGenState.BaseProposerReward, oldGenState.BonusProposerReward, oldGenState.WithdrawAddrEnabled, - dwifos, oldGenState.PreviousProposer, outRewards, accumComm, - histRewards, currRewards, delStartingInfos, slashEvents, + oldGenState.DelegatorWithdrawInfos, oldGenState.PreviousProposer, + oldGenState.OutstandingRewards, oldGenState.ValidatorAccumulatedCommissions, + oldGenState.ValidatorHistoricalRewards, oldGenState.ValidatorCurrentRewards, + oldGenState.DelegatorStartingInfos, slashEvents, ) } diff --git a/x/distribution/legacy/v0_36/migrate_test.go b/x/distribution/legacy/v0_36/migrate_test.go new file mode 100644 index 0000000000..299b689c3c --- /dev/null +++ b/x/distribution/legacy/v0_36/migrate_test.go @@ -0,0 +1,63 @@ +package v0_36 + +import ( + "github.com/cosmos/cosmos-sdk/types" + v034distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_34" + "github.com/tendermint/tendermint/crypto/secp256k1" + "testing" + + "github.com/stretchr/testify/require" +) + +var ( + priv = secp256k1.GenPrivKey() + addr = types.AccAddress(priv.PubKey().Address()) + valAddr, _ = types.ValAddressFromBech32(addr.String()) + + event = v034distr.ValidatorSlashEvent{ + ValidatorPeriod: 1, + Fraction: types.Dec{}, + } +) + +func TestMigrate(t *testing.T) { + var genesisState GenesisState + require.NotPanics(t, func() { + genesisState = Migrate(v034distr.GenesisState{ + ValidatorSlashEvents: []v034distr.ValidatorSlashEventRecord{ + { + ValidatorAddress: valAddr, + Height: 1, + Event: event, + }, + }, + }) + }) + + require.Equal(t, genesisState.ValidatorSlashEvents[0], ValidatorSlashEventRecord{ + ValidatorAddress: valAddr, + Height: 1, + Period: event.ValidatorPeriod, + Event: event, + }) +} + +func TestMigrateEmptyRecord(t *testing.T) { + var genesisState GenesisState + + require.NotPanics(t, func() { + genesisState = Migrate(v034distr.GenesisState{ + ValidatorSlashEvents: []v034distr.ValidatorSlashEventRecord{{}}, + }) + }) + + require.Equal(t, genesisState.ValidatorSlashEvents[0], ValidatorSlashEventRecord{ + ValidatorAddress: valAddr, + Height: 0, + Period: 0, + Event: v034distr.ValidatorSlashEvent{ + ValidatorPeriod: 0, + Fraction: types.Dec{}, + }, + }) +} diff --git a/x/distribution/legacy/v0_36/types.go b/x/distribution/legacy/v0_36/types.go index b8b29244de..d1f02b6296 100644 --- a/x/distribution/legacy/v0_36/types.go +++ b/x/distribution/legacy/v0_36/types.go @@ -4,6 +4,7 @@ package v0_36 import ( sdk "github.com/cosmos/cosmos-sdk/types" + v034distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_34" ) // ---------------------------------------------------------------------------- @@ -17,93 +18,36 @@ const ( type ( ValidatorAccumulatedCommission = sdk.DecCoins - ValidatorCurrentRewards struct { - Rewards sdk.DecCoins `json:"rewards"` - Period uint64 `json:"period"` - } - - ValidatorHistoricalRewards struct { - CumulativeRewardRatio sdk.DecCoins `json:"cumulative_reward_ratio"` - ReferenceCount uint16 `json:"reference_count"` - } - - DelegatorWithdrawInfo struct { - DelegatorAddress sdk.AccAddress `json:"delegator_address"` - WithdrawAddress sdk.AccAddress `json:"withdraw_address"` - } - - ValidatorOutstandingRewardsRecord struct { - ValidatorAddress sdk.ValAddress `json:"validator_address"` - OutstandingRewards sdk.DecCoins `json:"outstanding_rewards"` - } - - ValidatorAccumulatedCommissionRecord struct { - ValidatorAddress sdk.ValAddress `json:"validator_address"` - Accumulated ValidatorAccumulatedCommission `json:"accumulated"` - } - - ValidatorHistoricalRewardsRecord struct { - ValidatorAddress sdk.ValAddress `json:"validator_address"` - Period uint64 `json:"period"` - Rewards ValidatorHistoricalRewards `json:"rewards"` - } - - ValidatorCurrentRewardsRecord struct { - ValidatorAddress sdk.ValAddress `json:"validator_address"` - Rewards ValidatorCurrentRewards `json:"rewards"` - } - - DelegatorStartingInfo struct { - PreviousPeriod uint64 `json:"previous_period"` - Stake sdk.Dec `json:"stake"` - Height uint64 `json:"creation_height"` - } - - DelegatorStartingInfoRecord struct { - DelegatorAddress sdk.AccAddress `json:"delegator_address"` - ValidatorAddress sdk.ValAddress `json:"validator_address"` - StartingInfo DelegatorStartingInfo `json:"starting_info"` - } - - ValidatorSlashEvent struct { - ValidatorPeriod uint64 `json:"validator_period"` - Fraction sdk.Dec `json:"fraction"` - } - ValidatorSlashEventRecord struct { - ValidatorAddress sdk.ValAddress `json:"validator_address"` - Height uint64 `json:"height"` - Period uint64 `json:"period"` - Event ValidatorSlashEvent `json:"validator_slash_event"` - } - - FeePool struct { - CommunityPool sdk.DecCoins `json:"community_pool"` + ValidatorAddress sdk.ValAddress `json:"validator_address"` + Height uint64 `json:"height"` + Period uint64 `json:"period"` + Event v034distr.ValidatorSlashEvent `json:"validator_slash_event"` } GenesisState struct { - FeePool FeePool `json:"fee_pool"` - CommunityTax sdk.Dec `json:"community_tax"` - BaseProposerReward sdk.Dec `json:"base_proposer_reward"` - BonusProposerReward sdk.Dec `json:"bonus_proposer_reward"` - WithdrawAddrEnabled bool `json:"withdraw_addr_enabled"` - DelegatorWithdrawInfos []DelegatorWithdrawInfo `json:"delegator_withdraw_infos"` - PreviousProposer sdk.ConsAddress `json:"previous_proposer"` - OutstandingRewards []ValidatorOutstandingRewardsRecord `json:"outstanding_rewards"` - ValidatorAccumulatedCommissions []ValidatorAccumulatedCommissionRecord `json:"validator_accumulated_commissions"` - ValidatorHistoricalRewards []ValidatorHistoricalRewardsRecord `json:"validator_historical_rewards"` - ValidatorCurrentRewards []ValidatorCurrentRewardsRecord `json:"validator_current_rewards"` - DelegatorStartingInfos []DelegatorStartingInfoRecord `json:"delegator_starting_infos"` - ValidatorSlashEvents []ValidatorSlashEventRecord `json:"validator_slash_events"` + FeePool v034distr.FeePool `json:"fee_pool"` + CommunityTax sdk.Dec `json:"community_tax"` + BaseProposerReward sdk.Dec `json:"base_proposer_reward"` + BonusProposerReward sdk.Dec `json:"bonus_proposer_reward"` + WithdrawAddrEnabled bool `json:"withdraw_addr_enabled"` + DelegatorWithdrawInfos []v034distr.DelegatorWithdrawInfo `json:"delegator_withdraw_infos"` + PreviousProposer sdk.ConsAddress `json:"previous_proposer"` + OutstandingRewards []v034distr.ValidatorOutstandingRewardsRecord `json:"outstanding_rewards"` + ValidatorAccumulatedCommissions []v034distr.ValidatorAccumulatedCommissionRecord `json:"validator_accumulated_commissions"` + ValidatorHistoricalRewards []v034distr.ValidatorHistoricalRewardsRecord `json:"validator_historical_rewards"` + ValidatorCurrentRewards []v034distr.ValidatorCurrentRewardsRecord `json:"validator_current_rewards"` + DelegatorStartingInfos []v034distr.DelegatorStartingInfoRecord `json:"delegator_starting_infos"` + ValidatorSlashEvents []ValidatorSlashEventRecord `json:"validator_slash_events"` } ) func NewGenesisState( - feePool FeePool, communityTax, baseProposerReward, bonusProposerReward sdk.Dec, - withdrawAddrEnabled bool, dwis []DelegatorWithdrawInfo, pp sdk.ConsAddress, - r []ValidatorOutstandingRewardsRecord, acc []ValidatorAccumulatedCommissionRecord, - historical []ValidatorHistoricalRewardsRecord, cur []ValidatorCurrentRewardsRecord, - dels []DelegatorStartingInfoRecord, slashes []ValidatorSlashEventRecord, + feePool v034distr.FeePool, communityTax, baseProposerReward, bonusProposerReward sdk.Dec, + withdrawAddrEnabled bool, dwis []v034distr.DelegatorWithdrawInfo, pp sdk.ConsAddress, + r []v034distr.ValidatorOutstandingRewardsRecord, acc []v034distr.ValidatorAccumulatedCommissionRecord, + historical []v034distr.ValidatorHistoricalRewardsRecord, cur []v034distr.ValidatorCurrentRewardsRecord, + dels []v034distr.DelegatorStartingInfoRecord, slashes []ValidatorSlashEventRecord, ) GenesisState { return GenesisState{ diff --git a/x/genaccounts/legacy/v0_34/types.go b/x/genaccounts/legacy/v0_34/types.go new file mode 100644 index 0000000000..ee1bd419ab --- /dev/null +++ b/x/genaccounts/legacy/v0_34/types.go @@ -0,0 +1,28 @@ +// DONTCOVER +// nolint +package v0_34 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + ModuleName = "accounts" +) + +type ( + GenesisAccount struct { + Address sdk.AccAddress `json:"address"` + Coins sdk.Coins `json:"coins"` + Sequence uint64 `json:"sequence_number"` + AccountNumber uint64 `json:"account_number"` + + OriginalVesting sdk.Coins `json:"original_vesting"` + DelegatedFree sdk.Coins `json:"delegated_free"` + DelegatedVesting sdk.Coins `json:"delegated_vesting"` + StartTime int64 `json:"start_time"` + EndTime int64 `json:"end_time"` + } + + GenesisState []GenesisAccount +) diff --git a/x/genaccounts/legacy/v0_36/migrate.go b/x/genaccounts/legacy/v0_36/migrate.go new file mode 100644 index 0000000000..d69aece981 --- /dev/null +++ b/x/genaccounts/legacy/v0_36/migrate.go @@ -0,0 +1,179 @@ +// DONTCOVER +// nolint +package v0_36 + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + v034distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_34" + v034accounts "github.com/cosmos/cosmos-sdk/x/genaccounts/legacy/v0_34" + v034gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v0_34" + v034staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_34" + + "github.com/tendermint/tendermint/crypto" +) + +const ( + notBondedPoolName = "not_bonded_tokens_pool" + bondedPoolName = "bonded_tokens_pool" + feeCollectorName = "fee_collector" + mintModuleName = "mint" + + basic = "basic" + minter = "minter" + burner = "burner" + staking = "staking" +) + +// Migrate accepts exported genesis state from v0.34 and migrates it to v0.36 +// genesis state. It deletes the governance base accounts and creates the new module accounts. +// The remaining accounts are updated to the new GenesisAccount type from 0.36 +func Migrate( + oldGenState v034accounts.GenesisState, fees sdk.Coins, communityPool sdk.DecCoins, + deposits []v034gov.DepositWithMetadata, vals v034staking.Validators, ubds []v034staking.UnbondingDelegation, + valOutRewards []v034distr.ValidatorOutstandingRewardsRecord, bondDenom, distrModuleName, govModuleName string, +) GenesisState { + + depositedCoinsAccAddr := sdk.AccAddress(crypto.AddressHash([]byte("govDepositedCoins"))) + burnedDepositCoinsAccAddr := sdk.AccAddress(crypto.AddressHash([]byte("govBurnedDepositCoins"))) + + bondedAmt := sdk.ZeroInt() + notBondedAmt := sdk.ZeroInt() + + // remove the two previous governance base accounts for deposits and burned + // coins from rejected proposals add six new module accounts: + // distribution, gov, mint, fee collector, bonded and not bonded pool + var ( + newGenState GenesisState + govCoins sdk.Coins + extraAccounts = 6 + ) + + for _, acc := range oldGenState { + switch { + case acc.Address.Equals(depositedCoinsAccAddr): + // remove gov deposits base account + govCoins = acc.Coins + extraAccounts -= 1 + + case acc.Address.Equals(burnedDepositCoinsAccAddr): + // remove gov burned deposits base account + extraAccounts -= 1 + + default: + newGenState = append( + newGenState, + NewGenesisAccount( + acc.Address, acc.Coins, acc.Sequence, + acc.OriginalVesting, acc.DelegatedFree, acc.DelegatedVesting, + acc.StartTime, acc.EndTime, "", []string{}, + ), + ) + } + } + + var expDeposits sdk.Coins + for _, deposit := range deposits { + expDeposits = expDeposits.Add(deposit.Deposit.Amount) + } + + if !expDeposits.IsEqual(govCoins) { + panic( + fmt.Sprintf( + "pre migration deposit base account coins ≠ stored deposits coins (%s ≠ %s)", + expDeposits.String(), govCoins.String(), + ), + ) + } + + // get staking module accounts coins + for _, validator := range vals { + switch validator.Status { + case sdk.Bonded: + bondedAmt = bondedAmt.Add(validator.Tokens) + + case sdk.Unbonding, sdk.Unbonded: + notBondedAmt = notBondedAmt.Add(validator.Tokens) + + default: + panic("invalid validator status") + } + } + + for _, ubd := range ubds { + for _, entry := range ubd.Entries { + notBondedAmt = notBondedAmt.Add(entry.Balance) + } + } + + bondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, bondedAmt)) + notBondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, notBondedAmt)) + + // get distr module account coins + var distrDecCoins sdk.DecCoins + for _, reward := range valOutRewards { + distrDecCoins = distrDecCoins.Add(reward.OutstandingRewards) + } + + distrCoins, _ := distrDecCoins.Add(communityPool).TruncateDecimal() + + // get module account addresses + feeCollectorAddr := sdk.AccAddress(crypto.AddressHash([]byte(feeCollectorName))) + govAddr := sdk.AccAddress(crypto.AddressHash([]byte(govModuleName))) + bondedAddr := sdk.AccAddress(crypto.AddressHash([]byte(bondedPoolName))) + notBondedAddr := sdk.AccAddress(crypto.AddressHash([]byte(notBondedPoolName))) + distrAddr := sdk.AccAddress(crypto.AddressHash([]byte(distrModuleName))) + mintAddr := sdk.AccAddress(crypto.AddressHash([]byte(mintModuleName))) + + // create module genesis accounts + feeCollectorModuleAcc := NewGenesisAccount( + feeCollectorAddr, fees, 0, + sdk.Coins{}, sdk.Coins{}, sdk.Coins{}, + 0, 0, feeCollectorName, []string{basic}, + ) + govModuleAcc := NewGenesisAccount( + govAddr, govCoins, 0, + sdk.Coins{}, sdk.Coins{}, sdk.Coins{}, + 0, 0, govModuleName, []string{burner}, + ) + distrModuleAcc := NewGenesisAccount( + distrAddr, distrCoins, 0, + sdk.Coins{}, sdk.Coins{}, sdk.Coins{}, + 0, 0, distrModuleName, []string{basic}, + ) + bondedModuleAcc := NewGenesisAccount( + bondedAddr, bondedCoins, 0, + sdk.Coins{}, sdk.Coins{}, sdk.Coins{}, + 0, 0, bondedPoolName, []string{burner, staking}, + ) + notBondedModuleAcc := NewGenesisAccount( + notBondedAddr, notBondedCoins, 0, + sdk.Coins{}, sdk.Coins{}, sdk.Coins{}, + 0, 0, notBondedPoolName, []string{burner, staking}, + ) + mintModuleAcc := NewGenesisAccount( + mintAddr, sdk.Coins{}, 0, + sdk.Coins{}, sdk.Coins{}, sdk.Coins{}, + 0, 0, mintModuleName, []string{minter}, + ) + + newGenState = append( + newGenState, + []GenesisAccount{ + feeCollectorModuleAcc, govModuleAcc, distrModuleAcc, + bondedModuleAcc, notBondedModuleAcc, mintModuleAcc, + }..., + ) + + // verify the total number of accounts is correct + if len(newGenState) != len(oldGenState)+extraAccounts { + panic( + fmt.Sprintf( + "invalid total number of genesis accounts; got: %d, expected: %d", + len(newGenState), len(oldGenState)+extraAccounts), + ) + } + + return newGenState +} diff --git a/x/genaccounts/legacy/v0_36/migrate_test.go b/x/genaccounts/legacy/v0_36/migrate_test.go new file mode 100644 index 0000000000..e3e3b9a900 --- /dev/null +++ b/x/genaccounts/legacy/v0_36/migrate_test.go @@ -0,0 +1,123 @@ +package v0_36 + +import ( + "github.com/cosmos/cosmos-sdk/types" + v034distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_34" + v034accounts "github.com/cosmos/cosmos-sdk/x/genaccounts/legacy/v0_34" + v034gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v0_34" + v034staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_34" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/secp256k1" + "testing" + + "github.com/stretchr/testify/require" +) + +var ( + priv = secp256k1.GenPrivKey() + addr = types.AccAddress(priv.PubKey().Address()) + depositedCoinsAccAddr = types.AccAddress(crypto.AddressHash([]byte("govDepositedCoins"))) + burnedDepositCoinsAccAddr = types.AccAddress(crypto.AddressHash([]byte("govBurnedDepositCoins"))) + + coins = types.Coins{types.NewInt64Coin(types.DefaultBondDenom, 10)} + halfCoins = types.Coins{types.NewInt64Coin(types.DefaultBondDenom, 5)} + + accountDeposited = v034accounts.GenesisAccount{ + Address: depositedCoinsAccAddr, + Coins: coins, + Sequence: 1, + AccountNumber: 1, + + OriginalVesting: coins, + DelegatedFree: coins, + DelegatedVesting: coins, + StartTime: 0, + EndTime: 0, + } + + accountBurned = v034accounts.GenesisAccount{ + Address: burnedDepositCoinsAccAddr, + Coins: coins, + Sequence: 2, + AccountNumber: 2, + + OriginalVesting: coins, + DelegatedFree: coins, + DelegatedVesting: coins, + StartTime: 0, + EndTime: 0, + } + + deposit = v034gov.DepositWithMetadata{ + ProposalID: 1, + Deposit: v034gov.Deposit{ + ProposalID: 1, + Depositor: addr, + Amount: coins, + }, + } +) + +func TestMigrateEmptyRecord(t *testing.T) { + + type args struct { + accounts v034accounts.GenesisState + deposits []v034gov.DepositWithMetadata + } + tests := []struct { + name string + args args + }{ + {"No Accounts", args{v034accounts.GenesisState{}, []v034gov.DepositWithMetadata{}}}, + {"Deposited account", args{v034accounts.GenesisState{accountDeposited}, []v034gov.DepositWithMetadata{deposit}}}, + {"Burned account", args{v034accounts.GenesisState{accountBurned}, []v034gov.DepositWithMetadata{}}}, + {"Burned and deposited accounts", args{v034accounts.GenesisState{accountDeposited, accountBurned}, []v034gov.DepositWithMetadata{deposit}}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.NotPanics(t, func() { + Migrate( + tt.args.accounts, + types.Coins{}, + types.DecCoins{}, + tt.args.deposits, + v034staking.Validators{}, + []v034staking.UnbondingDelegation{}, + []v034distr.ValidatorOutstandingRewardsRecord{}, + types.DefaultBondDenom, + v034distr.ModuleName, + v034gov.ModuleName, + ) + }) + }) + } +} + +func TestMigrateWrongDeposit(t *testing.T) { + require.Panics(t, func() { + Migrate( + v034accounts.GenesisState{ + accountDeposited, + accountBurned, + }, + types.Coins{}, + types.DecCoins{}, + []v034gov.DepositWithMetadata{ + { + ProposalID: 1, + Deposit: v034gov.Deposit{ + ProposalID: 1, + Depositor: addr, + Amount: halfCoins, + }, + }, + }, + v034staking.Validators{}, + []v034staking.UnbondingDelegation{}, + []v034distr.ValidatorOutstandingRewardsRecord{}, + types.DefaultBondDenom, + v034distr.ModuleName, + v034gov.ModuleName, + ) + }) +} diff --git a/x/genaccounts/legacy/v0_36/types.go b/x/genaccounts/legacy/v0_36/types.go new file mode 100644 index 0000000000..54596f0a63 --- /dev/null +++ b/x/genaccounts/legacy/v0_36/types.go @@ -0,0 +1,53 @@ +// DONTCOVER +// nolint +package v0_36 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + ModuleName = "accounts" +) + +type ( + GenesisAccount struct { + Address sdk.AccAddress `json:"address" yaml:"address"` + Coins sdk.Coins `json:"coins" yaml:"coins"` + Sequence uint64 `json:"sequence_number" yaml:"sequence_number"` + AccountNumber uint64 `json:"account_number" yaml:"account_number"` + + OriginalVesting sdk.Coins `json:"original_vesting" yaml:"original_vesting"` + DelegatedFree sdk.Coins `json:"delegated_free" yaml:"delegated_free"` + DelegatedVesting sdk.Coins `json:"delegated_vesting" yaml:"delegated_vesting"` + StartTime int64 `json:"start_time" yaml:"start_time"` + EndTime int64 `json:"end_time" yaml:"end_time"` + + ModuleName string `json:"module_name" yaml:"module_name"` + ModulePermissions []string `json:"module_permissions" yaml:"module_permissions"` + } + + GenesisState []GenesisAccount +) + +// NewGenesisAccount creates a new GenesisAccount object +func NewGenesisAccount( + address sdk.AccAddress, coins sdk.Coins, sequence uint64, + vestingAmount, delFree, delVesting sdk.Coins, vestingStartTime, vestingEndTime int64, + module string, permissions []string, +) GenesisAccount { + + return GenesisAccount{ + Address: address, + Coins: coins, + Sequence: sequence, + AccountNumber: 0, // ignored set by the account keeper during InitGenesis + OriginalVesting: vestingAmount, + DelegatedFree: delFree, + DelegatedVesting: delVesting, + StartTime: vestingStartTime, + EndTime: vestingEndTime, + ModuleName: module, + ModulePermissions: permissions, + } +} diff --git a/x/genutil/legacy/v036/migrate.go b/x/genutil/legacy/v036/migrate.go index c25866ae2d..fcab4a666f 100644 --- a/x/genutil/legacy/v036/migrate.go +++ b/x/genutil/legacy/v036/migrate.go @@ -2,11 +2,18 @@ package v036 import ( "github.com/cosmos/cosmos-sdk/codec" + v034auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_34" + v036auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_36" v034distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_34" v036distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_36" + v034genAccounts "github.com/cosmos/cosmos-sdk/x/genaccounts/legacy/v0_34" + v036genAccounts "github.com/cosmos/cosmos-sdk/x/genaccounts/legacy/v0_36" "github.com/cosmos/cosmos-sdk/x/genutil" - v034gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v034" - v036gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v036" + v034gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v0_34" + v036gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v0_36" + v034staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_34" + v036staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_36" + v036supply "github.com/cosmos/cosmos-sdk/x/supply/legacy/v0_36" ) // Migrate migrates exported state from v0.34 to a v0.36 genesis state. @@ -16,17 +23,52 @@ func Migrate(appState genutil.AppMap) genutil.AppMap { v036Codec := codec.New() codec.RegisterCrypto(v036Codec) + v034gov.RegisterCodec(v034Codec) + v036gov.RegisterCodec(v036Codec) - // migrate genesis state + // migrate genesis accounts state + if appState[v034genAccounts.ModuleName] != nil { + var genAccs v034genAccounts.GenesisState + v034Codec.MustUnmarshalJSON(appState[v034genAccounts.ModuleName], &genAccs) + + var authGenState v034auth.GenesisState + v034Codec.MustUnmarshalJSON(appState[v034auth.ModuleName], &authGenState) + + var govGenState v034gov.GenesisState + v034Codec.MustUnmarshalJSON(appState[v034gov.ModuleName], &govGenState) + + var distrGenState v034distr.GenesisState + v034Codec.MustUnmarshalJSON(appState[v034distr.ModuleName], &distrGenState) + + var stakingGenState v034staking.GenesisState + v034Codec.MustUnmarshalJSON(appState[v034staking.ModuleName], &stakingGenState) + + delete(appState, v034genAccounts.ModuleName) // delete old key in case the name changed + appState[v036genAccounts.ModuleName] = v036Codec.MustMarshalJSON( + v036genAccounts.Migrate( + genAccs, authGenState.CollectedFees, distrGenState.FeePool.CommunityPool, govGenState.Deposits, + stakingGenState.Validators, stakingGenState.UnbondingDelegations, distrGenState.OutstandingRewards, + stakingGenState.Params.BondDenom, v036distr.ModuleName, v036gov.ModuleName, + ), + ) + } + + // migrate auth state + if appState[v034auth.ModuleName] != nil { + var authGenState v034auth.GenesisState + v034Codec.MustUnmarshalJSON(appState[v034auth.ModuleName], &authGenState) + + delete(appState, v034auth.ModuleName) // delete old key in case the name changed + appState[v036auth.ModuleName] = v036Codec.MustMarshalJSON(v036auth.Migrate(authGenState)) + } + + // migrate gov state if appState[v034gov.ModuleName] != nil { - v034gov.RegisterCodec(v034Codec) - v036gov.RegisterCodec(v036Codec) - - var govState v034gov.GenesisState - v034Codec.MustUnmarshalJSON(appState[v034gov.ModuleName], &govState) + var govGenState v034gov.GenesisState + v034Codec.MustUnmarshalJSON(appState[v034gov.ModuleName], &govGenState) delete(appState, v034gov.ModuleName) // delete old key in case the name changed - appState[v036gov.ModuleName] = v036Codec.MustMarshalJSON(v036gov.MigrateGovernance(govState)) + appState[v036gov.ModuleName] = v036Codec.MustMarshalJSON(v036gov.Migrate(govGenState)) } // migrate distribution state @@ -38,5 +80,16 @@ func Migrate(appState genutil.AppMap) genutil.AppMap { appState[v036distr.ModuleName] = v036Codec.MustMarshalJSON(v036distr.Migrate(slashingGenState)) } + // migrate staking state + if appState[v034staking.ModuleName] != nil { + var stakingGenState v034staking.GenesisState + v034Codec.MustUnmarshalJSON(appState[v034staking.ModuleName], &stakingGenState) + + delete(appState, v034staking.ModuleName) // delete old key in case the name changed + appState[v036staking.ModuleName] = v036Codec.MustMarshalJSON(v036staking.Migrate(stakingGenState)) + } + + appState[v036supply.ModuleName] = v036Codec.MustMarshalJSON(v036supply.EmptyGenesisState()) + return appState } diff --git a/x/gov/legacy/v034/types.go b/x/gov/legacy/v034/types.go deleted file mode 100644 index e103d084e3..0000000000 --- a/x/gov/legacy/v034/types.go +++ /dev/null @@ -1,513 +0,0 @@ -package v034 - -import ( - "encoding/json" - "fmt" - "strings" - "time" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// Keys -const ( - // ModuleName is the name of the module - ModuleName = "gov" - - // StoreKey is the store key string for gov - StoreKey = ModuleName - - // RouterKey is the message route for gov - RouterKey = ModuleName - - // QuerierRoute is the querier route for gov - QuerierRoute = ModuleName - - // DefaultParamspace default name for parameter store - DefaultParamspace = ModuleName -) - -type GenesisState struct { - StartingProposalID uint64 `json:"starting_proposal_id"` - Deposits []DepositWithMetadata `json:"deposits"` - Votes []VoteWithMetadata `json:"votes"` - Proposals []Proposal `json:"proposals"` - DepositParams DepositParams `json:"deposit_params"` - VotingParams VotingParams `json:"voting_params"` - TallyParams TallyParams `json:"tally_params"` -} - -type DepositWithMetadata struct { - ProposalID uint64 `json:"proposal_id"` - Deposit Deposit `json:"deposit"` -} - -type VoteWithMetadata struct { - ProposalID uint64 `json:"proposal_id"` - Vote Vote `json:"vote"` -} - -type Deposit struct { - ProposalID uint64 `json:"proposal_id"` // proposalID of the proposal - Depositor sdk.AccAddress `json:"depositor"` // Address of the depositor - Amount sdk.Coins `json:"amount"` // Deposit amount -} - -type Deposits []Deposit - -type Vote struct { - ProposalID uint64 `json:"proposal_id"` // proposalID of the proposal - Voter sdk.AccAddress `json:"voter"` // address of the voter - Option VoteOption `json:"option"` // option from OptionSet chosen by the voter -} - -type Votes []Vote - -// Param around deposits for governance -type DepositParams struct { - MinDeposit sdk.Coins `json:"min_deposit,omitempty"` // Minimum deposit for a proposal to enter voting period. - MaxDepositPeriod time.Duration `json:"max_deposit_period,omitempty"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months -} - -type TallyParams struct { - Quorum sdk.Dec `json:"quorum,omitempty"` // Minimum percentage of total stake needed to vote for a result to be considered valid - Threshold sdk.Dec `json:"threshold,omitempty"` // Minimum proportion of Yes votes for proposal to pass. Initial value: 0.5 - Veto sdk.Dec `json:"veto,omitempty"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3 -} - -type VotingParams struct { - VotingPeriod time.Duration `json:"voting_period,omitempty"` // Length of the voting period. -} - -type TallyResult struct { - Yes sdk.Int `json:"yes"` - Abstain sdk.Int `json:"abstain"` - No sdk.Int `json:"no"` - NoWithVeto sdk.Int `json:"no_with_veto"` -} - -// ---------------------------------------------------------------------------- -// ProposalStatus -// ---------------------------------------------------------------------------- - -// ProposalStatus is a type alias that represents a proposal status as a byte -type ProposalStatus byte - -//nolint -const ( - StatusNil ProposalStatus = 0x00 - StatusDepositPeriod ProposalStatus = 0x01 - StatusVotingPeriod ProposalStatus = 0x02 - StatusPassed ProposalStatus = 0x03 - StatusRejected ProposalStatus = 0x04 - StatusFailed ProposalStatus = 0x05 -) - -// ProposalStatusToString turns a string into a ProposalStatus -func ProposalStatusFromString(str string) (ProposalStatus, error) { - switch str { - case "DepositPeriod": - return StatusDepositPeriod, nil - - case "VotingPeriod": - return StatusVotingPeriod, nil - - case "Passed": - return StatusPassed, nil - - case "Rejected": - return StatusRejected, nil - - case "Failed": - return StatusFailed, nil - - case "": - return StatusNil, nil - - default: - return ProposalStatus(0xff), fmt.Errorf("'%s' is not a valid proposal status", str) - } -} - -// Marshal needed for protobuf compatibility -func (status ProposalStatus) Marshal() ([]byte, error) { - return []byte{byte(status)}, nil -} - -// Unmarshal needed for protobuf compatibility -func (status *ProposalStatus) Unmarshal(data []byte) error { - *status = ProposalStatus(data[0]) - return nil -} - -// Marshals to JSON using string -func (status ProposalStatus) MarshalJSON() ([]byte, error) { - return json.Marshal(status.String()) -} - -// Unmarshals from JSON assuming Bech32 encoding -func (status *ProposalStatus) UnmarshalJSON(data []byte) error { - var s string - err := json.Unmarshal(data, &s) - if err != nil { - return err - } - - bz2, err := ProposalStatusFromString(s) - if err != nil { - return err - } - - *status = bz2 - return nil -} - -// String implements the Stringer interface. -func (status ProposalStatus) String() string { - switch status { - case StatusDepositPeriod: - return "DepositPeriod" - - case StatusVotingPeriod: - return "VotingPeriod" - - case StatusPassed: - return "Passed" - - case StatusRejected: - return "Rejected" - - case StatusFailed: - return "Failed" - - default: - return "" - } -} - -// Format implements the fmt.Formatter interface. -// nolint: errcheck -func (status ProposalStatus) Format(s fmt.State, verb rune) { - switch verb { - case 's': - s.Write([]byte(status.String())) - default: - // TODO: Do this conversion more directly - s.Write([]byte(fmt.Sprintf("%v", byte(status)))) - } -} - -// ---------------------------------------------------------------------------- -// VoteOption -// ---------------------------------------------------------------------------- - -type VoteOption byte - -// Vote options -const ( - OptionEmpty VoteOption = 0x00 - OptionYes VoteOption = 0x01 - OptionAbstain VoteOption = 0x02 - OptionNo VoteOption = 0x03 - OptionNoWithVeto VoteOption = 0x04 -) - -// VoteOptionFromString returns a VoteOption from a string. It returns an error -// if the string is invalid. -func VoteOptionFromString(str string) (VoteOption, error) { - switch str { - case "Yes": - return OptionYes, nil - - case "Abstain": - return OptionAbstain, nil - - case "No": - return OptionNo, nil - - case "NoWithVeto": - return OptionNoWithVeto, nil - - default: - return VoteOption(0xff), fmt.Errorf("'%s' is not a valid vote option", str) - } -} - -// Marshal needed for protobuf compatibility. -func (vo VoteOption) Marshal() ([]byte, error) { - return []byte{byte(vo)}, nil -} - -// Unmarshal needed for protobuf compatibility. -func (vo *VoteOption) Unmarshal(data []byte) error { - *vo = VoteOption(data[0]) - return nil -} - -// Marshals to JSON using string. -func (vo VoteOption) MarshalJSON() ([]byte, error) { - return json.Marshal(vo.String()) -} - -// UnmarshalJSON decodes from JSON assuming Bech32 encoding. -func (vo *VoteOption) UnmarshalJSON(data []byte) error { - var s string - err := json.Unmarshal(data, &s) - if err != nil { - return err - } - - bz2, err := VoteOptionFromString(s) - if err != nil { - return err - } - - *vo = bz2 - return nil -} - -// String implements the Stringer interface. -func (vo VoteOption) String() string { - switch vo { - case OptionYes: - return "Yes" - case OptionAbstain: - return "Abstain" - case OptionNo: - return "No" - case OptionNoWithVeto: - return "NoWithVeto" - default: - return "" - } -} - -// Format implements the fmt.Formatter interface. -// nolint: errcheck -func (vo VoteOption) Format(s fmt.State, verb rune) { - switch verb { - case 's': - s.Write([]byte(vo.String())) - default: - s.Write([]byte(fmt.Sprintf("%v", byte(vo)))) - } -} - -// ---------------------------------------------------------------------------- -// Tally -// ---------------------------------------------------------------------------- - -// Equals returns if two proposals are equal. -func (tr TallyResult) Equals(comp TallyResult) bool { - return tr.Yes.Equal(comp.Yes) && - tr.Abstain.Equal(comp.Abstain) && - tr.No.Equal(comp.No) && - tr.NoWithVeto.Equal(comp.NoWithVeto) -} - -func (tr TallyResult) String() string { - return fmt.Sprintf(`Tally Result: - Yes: %s - Abstain: %s - No: %s - NoWithVeto: %s`, tr.Yes, tr.Abstain, tr.No, tr.NoWithVeto) -} - -// ---------------------------------------------------------------------------- -// Proposal -// ---------------------------------------------------------------------------- - -type Proposal struct { - ProposalContent `json:"proposal_content"` // Proposal content interface - - 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 - - SubmitTime time.Time `json:"submit_time"` // Time of the block where TxGovSubmitProposal was included - DepositEndTime time.Time `json:"deposit_end_time"` // Time that the Proposal would expire if deposit amount isn't met - TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit - - VotingStartTime time.Time `json:"voting_start_time"` // Time of the block where MinDeposit was reached. -1 if MinDeposit is not reached - VotingEndTime time.Time `json:"voting_end_time"` // Time that the VotingPeriod for this proposal will end and votes will be tallied -} - -// 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 - Description: %s`, - p.ProposalID, p.GetTitle(), p.ProposalType(), - p.Status, p.SubmitTime, p.DepositEndTime, - p.TotalDeposit, p.VotingStartTime, p.VotingEndTime, p.GetDescription(), - ) -} - -// 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 (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) -} - -// 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 - -// ProposalKind - -// Type that represents Proposal Type as a byte -type ProposalKind byte - -//nolint -const ( - ProposalTypeNil ProposalKind = 0x00 - ProposalTypeText ProposalKind = 0x01 - ProposalTypeParameterChange ProposalKind = 0x02 - ProposalTypeSoftwareUpgrade ProposalKind = 0x03 -) - -// String to proposalType byte. Returns 0xff if invalid. -func ProposalTypeFromString(str string) (ProposalKind, error) { - switch str { - case "Text": - return ProposalTypeText, nil - case "ParameterChange": - return ProposalTypeParameterChange, nil - case "SoftwareUpgrade": - return ProposalTypeSoftwareUpgrade, nil - default: - return ProposalKind(0xff), fmt.Errorf("'%s' is not a valid proposal type", str) - } -} - -// Marshal needed for protobuf compatibility -func (pt ProposalKind) Marshal() ([]byte, error) { - return []byte{byte(pt)}, nil -} - -// Unmarshal needed for protobuf compatibility -func (pt *ProposalKind) Unmarshal(data []byte) error { - *pt = ProposalKind(data[0]) - return nil -} - -// Marshals to JSON using string -func (pt ProposalKind) MarshalJSON() ([]byte, error) { - return json.Marshal(pt.String()) -} - -// Unmarshals from JSON assuming Bech32 encoding -func (pt *ProposalKind) UnmarshalJSON(data []byte) error { - var s string - err := json.Unmarshal(data, &s) - if err != nil { - return err - } - - bz2, err := ProposalTypeFromString(s) - if err != nil { - return err - } - *pt = bz2 - return nil -} - -// Turns VoteOption byte to String -func (pt ProposalKind) String() string { - switch pt { - case ProposalTypeText: - return "Text" - case ProposalTypeParameterChange: - return "ParameterChange" - case ProposalTypeSoftwareUpgrade: - return "SoftwareUpgrade" - default: - return "" - } -} - -// For Printf / Sprintf, returns bech32 when using %s -// nolint: errcheck -func (pt ProposalKind) Format(s fmt.State, verb rune) { - switch verb { - case 's': - s.Write([]byte(pt.String())) - default: - // TODO: Do this conversion more directly - s.Write([]byte(fmt.Sprintf("%v", byte(pt)))) - } -} - -// ---------------------------------------------------------------------------- -// Codec -// ---------------------------------------------------------------------------- - -func RegisterCodec(cdc *codec.Codec) { - cdc.RegisterInterface((*ProposalContent)(nil), nil) - cdc.RegisterConcrete(TextProposal{}, "gov/TextProposal", nil) - cdc.RegisterConcrete(SoftwareUpgradeProposal{}, "gov/SoftwareUpgradeProposal", nil) -} diff --git a/x/gov/legacy/v036/migrate.go b/x/gov/legacy/v036/migrate.go deleted file mode 100644 index 9463bad472..0000000000 --- a/x/gov/legacy/v036/migrate.go +++ /dev/null @@ -1,76 +0,0 @@ -package v036 - -import ( - v034gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v034" -) - -func MigrateGovernance(initialState v034gov.GenesisState) GenesisState { - targetGov := GenesisState{ - StartingProposalID: initialState.StartingProposalID, - DepositParams: DepositParams{ - MinDeposit: initialState.DepositParams.MinDeposit, - MaxDepositPeriod: initialState.DepositParams.MaxDepositPeriod, - }, - TallyParams: TallyParams{ - Quorum: initialState.TallyParams.Quorum, - Threshold: initialState.TallyParams.Threshold, - Veto: initialState.TallyParams.Veto, - }, - VotingParams: VotingParams{ - VotingPeriod: initialState.VotingParams.VotingPeriod, - }, - } - - var deposits Deposits - for _, p := range initialState.Deposits { - deposits = append(deposits, Deposit{ - ProposalID: p.Deposit.ProposalID, - Amount: p.Deposit.Amount, - Depositor: p.Deposit.Depositor, - }) - } - - targetGov.Deposits = deposits - - var votes Votes - for _, p := range initialState.Votes { - votes = append(votes, Vote{ - ProposalID: p.Vote.ProposalID, - Option: VoteOption(p.Vote.Option), - Voter: p.Vote.Voter, - }) - } - - targetGov.Votes = votes - - var proposals Proposals - for _, p := range initialState.Proposals { - proposal := Proposal{ - Content: migrateContent(p.ProposalContent), - ProposalID: p.ProposalID, - Status: ProposalStatus(p.Status), - FinalTallyResult: TallyResult(p.FinalTallyResult), - SubmitTime: p.SubmitTime, - DepositEndTime: p.DepositEndTime, - TotalDeposit: p.TotalDeposit, - VotingStartTime: p.VotingStartTime, - VotingEndTime: p.VotingEndTime, - } - - proposals = append(proposals, proposal) - } - - targetGov.Proposals = proposals - return targetGov -} - -func migrateContent(proposalContent v034gov.ProposalContent) (content Content) { - switch proposalContent.ProposalType() { - case v034gov.ProposalTypeText: - return NewTextProposal(proposalContent.GetTitle(), proposalContent.GetDescription()) - case v034gov.ProposalTypeSoftwareUpgrade: - return NewSoftwareUpgradeProposal(proposalContent.GetTitle(), proposalContent.GetDescription()) - default: - return nil - } -} diff --git a/x/gov/legacy/v036/types.go b/x/gov/legacy/v036/types.go deleted file mode 100644 index a6f6bb0a04..0000000000 --- a/x/gov/legacy/v036/types.go +++ /dev/null @@ -1,454 +0,0 @@ -package v036 - -import ( - "encoding/json" - "fmt" - "strings" - "time" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// Keys -const ( - // ModuleName is the name of the module - ModuleName = "gov" - - // StoreKey is the store key string for gov - StoreKey = ModuleName - - // RouterKey is the message route for gov - RouterKey = ModuleName - - // QuerierRoute is the querier route for gov - QuerierRoute = ModuleName - - // DefaultParamspace default name for parameter store - DefaultParamspace = ModuleName -) - -// GenesisState represents v0.34.x genesis state for the governance module. -type GenesisState struct { - StartingProposalID uint64 `json:"starting_proposal_id"` - Deposits Deposits `json:"deposits"` - Votes Votes `json:"votes"` - Proposals []Proposal `json:"proposals"` - DepositParams DepositParams `json:"deposit_params"` - VotingParams VotingParams `json:"voting_params"` - TallyParams TallyParams `json:"tally_params"` -} - -type Deposit struct { - ProposalID uint64 `json:"proposal_id"` // proposalID of the proposal - Depositor sdk.AccAddress `json:"depositor"` // Address of the depositor - Amount sdk.Coins `json:"amount"` // Deposit amount -} - -type Deposits []Deposit - -type Vote struct { - ProposalID uint64 `json:"proposal_id"` // proposalID of the proposal - Voter sdk.AccAddress `json:"voter"` // address of the voter - Option VoteOption `json:"option"` // option from OptionSet chosen by the voter -} - -type Votes []Vote - -// Param around deposits for governance -type DepositParams struct { - MinDeposit sdk.Coins `json:"min_deposit,omitempty"` // Minimum deposit for a proposal to enter voting period. - MaxDepositPeriod time.Duration `json:"max_deposit_period,omitempty"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months -} - -type Content interface { - GetTitle() string - GetDescription() string - ProposalRoute() string - ProposalType() string - ValidateBasic() sdk.Error - String() string -} - -type Proposal struct { - Content `json:"content"` // Proposal content interface - - ProposalID uint64 `json:"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 - - SubmitTime time.Time `json:"submit_time"` // Time of the block where TxGovSubmitProposal was included - DepositEndTime time.Time `json:"deposit_end_time"` // Time that the Proposal would expire if deposit amount isn't met - TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit - - VotingStartTime time.Time `json:"voting_start_time"` // Time of the block where MinDeposit was reached. -1 if MinDeposit is not reached - VotingEndTime time.Time `json:"voting_end_time"` // Time that the VotingPeriod for this proposal will end and votes will be tallied -} - -type Proposals []Proposal -type ProposalQueue []uint64 - -type TallyParams struct { - Quorum sdk.Dec `json:"quorum,omitempty"` // Minimum percentage of total stake needed to vote for a result to be considered valid - Threshold sdk.Dec `json:"threshold,omitempty"` // Minimum proportion of Yes votes for proposal to pass. Initial value: 0.5 - Veto sdk.Dec `json:"veto,omitempty"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3 -} - -// ---------------------------------------------------------------------------- -// ProposalStatus -// ---------------------------------------------------------------------------- - -// ProposalStatus is a type alias that represents a proposal status as a byte -type ProposalStatus byte - -//nolint -const ( - StatusNil ProposalStatus = 0x00 - StatusDepositPeriod ProposalStatus = 0x01 - StatusVotingPeriod ProposalStatus = 0x02 - StatusPassed ProposalStatus = 0x03 - StatusRejected ProposalStatus = 0x04 - StatusFailed ProposalStatus = 0x05 -) - -// ProposalStatusToString turns a string into a ProposalStatus -func ProposalStatusFromString(str string) (ProposalStatus, error) { - switch str { - case "DepositPeriod": - return StatusDepositPeriod, nil - - case "VotingPeriod": - return StatusVotingPeriod, nil - - case "Passed": - return StatusPassed, nil - - case "Rejected": - return StatusRejected, nil - - case "Failed": - return StatusFailed, nil - - case "": - return StatusNil, nil - - default: - return ProposalStatus(0xff), fmt.Errorf("'%s' is not a valid proposal status", str) - } -} - -// Marshal needed for protobuf compatibility -func (status ProposalStatus) Marshal() ([]byte, error) { - return []byte{byte(status)}, nil -} - -// Unmarshal needed for protobuf compatibility -func (status *ProposalStatus) Unmarshal(data []byte) error { - *status = ProposalStatus(data[0]) - return nil -} - -// Marshals to JSON using string -func (status ProposalStatus) MarshalJSON() ([]byte, error) { - return json.Marshal(status.String()) -} - -// Unmarshals from JSON assuming Bech32 encoding -func (status *ProposalStatus) UnmarshalJSON(data []byte) error { - var s string - err := json.Unmarshal(data, &s) - if err != nil { - return err - } - - bz2, err := ProposalStatusFromString(s) - if err != nil { - return err - } - - *status = bz2 - return nil -} - -// String implements the Stringer interface. -func (status ProposalStatus) String() string { - switch status { - case StatusDepositPeriod: - return "DepositPeriod" - - case StatusVotingPeriod: - return "VotingPeriod" - - case StatusPassed: - return "Passed" - - case StatusRejected: - return "Rejected" - - case StatusFailed: - return "Failed" - - default: - return "" - } -} - -// Format implements the fmt.Formatter interface. -// nolint: errcheck -func (status ProposalStatus) Format(s fmt.State, verb rune) { - switch verb { - case 's': - s.Write([]byte(status.String())) - default: - // TODO: Do this conversion more directly - s.Write([]byte(fmt.Sprintf("%v", byte(status)))) - } -} - -type VotingParams struct { - VotingPeriod time.Duration `json:"voting_period,omitempty"` // Length of the voting period. -} - -type TallyResult struct { - Yes sdk.Int `json:"yes"` - Abstain sdk.Int `json:"abstain"` - No sdk.Int `json:"no"` - NoWithVeto sdk.Int `json:"no_with_veto"` -} - -// ---------------------------------------------------------------------------- -// VoteOption -// ---------------------------------------------------------------------------- - -type VoteOption byte - -// Vote options -const ( - OptionEmpty VoteOption = 0x00 - OptionYes VoteOption = 0x01 - OptionAbstain VoteOption = 0x02 - OptionNo VoteOption = 0x03 - OptionNoWithVeto VoteOption = 0x04 -) - -// VoteOptionFromString returns a VoteOption from a string. It returns an error -// if the string is invalid. -func VoteOptionFromString(str string) (VoteOption, error) { - switch str { - case "Yes": - return OptionYes, nil - - case "Abstain": - return OptionAbstain, nil - - case "No": - return OptionNo, nil - - case "NoWithVeto": - return OptionNoWithVeto, nil - - default: - return VoteOption(0xff), fmt.Errorf("'%s' is not a valid vote option", str) - } -} - -// Marshal needed for protobuf compatibility. -func (vo VoteOption) Marshal() ([]byte, error) { - return []byte{byte(vo)}, nil -} - -// Unmarshal needed for protobuf compatibility. -func (vo *VoteOption) Unmarshal(data []byte) error { - *vo = VoteOption(data[0]) - return nil -} - -// Marshals to JSON using string. -func (vo VoteOption) MarshalJSON() ([]byte, error) { - return json.Marshal(vo.String()) -} - -// UnmarshalJSON decodes from JSON assuming Bech32 encoding. -func (vo *VoteOption) UnmarshalJSON(data []byte) error { - var s string - err := json.Unmarshal(data, &s) - if err != nil { - return err - } - - bz2, err := VoteOptionFromString(s) - if err != nil { - return err - } - - *vo = bz2 - return nil -} - -// String implements the Stringer interface. -func (vo VoteOption) String() string { - switch vo { - case OptionYes: - return "Yes" - case OptionAbstain: - return "Abstain" - case OptionNo: - return "No" - case OptionNoWithVeto: - return "NoWithVeto" - default: - return "" - } -} - -// Format implements the fmt.Formatter interface. -// nolint: errcheck -func (vo VoteOption) Format(s fmt.State, verb rune) { - switch verb { - case 's': - s.Write([]byte(vo.String())) - default: - s.Write([]byte(fmt.Sprintf("%v", byte(vo)))) - } -} - -// ---------------------------------------------------------------------------- -// Tally -// ---------------------------------------------------------------------------- - -// Equals returns if two proposals are equal. -func (tr TallyResult) Equals(comp TallyResult) bool { - return tr.Yes.Equal(comp.Yes) && - tr.Abstain.Equal(comp.Abstain) && - tr.No.Equal(comp.No) && - tr.NoWithVeto.Equal(comp.NoWithVeto) -} - -func (tr TallyResult) String() string { - return fmt.Sprintf(`Tally Result: - Yes: %s - Abstain: %s - No: %s - NoWithVeto: %s`, tr.Yes, tr.Abstain, tr.No, tr.NoWithVeto) -} - -// ---------------------------------------------------------------------------- -// Proposal -// ---------------------------------------------------------------------------- - -// Proposal types -const ( - ProposalTypeText string = "Text" - ProposalTypeSoftwareUpgrade string = "SoftwareUpgrade" -) - -// Text Proposal -type TextProposal struct { - Title string `json:"title"` - Description string `json:"description"` -} - -func NewTextProposal(title, description string) Content { - return TextProposal{title, description} -} - -// Implements Proposal Interface -var _ Content = TextProposal{} - -// nolint -func (tp TextProposal) GetTitle() string { return tp.Title } -func (tp TextProposal) GetDescription() string { return tp.Description } -func (tp TextProposal) ProposalRoute() string { return RouterKey } -func (tp TextProposal) ProposalType() string { return ProposalTypeText } -func (tp TextProposal) ValidateBasic() sdk.Error { return ValidateAbstract(DefaultCodespace, tp) } - -const ( - DefaultCodespace sdk.CodespaceType = "gov" - - CodeInvalidContent sdk.CodeType = 6 - CodeInvalidProposalType sdk.CodeType = 7 -) - -func ErrInvalidProposalContent(cs sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(cs, CodeInvalidContent, fmt.Sprintf("invalid proposal content: %s", msg)) -} - -func ErrInvalidProposalType(codespace sdk.CodespaceType, proposalType string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidProposalType, fmt.Sprintf("proposal type '%s' is not valid", proposalType)) -} - -// ValidateAbstract validates a proposal's abstract contents returning an error -// if invalid. -func ValidateAbstract(codespace sdk.CodespaceType, c Content) sdk.Error { - title := c.GetTitle() - if len(strings.TrimSpace(title)) == 0 { - return ErrInvalidProposalContent(codespace, "proposal title cannot be blank") - } - if len(title) > MaxTitleLength { - return ErrInvalidProposalContent(codespace, fmt.Sprintf("proposal title is longer than max length of %d", MaxTitleLength)) - } - - description := c.GetDescription() - if len(description) == 0 { - return ErrInvalidProposalContent(codespace, "proposal description cannot be blank") - } - if len(description) > MaxDescriptionLength { - return ErrInvalidProposalContent(codespace, fmt.Sprintf("proposal description is longer than max length of %d", MaxDescriptionLength)) - } - - return nil -} - -// Constants pertaining to a Content object -const ( - MaxDescriptionLength int = 5000 - MaxTitleLength int = 140 -) - -func (tp TextProposal) String() string { - return fmt.Sprintf(`Text Proposal: - Title: %s - Description: %s -`, tp.Title, tp.Description) -} - -// Software Upgrade Proposals -// TODO: We have to add fields for SUP specific arguments e.g. commit hash, -// upgrade date, etc. -type SoftwareUpgradeProposal struct { - Title string `json:"title"` - Description string `json:"description"` -} - -func NewSoftwareUpgradeProposal(title, description string) Content { - return SoftwareUpgradeProposal{title, description} -} - -// Implements Proposal Interface -var _ Content = SoftwareUpgradeProposal{} - -// nolint -func (sup SoftwareUpgradeProposal) GetTitle() string { return sup.Title } -func (sup SoftwareUpgradeProposal) GetDescription() string { return sup.Description } -func (sup SoftwareUpgradeProposal) ProposalRoute() string { return RouterKey } -func (sup SoftwareUpgradeProposal) ProposalType() string { return ProposalTypeSoftwareUpgrade } -func (sup SoftwareUpgradeProposal) ValidateBasic() sdk.Error { - return ValidateAbstract(DefaultCodespace, sup) -} - -func (sup SoftwareUpgradeProposal) String() string { - return fmt.Sprintf(`Software Upgrade Proposal: - Title: %s - Description: %s -`, sup.Title, sup.Description) -} - -// ---------------------------------------------------------------------------- -// Codec -// ---------------------------------------------------------------------------- - -func RegisterCodec(cdc *codec.Codec) { - cdc.RegisterInterface((*Content)(nil), nil) - cdc.RegisterConcrete(TextProposal{}, "cosmos-sdk/TextProposal", nil) - cdc.RegisterConcrete(SoftwareUpgradeProposal{}, "cosmos-sdk/SoftwareUpgradeProposal", nil) -} diff --git a/x/gov/legacy/v0_34/types.go b/x/gov/legacy/v0_34/types.go new file mode 100644 index 0000000000..cbc139b01e --- /dev/null +++ b/x/gov/legacy/v0_34/types.go @@ -0,0 +1,345 @@ +// DONTCOVER +// nolint +package v0_34 + +import ( + "encoding/json" + "fmt" + "time" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ( + _ ProposalContent = TextProposal{} + _ ProposalContent = SoftwareUpgradeProposal{} +) + +const ( + ModuleName = "gov" + + StatusNil ProposalStatus = 0x00 + StatusDepositPeriod ProposalStatus = 0x01 + StatusVotingPeriod ProposalStatus = 0x02 + StatusPassed ProposalStatus = 0x03 + StatusRejected ProposalStatus = 0x04 + StatusFailed ProposalStatus = 0x05 + + OptionEmpty VoteOption = 0x00 + OptionYes VoteOption = 0x01 + OptionAbstain VoteOption = 0x02 + OptionNo VoteOption = 0x03 + OptionNoWithVeto VoteOption = 0x04 + + ProposalTypeNil ProposalKind = 0x00 + ProposalTypeText ProposalKind = 0x01 + ProposalTypeParameterChange ProposalKind = 0x02 + ProposalTypeSoftwareUpgrade ProposalKind = 0x03 +) + +type ( + SoftwareUpgradeProposal struct { + TextProposal + } + + ProposalQueue []uint64 + + ProposalKind byte + + VoteOption byte + ProposalStatus byte + + ProposalContent interface { + GetTitle() string + GetDescription() string + ProposalType() ProposalKind + } + + Proposals []Proposal + + TextProposal struct { + Title string `json:"title"` + Description string `json:"description"` + } + + Proposal struct { + ProposalContent `json:"proposal_content"` + + ProposalID uint64 `json:"proposal_id"` + + Status ProposalStatus `json:"proposal_status"` + FinalTallyResult TallyResult `json:"final_tally_result"` + + SubmitTime time.Time `json:"submit_time"` + DepositEndTime time.Time `json:"deposit_end_time"` + TotalDeposit sdk.Coins `json:"total_deposit"` + + VotingStartTime time.Time `json:"voting_start_time"` + VotingEndTime time.Time `json:"voting_end_time"` + } + + TallyParams struct { + Quorum sdk.Dec `json:"quorum,omitempty"` + Threshold sdk.Dec `json:"threshold,omitempty"` + Veto sdk.Dec `json:"veto,omitempty"` + } + + VotingParams struct { + VotingPeriod time.Duration `json:"voting_period,omitempty"` + } + + TallyResult struct { + Yes sdk.Int `json:"yes"` + Abstain sdk.Int `json:"abstain"` + No sdk.Int `json:"no"` + NoWithVeto sdk.Int `json:"no_with_veto"` + } + + Deposits []Deposit + + Vote struct { + ProposalID uint64 `json:"proposal_id"` + Voter sdk.AccAddress `json:"voter"` + Option VoteOption `json:"option"` + } + + Votes []Vote + + DepositParams struct { + MinDeposit sdk.Coins `json:"min_deposit,omitempty"` + MaxDepositPeriod time.Duration `json:"max_deposit_period,omitempty"` + } + + Deposit struct { + ProposalID uint64 `json:"proposal_id"` + Depositor sdk.AccAddress `json:"depositor"` + Amount sdk.Coins `json:"amount"` + } + + DepositWithMetadata struct { + ProposalID uint64 `json:"proposal_id"` + Deposit Deposit `json:"deposit"` + } + + VoteWithMetadata struct { + ProposalID uint64 `json:"proposal_id"` + Vote Vote `json:"vote"` + } + + GenesisState struct { + StartingProposalID uint64 `json:"starting_proposal_id"` + Deposits []DepositWithMetadata `json:"deposits"` + Votes []VoteWithMetadata `json:"votes"` + Proposals []Proposal `json:"proposals"` + DepositParams DepositParams `json:"deposit_params"` + VotingParams VotingParams `json:"voting_params"` + TallyParams TallyParams `json:"tally_params"` + } +) + +func (tp TextProposal) GetTitle() string { return tp.Title } +func (tp TextProposal) GetDescription() string { return tp.Description } +func (tp TextProposal) ProposalType() ProposalKind { return ProposalTypeText } + +func (sup SoftwareUpgradeProposal) ProposalType() ProposalKind { return ProposalTypeSoftwareUpgrade } + +// ProposalStatusToString turns a string into a ProposalStatus +func ProposalStatusFromString(str string) (ProposalStatus, error) { + switch str { + case "DepositPeriod": + return StatusDepositPeriod, nil + + case "VotingPeriod": + return StatusVotingPeriod, nil + + case "Passed": + return StatusPassed, nil + + case "Rejected": + return StatusRejected, nil + + case "Failed": + return StatusFailed, nil + + case "": + return StatusNil, nil + + default: + return ProposalStatus(0xff), fmt.Errorf("'%s' is not a valid proposal status", str) + } +} + +func (status ProposalStatus) Marshal() ([]byte, error) { + return []byte{byte(status)}, nil +} + +func (status *ProposalStatus) Unmarshal(data []byte) error { + *status = ProposalStatus(data[0]) + return nil +} + +func (status ProposalStatus) MarshalJSON() ([]byte, error) { + return json.Marshal(status.String()) +} + +func (status *ProposalStatus) UnmarshalJSON(data []byte) error { + var s string + err := json.Unmarshal(data, &s) + if err != nil { + return err + } + + bz2, err := ProposalStatusFromString(s) + if err != nil { + return err + } + + *status = bz2 + return nil +} + +func (status ProposalStatus) String() string { + switch status { + case StatusDepositPeriod: + return "DepositPeriod" + + case StatusVotingPeriod: + return "VotingPeriod" + + case StatusPassed: + return "Passed" + + case StatusRejected: + return "Rejected" + + case StatusFailed: + return "Failed" + + default: + return "" + } +} + +func VoteOptionFromString(str string) (VoteOption, error) { + switch str { + case "Yes": + return OptionYes, nil + + case "Abstain": + return OptionAbstain, nil + + case "No": + return OptionNo, nil + + case "NoWithVeto": + return OptionNoWithVeto, nil + + default: + return VoteOption(0xff), fmt.Errorf("'%s' is not a valid vote option", str) + } +} + +func (vo VoteOption) Marshal() ([]byte, error) { + return []byte{byte(vo)}, nil +} + +func (vo *VoteOption) Unmarshal(data []byte) error { + *vo = VoteOption(data[0]) + return nil +} + +func (vo VoteOption) MarshalJSON() ([]byte, error) { + return json.Marshal(vo.String()) +} + +func (vo *VoteOption) UnmarshalJSON(data []byte) error { + var s string + err := json.Unmarshal(data, &s) + if err != nil { + return err + } + + bz2, err := VoteOptionFromString(s) + if err != nil { + return err + } + + *vo = bz2 + return nil +} + +func (vo VoteOption) String() string { + switch vo { + case OptionYes: + return "Yes" + case OptionAbstain: + return "Abstain" + case OptionNo: + return "No" + case OptionNoWithVeto: + return "NoWithVeto" + default: + return "" + } +} + +func ProposalTypeFromString(str string) (ProposalKind, error) { + switch str { + case "Text": + return ProposalTypeText, nil + case "ParameterChange": + return ProposalTypeParameterChange, nil + case "SoftwareUpgrade": + return ProposalTypeSoftwareUpgrade, nil + default: + return ProposalKind(0xff), fmt.Errorf("'%s' is not a valid proposal type", str) + } +} + +func (pt ProposalKind) Marshal() ([]byte, error) { + return []byte{byte(pt)}, nil +} + +func (pt *ProposalKind) Unmarshal(data []byte) error { + *pt = ProposalKind(data[0]) + return nil +} + +func (pt ProposalKind) MarshalJSON() ([]byte, error) { + return json.Marshal(pt.String()) +} + +func (pt *ProposalKind) UnmarshalJSON(data []byte) error { + var s string + err := json.Unmarshal(data, &s) + if err != nil { + return err + } + + bz2, err := ProposalTypeFromString(s) + if err != nil { + return err + } + *pt = bz2 + return nil +} + +func (pt ProposalKind) String() string { + switch pt { + case ProposalTypeText: + return "Text" + case ProposalTypeParameterChange: + return "ParameterChange" + case ProposalTypeSoftwareUpgrade: + return "SoftwareUpgrade" + default: + return "" + } +} + +func RegisterCodec(cdc *codec.Codec) { + cdc.RegisterInterface((*ProposalContent)(nil), nil) + cdc.RegisterConcrete(TextProposal{}, "gov/TextProposal", nil) + cdc.RegisterConcrete(SoftwareUpgradeProposal{}, "gov/SoftwareUpgradeProposal", nil) +} diff --git a/x/gov/legacy/v0_36/migrate.go b/x/gov/legacy/v0_36/migrate.go new file mode 100644 index 0000000000..8bc892bd81 --- /dev/null +++ b/x/gov/legacy/v0_36/migrate.go @@ -0,0 +1,51 @@ +package v0_36 + +import ( + v034gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v0_34" +) + +// Migrate accepts exported genesis state from v0.34 and migrates it to v0.36 +// genesis state. This migration flattens the deposits and votes and updates the +// proposal content to the new +func Migrate(oldGenState v034gov.GenesisState) GenesisState { + deposits := make(v034gov.Deposits, len(oldGenState.Deposits)) + for i, deposit := range oldGenState.Deposits { + deposits[i] = deposit.Deposit + } + + votes := make(v034gov.Votes, len(oldGenState.Votes)) + for i, vote := range oldGenState.Votes { + votes[i] = vote.Vote + } + + proposals := make([]Proposal, len(oldGenState.Proposals)) + for i, proposal := range oldGenState.Proposals { + proposals[i] = Proposal{ + Content: migrateContent(proposal.ProposalContent), + ProposalID: proposal.ProposalID, + Status: proposal.Status, + FinalTallyResult: proposal.FinalTallyResult, + SubmitTime: proposal.SubmitTime, + DepositEndTime: proposal.DepositEndTime, + TotalDeposit: proposal.TotalDeposit, + VotingStartTime: proposal.VotingStartTime, + VotingEndTime: proposal.VotingEndTime, + } + } + + return NewGenesisState( + oldGenState.StartingProposalID, deposits, votes, proposals, + oldGenState.DepositParams, oldGenState.VotingParams, oldGenState.TallyParams, + ) +} + +func migrateContent(proposalContent v034gov.ProposalContent) (content Content) { + switch proposalContent.ProposalType() { + case v034gov.ProposalTypeText: + return NewTextProposal(proposalContent.GetTitle(), proposalContent.GetDescription()) + case v034gov.ProposalTypeSoftwareUpgrade: + return NewSoftwareUpgradeProposal(proposalContent.GetTitle(), proposalContent.GetDescription()) + default: + return nil + } +} diff --git a/x/gov/legacy/v0_36/types.go b/x/gov/legacy/v0_36/types.go new file mode 100644 index 0000000000..64d30a6527 --- /dev/null +++ b/x/gov/legacy/v0_36/types.go @@ -0,0 +1,164 @@ +// DONTCOVER +// nolint +package v0_36 + +import ( + "fmt" + "strings" + "time" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + v034gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v0_34" +) + +const ( + ModuleName = "gov" + RouterKey = ModuleName + + DefaultCodespace sdk.CodespaceType = "gov" + + ProposalTypeText string = "Text" + ProposalTypeSoftwareUpgrade string = "SoftwareUpgrade" + + MaxDescriptionLength int = 5000 + MaxTitleLength int = 140 + + CodeInvalidContent sdk.CodeType = 6 +) + +var ( + _ Content = TextProposal{} + _ Content = SoftwareUpgradeProposal{} +) + +type ( + Proposals []Proposal + ProposalQueue []uint64 + + TextProposal struct { + Title string `json:"title"` + Description string `json:"description"` + } + + SoftwareUpgradeProposal struct { + Title string `json:"title"` + Description string `json:"description"` + } + + Content interface { + GetTitle() string + GetDescription() string + ProposalRoute() string + ProposalType() string + ValidateBasic() sdk.Error + String() string + } + + Proposal struct { + Content `json:"content"` + + ProposalID uint64 `json:"id"` + Status v034gov.ProposalStatus `json:"proposal_status"` + FinalTallyResult v034gov.TallyResult `json:"final_tally_result"` + + SubmitTime time.Time `json:"submit_time"` + DepositEndTime time.Time `json:"deposit_end_time"` + TotalDeposit sdk.Coins `json:"total_deposit"` + + VotingStartTime time.Time `json:"voting_start_time"` + VotingEndTime time.Time `json:"voting_end_time"` + } + + GenesisState struct { + StartingProposalID uint64 `json:"starting_proposal_id"` + Deposits v034gov.Deposits `json:"deposits"` + Votes v034gov.Votes `json:"votes"` + Proposals []Proposal `json:"proposals"` + DepositParams v034gov.DepositParams `json:"deposit_params"` + VotingParams v034gov.VotingParams `json:"voting_params"` + TallyParams v034gov.TallyParams `json:"tally_params"` + } +) + +func NewGenesisState( + startingProposalID uint64, deposits v034gov.Deposits, votes v034gov.Votes, proposals []Proposal, + depositParams v034gov.DepositParams, votingParams v034gov.VotingParams, tallyParams v034gov.TallyParams, +) GenesisState { + + return GenesisState{ + StartingProposalID: startingProposalID, + Deposits: deposits, + Votes: votes, + Proposals: proposals, + DepositParams: depositParams, + VotingParams: votingParams, + TallyParams: tallyParams, + } +} + +func NewTextProposal(title, description string) Content { + return TextProposal{title, description} +} + +func (tp TextProposal) GetTitle() string { return tp.Title } +func (tp TextProposal) GetDescription() string { return tp.Description } +func (tp TextProposal) ProposalRoute() string { return RouterKey } +func (tp TextProposal) ProposalType() string { return ProposalTypeText } +func (tp TextProposal) ValidateBasic() sdk.Error { return ValidateAbstract(DefaultCodespace, tp) } + +func (tp TextProposal) String() string { + return fmt.Sprintf(`Text Proposal: + Title: %s + Description: %s +`, tp.Title, tp.Description) +} + +func NewSoftwareUpgradeProposal(title, description string) Content { + return SoftwareUpgradeProposal{title, description} +} + +func (sup SoftwareUpgradeProposal) GetTitle() string { return sup.Title } +func (sup SoftwareUpgradeProposal) GetDescription() string { return sup.Description } +func (sup SoftwareUpgradeProposal) ProposalRoute() string { return RouterKey } +func (sup SoftwareUpgradeProposal) ProposalType() string { return ProposalTypeSoftwareUpgrade } +func (sup SoftwareUpgradeProposal) ValidateBasic() sdk.Error { + return ValidateAbstract(DefaultCodespace, sup) +} + +func (sup SoftwareUpgradeProposal) String() string { + return fmt.Sprintf(`Software Upgrade Proposal: + Title: %s + Description: %s +`, sup.Title, sup.Description) +} + +func ErrInvalidProposalContent(cs sdk.CodespaceType, msg string) sdk.Error { + return sdk.NewError(cs, CodeInvalidContent, fmt.Sprintf("invalid proposal content: %s", msg)) +} + +func ValidateAbstract(codespace sdk.CodespaceType, c Content) sdk.Error { + title := c.GetTitle() + if len(strings.TrimSpace(title)) == 0 { + return ErrInvalidProposalContent(codespace, "proposal title cannot be blank") + } + if len(title) > MaxTitleLength { + return ErrInvalidProposalContent(codespace, fmt.Sprintf("proposal title is longer than max length of %d", MaxTitleLength)) + } + + description := c.GetDescription() + if len(description) == 0 { + return ErrInvalidProposalContent(codespace, "proposal description cannot be blank") + } + if len(description) > MaxDescriptionLength { + return ErrInvalidProposalContent(codespace, fmt.Sprintf("proposal description is longer than max length of %d", MaxDescriptionLength)) + } + + return nil +} + +func RegisterCodec(cdc *codec.Codec) { + cdc.RegisterInterface((*Content)(nil), nil) + cdc.RegisterConcrete(TextProposal{}, "cosmos-sdk/TextProposal", nil) + cdc.RegisterConcrete(SoftwareUpgradeProposal{}, "cosmos-sdk/SoftwareUpgradeProposal", nil) +} diff --git a/x/simulation/simulate.go b/x/simulation/simulate.go index 30450aeb7d..08920e2953 100644 --- a/x/simulation/simulate.go +++ b/x/simulation/simulate.go @@ -47,6 +47,7 @@ func SimulateFromSeed( appStateFn AppStateFn, seed int64, ops WeightedOperations, invariants sdk.Invariants, numBlocks, blockSize int, commit, lean, onOperation, allInvariants bool, + blackListedAccs map[string]bool, ) (stopEarly bool, simError error) { // in case we have to end early, don't os.Exit so that we can run cleanup code. @@ -74,6 +75,16 @@ func SimulateFromSeed( return true, fmt.Errorf("must have greater than zero genesis accounts") } + // remove module account address if they exist in accs + var tmpAccs []Account + for _, acc := range accs { + if !blackListedAccs[acc.Address.String()] { + tmpAccs = append(tmpAccs, acc) + } + } + + accs = tmpAccs + nextValidators := validators header := abci.Header{ diff --git a/x/slashing/keeper.go b/x/slashing/keeper.go index 6d112a5125..52b186857e 100644 --- a/x/slashing/keeper.go +++ b/x/slashing/keeper.go @@ -151,7 +151,7 @@ func (k Keeper) HandleValidatorSignature(ctx sdk.Context, addr crypto.Address, p consAddr := sdk.ConsAddress(addr) pubkey, err := k.getPubkey(ctx, addr) if err != nil { - panic(fmt.Sprintf("Validator consensus-address %v not found", consAddr.String())) + panic(fmt.Sprintf("Validator consensus-address %s not found", consAddr)) } // fetch signing info @@ -193,7 +193,8 @@ func (k Keeper) HandleValidatorSignature(ctx sdk.Context, addr crypto.Address, p ), ) - logger.Info(fmt.Sprintf("Absent validator %s (%s) at height %d, %d missed, threshold %d", addr, pubkey, height, signInfo.MissedBlocksCounter, k.MinSignedPerWindow(ctx))) + logger.Info( + fmt.Sprintf("Absent validator %s (%s) at height %d, %d missed, threshold %d", consAddr, pubkey, height, signInfo.MissedBlocksCounter, k.MinSignedPerWindow(ctx))) } minHeight := signInfo.StartHeight + k.SignedBlocksWindow(ctx) @@ -206,7 +207,7 @@ func (k Keeper) HandleValidatorSignature(ctx sdk.Context, addr crypto.Address, p // Downtime confirmed: slash and jail the validator logger.Info(fmt.Sprintf("Validator %s past min height of %d and below signed blocks threshold of %d", - sdk.ConsAddress(pubkey.Address()), minHeight, k.MinSignedPerWindow(ctx))) + consAddr, minHeight, k.MinSignedPerWindow(ctx))) // We need to retrieve the stake distribution which signed the block, so we subtract ValidatorUpdateDelay from the evidence height, // and subtract an additional 1 since this is the LastCommit. @@ -235,8 +236,9 @@ func (k Keeper) HandleValidatorSignature(ctx sdk.Context, addr crypto.Address, p k.clearValidatorMissedBlockBitArray(ctx, consAddr) } else { // Validator was (a) not found or (b) already jailed, don't slash - logger.Info(fmt.Sprintf("Validator %s would have been slashed for downtime, but was either not found in store or already jailed", - sdk.ConsAddress(pubkey.Address()))) + logger.Info( + fmt.Sprintf("Validator %s would have been slashed for downtime, but was either not found in store or already jailed", consAddr), + ) } } diff --git a/x/staking/legacy/v0_34/types.go b/x/staking/legacy/v0_34/types.go new file mode 100644 index 0000000000..aef3461838 --- /dev/null +++ b/x/staking/legacy/v0_34/types.go @@ -0,0 +1,177 @@ +// DONTCOVER +// nolint +package v0_34 + +import ( + "time" + + "github.com/tendermint/tendermint/crypto" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + ModuleName = "staking" +) + +type ( + Pool struct { + NotBondedTokens sdk.Int `json:"not_bonded_tokens"` + BondedTokens sdk.Int `json:"bonded_tokens"` + } + + Params struct { + UnbondingTime time.Duration `json:"unbonding_time"` + MaxValidators uint16 `json:"max_validators"` + MaxEntries uint16 `json:"max_entries"` + BondDenom string `json:"bond_denom"` + } + + LastValidatorPower struct { + Address sdk.ValAddress + Power int64 + } + + Description struct { + Moniker string `json:"moniker"` + Identity string `json:"identity"` + Website string `json:"website"` + Details string `json:"details"` + } + + Commission struct { + CommissionRates CommissionRates `json:"commission_rates"` + UpdateTime time.Time `json:"update_time"` + } + + CommissionRates struct { + Rate sdk.Dec `json:"rate"` + MaxRate sdk.Dec `json:"max_rate"` + MaxChangeRate sdk.Dec `json:"max_change_rate"` + } + + bechValidator struct { + OperatorAddress sdk.ValAddress `json:"operator_address"` // the bech32 address of the validator's operator + ConsPubKey string `json:"consensus_pubkey"` // the bech32 consensus public key of the validator + Jailed bool `json:"jailed"` // has the validator been jailed from bonded status? + Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded) + Tokens sdk.Int `json:"tokens"` // delegated tokens (incl. self-delegation) + DelegatorShares sdk.Dec `json:"delegator_shares"` // total shares issued to a validator's delegators + Description Description `json:"description"` // description terms for the validator + UnbondingHeight int64 `json:"unbonding_height"` // if unbonding, height at which this validator has begun unbonding + UnbondingCompletionTime time.Time `json:"unbonding_time"` // if unbonding, min time for the validator to complete unbonding + Commission Commission `json:"commission"` // commission parameters + MinSelfDelegation sdk.Int `json:"min_self_delegation"` // minimum self delegation + } + + Validator struct { + OperatorAddress sdk.ValAddress `json:"operator_address"` + ConsPubKey crypto.PubKey `json:"consensus_pubkey"` + Jailed bool `json:"jailed"` + Status sdk.BondStatus `json:"status"` + Tokens sdk.Int `json:"tokens"` + DelegatorShares sdk.Dec `json:"delegator_shares"` + Description Description `json:"description"` + UnbondingHeight int64 `json:"unbonding_height"` + UnbondingCompletionTime time.Time `json:"unbonding_time"` + Commission Commission `json:"commission"` + MinSelfDelegation sdk.Int `json:"min_self_delegation"` + } + + Validators []Validator + + Delegation struct { + DelegatorAddress sdk.AccAddress `json:"delegator_address"` + ValidatorAddress sdk.ValAddress `json:"validator_address"` + Shares sdk.Dec `json:"shares"` + } + + Delegations []Delegation + + UnbondingDelegationEntry struct { + CreationHeight int64 `json:"creation_height"` + CompletionTime time.Time `json:"completion_time"` + InitialBalance sdk.Int `json:"initial_balance"` + Balance sdk.Int `json:"balance"` + } + + UnbondingDelegation struct { + DelegatorAddress sdk.AccAddress `json:"delegator_address"` + ValidatorAddress sdk.ValAddress `json:"validator_address"` + Entries []UnbondingDelegationEntry `json:"entries"` + } + + RedelegationEntry struct { + CreationHeight int64 `json:"creation_height"` + CompletionTime time.Time `json:"completion_time"` + InitialBalance sdk.Int `json:"initial_balance"` + SharesDst sdk.Dec `json:"shares_dst"` + } + + Redelegation struct { + DelegatorAddress sdk.AccAddress `json:"delegator_address"` + ValidatorSrcAddress sdk.ValAddress `json:"validator_src_address"` + ValidatorDstAddress sdk.ValAddress `json:"validator_dst_address"` + Entries []RedelegationEntry `json:"entries"` + } + + GenesisState struct { + Pool Pool `json:"pool"` + Params Params `json:"params"` + LastTotalPower sdk.Int `json:"last_total_power"` + LastValidatorPowers []LastValidatorPower `json:"last_validator_powers"` + Validators Validators `json:"validators"` + Delegations Delegations `json:"delegations"` + UnbondingDelegations []UnbondingDelegation `json:"unbonding_delegations"` + Redelegations []Redelegation `json:"redelegations"` + Exported bool `json:"exported"` + } +) + +func (v Validator) MarshalJSON() ([]byte, error) { + bechConsPubKey, err := sdk.Bech32ifyConsPub(v.ConsPubKey) + if err != nil { + return nil, err + } + + return codec.Cdc.MarshalJSON(bechValidator{ + OperatorAddress: v.OperatorAddress, + ConsPubKey: bechConsPubKey, + Jailed: v.Jailed, + Status: v.Status, + Tokens: v.Tokens, + DelegatorShares: v.DelegatorShares, + Description: v.Description, + UnbondingHeight: v.UnbondingHeight, + UnbondingCompletionTime: v.UnbondingCompletionTime, + MinSelfDelegation: v.MinSelfDelegation, + Commission: v.Commission, + }) +} + +// UnmarshalJSON unmarshals the validator from JSON using Bech32 +func (v *Validator) UnmarshalJSON(data []byte) error { + bv := &bechValidator{} + if err := codec.Cdc.UnmarshalJSON(data, bv); err != nil { + return err + } + consPubKey, err := sdk.GetConsPubKeyBech32(bv.ConsPubKey) + if err != nil { + return err + } + *v = Validator{ + OperatorAddress: bv.OperatorAddress, + ConsPubKey: consPubKey, + Jailed: bv.Jailed, + Tokens: bv.Tokens, + Status: bv.Status, + DelegatorShares: bv.DelegatorShares, + Description: bv.Description, + UnbondingHeight: bv.UnbondingHeight, + UnbondingCompletionTime: bv.UnbondingCompletionTime, + Commission: bv.Commission, + MinSelfDelegation: bv.MinSelfDelegation, + } + return nil +} diff --git a/x/staking/legacy/v0_36/migrate.go b/x/staking/legacy/v0_36/migrate.go new file mode 100644 index 0000000000..7ccac5f54d --- /dev/null +++ b/x/staking/legacy/v0_36/migrate.go @@ -0,0 +1,23 @@ +// DONTCOVER +// nolint +package v0_36 + +import ( + v034staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_34" +) + +// Migrate accepts exported genesis state from v0.34 and migrates it to v0.36 +// genesis state. All entries are identical except for validator slashing events +// which now include the period. +func Migrate(oldGenState v034staking.GenesisState) GenesisState { + return NewGenesisState( + oldGenState.Params, + oldGenState.LastTotalPower, + oldGenState.LastValidatorPowers, + oldGenState.Validators, + oldGenState.Delegations, + oldGenState.UnbondingDelegations, + oldGenState.Redelegations, + oldGenState.Exported, + ) +} diff --git a/x/staking/legacy/v0_36/types.go b/x/staking/legacy/v0_36/types.go new file mode 100644 index 0000000000..5af5d8acd9 --- /dev/null +++ b/x/staking/legacy/v0_36/types.go @@ -0,0 +1,44 @@ +// DONTCOVER +// nolint +package v0_36 + +import ( + v034staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_34" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + ModuleName = "staking" +) + +type ( + GenesisState struct { + Params v034staking.Params `json:"params"` + LastTotalPower sdk.Int `json:"last_total_power"` + LastValidatorPowers []v034staking.LastValidatorPower `json:"last_validator_powers"` + Validators v034staking.Validators `json:"validators"` + Delegations v034staking.Delegations `json:"delegations"` + UnbondingDelegations []v034staking.UnbondingDelegation `json:"unbonding_delegations"` + Redelegations []v034staking.Redelegation `json:"redelegations"` + Exported bool `json:"exported"` + } +) + +func NewGenesisState( + params v034staking.Params, lastTotalPower sdk.Int, lastValPowers []v034staking.LastValidatorPower, + validators v034staking.Validators, delegations v034staking.Delegations, + ubds []v034staking.UnbondingDelegation, reds []v034staking.Redelegation, exported bool, +) GenesisState { + + return GenesisState{ + Params: params, + LastTotalPower: lastTotalPower, + LastValidatorPowers: lastValPowers, + Validators: validators, + Delegations: delegations, + UnbondingDelegations: ubds, + Redelegations: reds, + Exported: exported, + } +} diff --git a/x/staking/simulation/msgs.go b/x/staking/simulation/msgs.go index ffdef0906c..2cd3ce0db6 100644 --- a/x/staking/simulation/msgs.go +++ b/x/staking/simulation/msgs.go @@ -159,7 +159,7 @@ func SimulateMsgUndelegate(m auth.AccountKeeper, k staking.Keeper) simulation.Op return simulation.NoOpMsg(), nil, nil } - msg := staking.NewMsgDelegate( + msg := staking.NewMsgUndelegate( delegatorAddress, delegation.ValidatorAddress, sdk.NewCoin(k.GetParams(ctx).BondDenom, unbondAmt), ) if msg.ValidateBasic() != nil { diff --git a/x/staking/types/pool.go b/x/staking/types/pool.go index ca9ed5f2b9..c19bf59a41 100644 --- a/x/staking/types/pool.go +++ b/x/staking/types/pool.go @@ -8,12 +8,12 @@ import ( // names used as root for pool module accounts: // -// - NotBondedPool -> "NotBondedTokensPool" +// - NotBondedPool -> "not_bonded_tokens_pool" // -// - BondedPool -> "BondedTokensPool" +// - BondedPool -> "bonded_tokens_pool" const ( - NotBondedPoolName = "NotBondedTokensPool" - BondedPoolName = "BondedTokensPool" + NotBondedPoolName = "not_bonded_tokens_pool" + BondedPoolName = "bonded_tokens_pool" ) // Pool - tracking bonded and not-bonded token supply of the bond denomination diff --git a/x/supply/genesis.go b/x/supply/genesis.go index 07ad939404..33c67800cc 100644 --- a/x/supply/genesis.go +++ b/x/supply/genesis.go @@ -7,6 +7,8 @@ import ( ) // InitGenesis sets supply information for genesis. +// +// CONTRACT: all types of accounts must have been already initialized/created func InitGenesis(ctx sdk.Context, keeper Keeper, ak types.AccountKeeper, data GenesisState) { // manually set the total supply based on accounts if not provided if data.Supply.Total.Empty() { diff --git a/x/supply/internal/keeper/bank.go b/x/supply/internal/keeper/bank.go index 65d204ad56..fa91b9b30e 100644 --- a/x/supply/internal/keeper/bank.go +++ b/x/supply/internal/keeper/bank.go @@ -73,8 +73,7 @@ func (k Keeper) UndelegateCoinsFromModuleToAccount(ctx sdk.Context, senderModule recipientAddr sdk.AccAddress, amt sdk.Coins) sdk.Error { acc := k.GetModuleAccount(ctx, senderModule) - senderAddr := acc.GetAddress() - if senderAddr == nil { + if acc == nil { return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", senderModule)) } @@ -82,7 +81,7 @@ func (k Keeper) UndelegateCoinsFromModuleToAccount(ctx sdk.Context, senderModule panic(fmt.Sprintf("module account %s does not have permissions to undelegate coins", senderModule)) } - return k.bk.UndelegateCoins(ctx, senderAddr, recipientAddr, amt) + return k.bk.UndelegateCoins(ctx, acc.GetAddress(), recipientAddr, amt) } // MintCoins creates new coins from thin air and adds it to the module account. @@ -95,13 +94,11 @@ func (k Keeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", moduleName)) } - addr := acc.GetAddress() - if !acc.HasPermission(types.Minter) { panic(fmt.Sprintf("module account %s does not have permissions to mint tokens", moduleName)) } - _, err := k.bk.AddCoins(ctx, addr, amt) + _, err := k.bk.AddCoins(ctx, acc.GetAddress(), amt) if err != nil { panic(err) } @@ -121,9 +118,9 @@ func (k Keeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk // Panics if the name maps to a non-burner module account or if the amount is invalid. func (k Keeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk.Error { + // create the account if it doesn't yet exist acc := k.GetModuleAccount(ctx, moduleName) - addr := acc.GetAddress() - if addr == nil { + if acc == nil { return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", moduleName)) } @@ -131,7 +128,7 @@ func (k Keeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk panic(fmt.Sprintf("module account %s does not have permissions to burn tokens", moduleName)) } - _, err := k.bk.SubtractCoins(ctx, addr, amt) + _, err := k.bk.SubtractCoins(ctx, acc.GetAddress(), amt) if err != nil { panic(err) } diff --git a/x/supply/internal/keeper/bank_test.go b/x/supply/internal/keeper/bank_test.go index e1701b653b..a21c90eb47 100644 --- a/x/supply/internal/keeper/bank_test.go +++ b/x/supply/internal/keeper/bank_test.go @@ -118,7 +118,7 @@ func TestBurnCoins(t *testing.T) { initialSupply.Inflate(initCoins) keeper.SetSupply(ctx, initialSupply) - require.Panics(t, func() { keeper.BurnCoins(ctx, "", initCoins) }, "no module account") + require.Error(t, keeper.BurnCoins(ctx, "", initCoins), "no module account") require.Panics(t, func() { keeper.BurnCoins(ctx, types.Minter, initCoins) }, "invalid permission") require.Panics(t, func() { keeper.BurnCoins(ctx, randomPerm, initialSupply.Total) }, "random permission") require.Panics(t, func() { keeper.BurnCoins(ctx, types.Burner, initialSupply.Total) }, "insufficient coins") diff --git a/x/supply/internal/types/supply.go b/x/supply/internal/types/supply.go index e3513cad4d..481223e449 100644 --- a/x/supply/internal/types/supply.go +++ b/x/supply/internal/types/supply.go @@ -9,7 +9,7 @@ import ( // Supply represents a struct that passively keeps track of the total supply amounts in the network type Supply struct { - Total sdk.Coins `json:"total_supply" yaml:"total_supply"` // total supply of tokens registered on the chain + Total sdk.Coins `json:"total" yaml:"total"` // total supply of tokens registered on the chain } // NewSupply creates a new Supply instance diff --git a/x/supply/internal/types/supply_test.go b/x/supply/internal/types/supply_test.go index 74756256a7..34f45d041a 100644 --- a/x/supply/internal/types/supply_test.go +++ b/x/supply/internal/types/supply_test.go @@ -21,7 +21,7 @@ func TestSupplyMarshalYAML(t *testing.T) { bzCoins, err := yaml.Marshal(coins) require.NoError(t, err) - want := fmt.Sprintf(`total_supply: + want := fmt.Sprintf(`total: %s`, string(bzCoins)) require.Equal(t, want, string(bz)) diff --git a/x/supply/legacy/v0_36/types.go b/x/supply/legacy/v0_36/types.go new file mode 100644 index 0000000000..4a219f5487 --- /dev/null +++ b/x/supply/legacy/v0_36/types.go @@ -0,0 +1,27 @@ +// DONTCOVER +// nolint +package v0_36 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ModuleName = "supply" + +type ( + Supply struct { + Total sdk.Coins `json:"total"` + } + + GenesisState struct { + Supply Supply `json:"supply"` + } +) + +func EmptyGenesisState() GenesisState { + return GenesisState{ + Supply: Supply{ + Total: sdk.NewCoins(), // leave this empty as it's filled on initialization + }, + } +}