chore: remove params dep from crisis, gov and mint (#17837)
This commit is contained in:
parent
076ab3bf89
commit
d5c78a637e
@ -426,6 +426,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
* (x/bank) [#17818](https://github.com/cosmos/cosmos-sdk/pull/17818) Remove params requirement from `NewAppModule`
|
||||
* (x/slashing & x/auth) [#17820](https://github.com/cosmos/cosmos-sdk/pull/17820) Remove params requirement from `NewAppModule`
|
||||
* (x/distribution & x/staking) [#17834](https://github.com/cosmos/cosmos-sdk/pull/17834) Remove params requirement from `NewAppModule`
|
||||
* (x/mint & x/gov & x/crisis) [#17837](https://github.com/cosmos/cosmos-sdk/pull/17837) Remove params requirement from `NewAppModule`
|
||||
|
||||
### Client Breaking Changes
|
||||
|
||||
|
||||
@ -386,10 +386,10 @@ func NewSimApp(
|
||||
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
|
||||
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
|
||||
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
|
||||
crisis.NewAppModule(app.CrisisKeeper, skipGenesisInvariants, app.GetSubspace(crisistypes.ModuleName)),
|
||||
crisis.NewAppModule(app.CrisisKeeper, skipGenesisInvariants),
|
||||
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
|
||||
gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)),
|
||||
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, app.GetSubspace(minttypes.ModuleName)),
|
||||
gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper),
|
||||
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil),
|
||||
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.interfaceRegistry),
|
||||
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
||||
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
|
||||
|
||||
@ -127,7 +127,7 @@ func initFixture(tb testing.TB) *fixture {
|
||||
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper)
|
||||
stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper)
|
||||
distrModule := distribution.NewAppModule(cdc, distrKeeper, accountKeeper, bankKeeper, stakingKeeper)
|
||||
govModule := gov.NewAppModule(cdc, govKeeper, accountKeeper, bankKeeper, nil)
|
||||
govModule := gov.NewAppModule(cdc, govKeeper, accountKeeper, bankKeeper)
|
||||
|
||||
integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, map[string]appmodule.AppModule{
|
||||
authtypes.ModuleName: authModule,
|
||||
|
||||
@ -55,7 +55,7 @@ func Example() {
|
||||
// here bankkeeper and staking keeper is nil because we are not testing them
|
||||
// subspace is nil because we don't test params (which is legacy anyway)
|
||||
mintKeeper := mintkeeper.NewKeeper(encodingCfg.Codec, runtime.NewKVStoreService(keys[minttypes.StoreKey]), nil, accountKeeper, nil, authtypes.FeeCollectorName, authority)
|
||||
mintModule := mint.NewAppModule(encodingCfg.Codec, mintKeeper, accountKeeper, nil, nil)
|
||||
mintModule := mint.NewAppModule(encodingCfg.Codec, mintKeeper, accountKeeper, nil)
|
||||
|
||||
// create the application and register all the modules from the previous step
|
||||
integrationApp := integration.NewIntegrationApp(
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
package exported
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
)
|
||||
|
||||
type (
|
||||
ParamSet = paramtypes.ParamSet
|
||||
|
||||
// Subspace defines an interface that implements the legacy x/params Subspace
|
||||
// type.
|
||||
//
|
||||
// NOTE: This is used solely for migration of x/params managed parameters.
|
||||
Subspace interface {
|
||||
Get(ctx sdk.Context, key []byte, ptr interface{})
|
||||
}
|
||||
)
|
||||
@ -2,21 +2,17 @@ package keeper
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/crisis/exported"
|
||||
v2 "github.com/cosmos/cosmos-sdk/x/crisis/migrations/v2"
|
||||
)
|
||||
|
||||
// Migrator is a struct for handling in-place state migrations.
|
||||
type Migrator struct {
|
||||
keeper *Keeper
|
||||
legacySubspace exported.Subspace
|
||||
keeper *Keeper
|
||||
}
|
||||
|
||||
// NewMigrator returns a new Migrator.
|
||||
func NewMigrator(k *Keeper, ss exported.Subspace) Migrator {
|
||||
func NewMigrator(k *Keeper) Migrator {
|
||||
return Migrator{
|
||||
keeper: k,
|
||||
legacySubspace: ss,
|
||||
keeper: k,
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,5 +21,5 @@ func NewMigrator(k *Keeper, ss exported.Subspace) Migrator {
|
||||
// and managed by the x/params modules and stores them directly into the x/crisis
|
||||
// module state.
|
||||
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
|
||||
return v2.MigrateStore(ctx, m.keeper.storeService, m.legacySubspace, m.keeper.cdc)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
storetypes "cosmossdk.io/core/store"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/x/crisis/exported"
|
||||
)
|
||||
|
||||
const (
|
||||
ModuleName = "crisis"
|
||||
)
|
||||
|
||||
var (
|
||||
ConstantFee = []byte("ConstantFee")
|
||||
ConstantFeeKey = []byte{0x01}
|
||||
)
|
||||
|
||||
// MigrateStore migrates the x/crisis module state from the consensus version 1 to
|
||||
// version 2. Specifically, it takes the `ConstantFee` parameter that is currently stored
|
||||
// and managed by the x/params module and stores it directly into the x/crisis
|
||||
// module state.
|
||||
func MigrateStore(ctx sdk.Context, storeService storetypes.KVStoreService, legacySubspace exported.Subspace, cdc codec.BinaryCodec) error {
|
||||
store := storeService.OpenKVStore(ctx)
|
||||
var currConstantFee sdk.Coin
|
||||
legacySubspace.Get(ctx, ConstantFee, &currConstantFee)
|
||||
|
||||
if !currConstantFee.IsValid() {
|
||||
return errors.ErrInvalidCoins.Wrap("constant fee")
|
||||
}
|
||||
|
||||
bz, err := cdc.Marshal(&currConstantFee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return store.Set(ConstantFeeKey, bz)
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
package v2_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/crisis"
|
||||
v2 "github.com/cosmos/cosmos-sdk/x/crisis/migrations/v2"
|
||||
"github.com/cosmos/cosmos-sdk/x/crisis/types"
|
||||
)
|
||||
|
||||
type mockSubspace struct {
|
||||
constantFee sdk.Coin
|
||||
}
|
||||
|
||||
func newMockSubspace(fee sdk.Coin) mockSubspace {
|
||||
return mockSubspace{constantFee: fee}
|
||||
}
|
||||
|
||||
func (ms mockSubspace) Get(ctx sdk.Context, key []byte, ptr interface{}) {
|
||||
*ptr.(*sdk.Coin) = ms.constantFee
|
||||
}
|
||||
|
||||
func TestMigrate(t *testing.T) {
|
||||
cdc := moduletestutil.MakeTestEncodingConfig(crisis.AppModuleBasic{}).Codec
|
||||
storeKey := storetypes.NewKVStoreKey(v2.ModuleName)
|
||||
storeService := runtime.NewKVStoreService(storeKey)
|
||||
tKey := storetypes.NewTransientStoreKey("transient_test")
|
||||
ctx := testutil.DefaultContext(storeKey, tKey)
|
||||
store := ctx.KVStore(storeKey)
|
||||
|
||||
legacySubspace := newMockSubspace(types.DefaultGenesisState().ConstantFee)
|
||||
require.NoError(t, v2.MigrateStore(ctx, storeService, legacySubspace, cdc))
|
||||
|
||||
var res sdk.Coin
|
||||
bz := store.Get(v2.ConstantFeeKey)
|
||||
require.NoError(t, cdc.Unmarshal(bz, &res))
|
||||
require.NotNil(t, res)
|
||||
require.Equal(t, legacySubspace.constantFee, res)
|
||||
}
|
||||
@ -26,7 +26,6 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/crisis/client/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/crisis/exported"
|
||||
"github.com/cosmos/cosmos-sdk/x/crisis/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/crisis/types"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
@ -101,9 +100,6 @@ type AppModule struct {
|
||||
// executed.
|
||||
keeper *keeper.Keeper
|
||||
|
||||
// legacySubspace is used solely for migration of x/params managed parameters
|
||||
legacySubspace exported.Subspace
|
||||
|
||||
skipGenesisInvariants bool
|
||||
}
|
||||
|
||||
@ -111,11 +107,10 @@ type AppModule struct {
|
||||
// we will call keeper.AssertInvariants during InitGenesis (it may take a significant time)
|
||||
// - which doesn't impact the chain security unless 66+% of validators have a wrongly
|
||||
// modified genesis file.
|
||||
func NewAppModule(keeper *keeper.Keeper, skipGenesisInvariants bool, ss exported.Subspace) AppModule {
|
||||
func NewAppModule(keeper *keeper.Keeper, skipGenesisInvariants bool) AppModule {
|
||||
return AppModule{
|
||||
AppModuleBasic: AppModuleBasic{},
|
||||
keeper: keeper,
|
||||
legacySubspace: ss,
|
||||
|
||||
skipGenesisInvariants: skipGenesisInvariants,
|
||||
}
|
||||
@ -136,7 +131,7 @@ func AddModuleInitFlags(startCmd *cobra.Command) {
|
||||
func (am AppModule) RegisterServices(cfg module.Configurator) {
|
||||
types.RegisterMsgServer(cfg.MsgServer(), am.keeper)
|
||||
|
||||
m := keeper.NewMigrator(am.keeper, am.legacySubspace)
|
||||
m := keeper.NewMigrator(am.keeper)
|
||||
if err := cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2); err != nil {
|
||||
panic(fmt.Sprintf("failed to migrate x/%s from version 1 to 2: %v", types.ModuleName, err))
|
||||
}
|
||||
@ -192,9 +187,6 @@ type ModuleInputs struct {
|
||||
|
||||
BankKeeper types.SupplyKeeper
|
||||
AddressCodec address.Codec
|
||||
|
||||
// LegacySubspace is used solely for migration of x/params managed parameters
|
||||
LegacySubspace exported.Subspace `optional:"true"`
|
||||
}
|
||||
|
||||
type ModuleOutputs struct {
|
||||
@ -236,7 +228,7 @@ func ProvideModule(in ModuleInputs) ModuleOutputs {
|
||||
skipGenesisInvariants = cast.ToBool(in.AppOpts.Get(FlagSkipGenesisInvariants))
|
||||
}
|
||||
|
||||
m := NewAppModule(k, skipGenesisInvariants, in.LegacySubspace)
|
||||
m := NewAppModule(k, skipGenesisInvariants)
|
||||
|
||||
return ModuleOutputs{CrisisKeeper: k, Module: m}
|
||||
}
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
package exported
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
)
|
||||
|
||||
type (
|
||||
ParamSet = paramtypes.ParamSet
|
||||
|
||||
// Subspace defines an interface that implements the legacy x/params Subspace
|
||||
// type.
|
||||
//
|
||||
// NOTE: This is used solely for migration of x/params managed parameters.
|
||||
ParamSubspace interface {
|
||||
Get(ctx sdk.Context, key []byte, ptr interface{})
|
||||
}
|
||||
)
|
||||
@ -2,40 +2,34 @@ package keeper
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/exported"
|
||||
v2 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v2"
|
||||
v3 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v3"
|
||||
v4 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v4"
|
||||
v5 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v5"
|
||||
)
|
||||
|
||||
// Migrator is a struct for handling in-place store migrations.
|
||||
type Migrator struct {
|
||||
keeper *Keeper
|
||||
legacySubspace exported.ParamSubspace
|
||||
keeper *Keeper
|
||||
}
|
||||
|
||||
// NewMigrator returns a new Migrator.
|
||||
func NewMigrator(keeper *Keeper, legacySubspace exported.ParamSubspace) Migrator {
|
||||
func NewMigrator(keeper *Keeper) Migrator {
|
||||
return Migrator{
|
||||
keeper: keeper,
|
||||
legacySubspace: legacySubspace,
|
||||
keeper: keeper,
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate1to2 migrates from version 1 to 2.
|
||||
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
|
||||
return v2.MigrateStore(ctx, m.keeper.storeService, m.keeper.cdc)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Migrate2to3 migrates from version 2 to 3.
|
||||
func (m Migrator) Migrate2to3(ctx sdk.Context) error {
|
||||
return v3.MigrateStore(ctx, m.keeper.storeService, m.keeper.cdc)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Migrate3to4 migrates from version 3 to 4.
|
||||
func (m Migrator) Migrate3to4(ctx sdk.Context) error {
|
||||
return v4.MigrateStore(ctx, m.keeper.storeService, m.legacySubspace, m.keeper.cdc)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Migrate4to5 migrates from version 4 to 5.
|
||||
|
||||
@ -1,164 +0,0 @@
|
||||
package v1
|
||||
|
||||
// Package v1 (v0.40) is copy-pasted from:
|
||||
// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/gov/types/keys.go
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/kv"
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
addrLen = 20
|
||||
)
|
||||
|
||||
// Keys for governance store
|
||||
// Items are stored with the following key: values
|
||||
//
|
||||
// - 0x00<proposalID_Bytes>: Proposal
|
||||
//
|
||||
// - 0x01<endTime_Bytes><proposalID_Bytes>: activeProposalID
|
||||
//
|
||||
// - 0x02<endTime_Bytes><proposalID_Bytes>: inactiveProposalID
|
||||
//
|
||||
// - 0x03: nextProposalID
|
||||
//
|
||||
// - 0x10<proposalID_Bytes><depositorAddr_Bytes>: Deposit
|
||||
//
|
||||
// - 0x20<proposalID_Bytes><voterAddr_Bytes>: Voter
|
||||
var (
|
||||
ProposalsKeyPrefix = []byte{0x00}
|
||||
ActiveProposalQueuePrefix = []byte{0x01}
|
||||
InactiveProposalQueuePrefix = []byte{0x02}
|
||||
ProposalIDKey = []byte{0x03}
|
||||
|
||||
DepositsKeyPrefix = []byte{0x10}
|
||||
|
||||
VotesKeyPrefix = []byte{0x20}
|
||||
)
|
||||
|
||||
var lenTime = len(sdk.FormatTimeBytes(time.Now()))
|
||||
|
||||
// GetProposalIDBytes returns the byte representation of the proposalID
|
||||
func GetProposalIDBytes(proposalID uint64) (proposalIDBz []byte) {
|
||||
proposalIDBz = make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(proposalIDBz, proposalID)
|
||||
return
|
||||
}
|
||||
|
||||
// GetProposalIDFromBytes returns proposalID in uint64 format from a byte array
|
||||
func GetProposalIDFromBytes(bz []byte) (proposalID uint64) {
|
||||
return binary.BigEndian.Uint64(bz)
|
||||
}
|
||||
|
||||
// ProposalKey gets a specific proposal from the store
|
||||
func ProposalKey(proposalID uint64) []byte {
|
||||
return append(ProposalsKeyPrefix, GetProposalIDBytes(proposalID)...)
|
||||
}
|
||||
|
||||
// ActiveProposalByTimeKey gets the active proposal queue key by endTime
|
||||
func ActiveProposalByTimeKey(endTime time.Time) []byte {
|
||||
return append(ActiveProposalQueuePrefix, sdk.FormatTimeBytes(endTime)...)
|
||||
}
|
||||
|
||||
// ActiveProposalQueueKey returns the key for a proposalID in the activeProposalQueue
|
||||
func ActiveProposalQueueKey(proposalID uint64, endTime time.Time) []byte {
|
||||
return append(ActiveProposalByTimeKey(endTime), GetProposalIDBytes(proposalID)...)
|
||||
}
|
||||
|
||||
// InactiveProposalByTimeKey gets the inactive proposal queue key by endTime
|
||||
func InactiveProposalByTimeKey(endTime time.Time) []byte {
|
||||
return append(InactiveProposalQueuePrefix, sdk.FormatTimeBytes(endTime)...)
|
||||
}
|
||||
|
||||
// InactiveProposalQueueKey returns the key for a proposalID in the inactiveProposalQueue
|
||||
func InactiveProposalQueueKey(proposalID uint64, endTime time.Time) []byte {
|
||||
return append(InactiveProposalByTimeKey(endTime), GetProposalIDBytes(proposalID)...)
|
||||
}
|
||||
|
||||
// DepositsKey gets the first part of the deposits key based on the proposalID
|
||||
func DepositsKey(proposalID uint64) []byte {
|
||||
return append(DepositsKeyPrefix, GetProposalIDBytes(proposalID)...)
|
||||
}
|
||||
|
||||
// DepositKey key of a specific deposit from the store
|
||||
func DepositKey(proposalID uint64, depositorAddr sdk.AccAddress) []byte {
|
||||
return append(DepositsKey(proposalID), depositorAddr.Bytes()...)
|
||||
}
|
||||
|
||||
// VotesKey gets the first part of the votes key based on the proposalID
|
||||
func VotesKey(proposalID uint64) []byte {
|
||||
return append(VotesKeyPrefix, GetProposalIDBytes(proposalID)...)
|
||||
}
|
||||
|
||||
// VoteKey key of a specific vote from the store
|
||||
func VoteKey(proposalID uint64, voterAddr sdk.AccAddress) []byte {
|
||||
return append(VotesKey(proposalID), voterAddr.Bytes()...)
|
||||
}
|
||||
|
||||
// Split keys function; used for iterators
|
||||
|
||||
// SplitProposalKey split the proposal key and returns the proposal id
|
||||
func SplitProposalKey(key []byte) (proposalID uint64) {
|
||||
kv.AssertKeyLength(key[1:], 8)
|
||||
|
||||
return GetProposalIDFromBytes(key[1:])
|
||||
}
|
||||
|
||||
// SplitActiveProposalQueueKey split the active proposal key and returns the proposal id and endTime
|
||||
func SplitActiveProposalQueueKey(key []byte) (proposalID uint64, endTime time.Time) {
|
||||
return splitKeyWithTime(key)
|
||||
}
|
||||
|
||||
// SplitInactiveProposalQueueKey split the inactive proposal key and returns the proposal id and endTime
|
||||
func SplitInactiveProposalQueueKey(key []byte) (proposalID uint64, endTime time.Time) {
|
||||
return splitKeyWithTime(key)
|
||||
}
|
||||
|
||||
// SplitKeyDeposit split the deposits key and returns the proposal id and depositor address
|
||||
func SplitKeyDeposit(key []byte) (proposalID uint64, depositorAddr sdk.AccAddress) {
|
||||
return splitKeyWithAddress(key)
|
||||
}
|
||||
|
||||
// SplitKeyVote split the votes key and returns the proposal id and voter address
|
||||
func SplitKeyVote(key []byte) (proposalID uint64, voterAddr sdk.AccAddress) {
|
||||
return splitKeyWithAddress(key)
|
||||
}
|
||||
|
||||
// private functions
|
||||
|
||||
func splitKeyWithTime(key []byte) (proposalID uint64, endTime time.Time) {
|
||||
kv.AssertKeyLength(key[1:], 8+lenTime)
|
||||
|
||||
endTime, err := sdk.ParseTimeBytes(key[1 : 1+lenTime])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
proposalID = GetProposalIDFromBytes(key[1+lenTime:])
|
||||
return
|
||||
}
|
||||
|
||||
func splitKeyWithAddress(key []byte) (proposalID uint64, addr sdk.AccAddress) {
|
||||
kv.AssertKeyLength(key[1:], 8+addrLen)
|
||||
|
||||
kv.AssertKeyAtLeastLength(key, 10)
|
||||
proposalID = GetProposalIDFromBytes(key[1:9])
|
||||
addr = sdk.AccAddress(key[9:])
|
||||
return
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
)
|
||||
|
||||
// migrateJSONWeightedVotes migrates the ADR-037 weighted votes.
|
||||
func migrateJSONWeightedVotes(oldVotes v1beta1.Votes) v1beta1.Votes {
|
||||
newVotes := make(v1beta1.Votes, len(oldVotes))
|
||||
for i, oldVote := range oldVotes {
|
||||
newVotes[i] = migrateVote(oldVote)
|
||||
}
|
||||
|
||||
return newVotes
|
||||
}
|
||||
|
||||
// MigrateJSON accepts exported v1 (v0.40) x/gov genesis state and migrates it to
|
||||
// v2 (v0.43) x/gov genesis state. The migration includes:
|
||||
//
|
||||
// - Gov weighted votes.
|
||||
func MigrateJSON(oldState *v1beta1.GenesisState) *v1beta1.GenesisState {
|
||||
return &v1beta1.GenesisState{
|
||||
StartingProposalId: oldState.StartingProposalId,
|
||||
Deposits: oldState.Deposits,
|
||||
Votes: migrateJSONWeightedVotes(oldState.Votes),
|
||||
Proposals: oldState.Proposals,
|
||||
DepositParams: oldState.DepositParams,
|
||||
VotingParams: oldState.VotingParams,
|
||||
TallyParams: oldState.TallyParams,
|
||||
}
|
||||
}
|
||||
@ -1,125 +0,0 @@
|
||||
package v2_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
v2 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v2"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
)
|
||||
|
||||
func TestMigrateJSON(t *testing.T) {
|
||||
encodingConfig := moduletestutil.MakeTestEncodingConfig()
|
||||
clientCtx := client.Context{}.
|
||||
WithInterfaceRegistry(encodingConfig.InterfaceRegistry).
|
||||
WithTxConfig(encodingConfig.TxConfig).
|
||||
WithCodec(encodingConfig.Codec)
|
||||
|
||||
voter, err := sdk.AccAddressFromBech32("cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh")
|
||||
require.NoError(t, err)
|
||||
govGenState := &v1beta1.GenesisState{
|
||||
Votes: v1beta1.Votes{
|
||||
v1beta1.Vote{ProposalId: 1, Voter: voter.String(), Option: v1beta1.OptionAbstain},
|
||||
v1beta1.Vote{ProposalId: 2, Voter: voter.String(), Option: v1beta1.OptionEmpty},
|
||||
v1beta1.Vote{ProposalId: 3, Voter: voter.String(), Option: v1beta1.OptionNo},
|
||||
v1beta1.Vote{ProposalId: 4, Voter: voter.String(), Option: v1beta1.OptionNoWithVeto},
|
||||
v1beta1.Vote{ProposalId: 5, Voter: voter.String(), Option: v1beta1.OptionYes},
|
||||
},
|
||||
}
|
||||
|
||||
migrated := v2.MigrateJSON(govGenState)
|
||||
|
||||
bz, err := clientCtx.Codec.MarshalJSON(migrated)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Indent the JSON bz correctly.
|
||||
var jsonObj map[string]interface{}
|
||||
err = json.Unmarshal(bz, &jsonObj)
|
||||
require.NoError(t, err)
|
||||
indentedBz, err := json.MarshalIndent(jsonObj, "", "\t")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Make sure about:
|
||||
// - Votes are all ADR-037 weighted votes with weight 1.
|
||||
expected := `{
|
||||
"deposit_params": {
|
||||
"max_deposit_period": "0s",
|
||||
"min_deposit": []
|
||||
},
|
||||
"deposits": [],
|
||||
"proposals": [],
|
||||
"starting_proposal_id": "0",
|
||||
"tally_params": {
|
||||
"quorum": "0",
|
||||
"threshold": "0",
|
||||
"veto_threshold": "0"
|
||||
},
|
||||
"votes": [
|
||||
{
|
||||
"option": "VOTE_OPTION_UNSPECIFIED",
|
||||
"options": [
|
||||
{
|
||||
"option": "VOTE_OPTION_ABSTAIN",
|
||||
"weight": "1.000000000000000000"
|
||||
}
|
||||
],
|
||||
"proposal_id": "1",
|
||||
"voter": "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh"
|
||||
},
|
||||
{
|
||||
"option": "VOTE_OPTION_UNSPECIFIED",
|
||||
"options": [
|
||||
{
|
||||
"option": "VOTE_OPTION_UNSPECIFIED",
|
||||
"weight": "1.000000000000000000"
|
||||
}
|
||||
],
|
||||
"proposal_id": "2",
|
||||
"voter": "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh"
|
||||
},
|
||||
{
|
||||
"option": "VOTE_OPTION_UNSPECIFIED",
|
||||
"options": [
|
||||
{
|
||||
"option": "VOTE_OPTION_NO",
|
||||
"weight": "1.000000000000000000"
|
||||
}
|
||||
],
|
||||
"proposal_id": "3",
|
||||
"voter": "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh"
|
||||
},
|
||||
{
|
||||
"option": "VOTE_OPTION_UNSPECIFIED",
|
||||
"options": [
|
||||
{
|
||||
"option": "VOTE_OPTION_NO_WITH_VETO",
|
||||
"weight": "1.000000000000000000"
|
||||
}
|
||||
],
|
||||
"proposal_id": "4",
|
||||
"voter": "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh"
|
||||
},
|
||||
{
|
||||
"option": "VOTE_OPTION_UNSPECIFIED",
|
||||
"options": [
|
||||
{
|
||||
"option": "VOTE_OPTION_YES",
|
||||
"weight": "1.000000000000000000"
|
||||
}
|
||||
],
|
||||
"proposal_id": "5",
|
||||
"voter": "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh"
|
||||
}
|
||||
],
|
||||
"voting_params": {
|
||||
"voting_period": "0s"
|
||||
}
|
||||
}`
|
||||
|
||||
require.Equal(t, expected, string(indentedBz))
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
package v2
|
||||
|
||||
const (
|
||||
// ModuleName is the name of the module
|
||||
ModuleName = "gov"
|
||||
)
|
||||
@ -1,102 +0,0 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
corestoretypes "cosmossdk.io/core/store"
|
||||
"cosmossdk.io/store/prefix"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/address"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
)
|
||||
|
||||
const proposalIDLen = 8
|
||||
|
||||
// migratePrefixProposalAddress is a helper function that migrates all keys of format:
|
||||
// <prefix_bytes><proposal_id (8 bytes)><address_bytes>
|
||||
// into format:
|
||||
// <prefix_bytes><proposal_id (8 bytes)><address_len (1 byte)><address_bytes>
|
||||
func migratePrefixProposalAddress(store corestoretypes.KVStore, prefixBz []byte) error {
|
||||
oldStore := prefix.NewStore(runtime.KVStoreAdapter(store), prefixBz)
|
||||
|
||||
oldStoreIter := oldStore.Iterator(nil, nil)
|
||||
defer oldStoreIter.Close()
|
||||
|
||||
for ; oldStoreIter.Valid(); oldStoreIter.Next() {
|
||||
proposalID := oldStoreIter.Key()[:proposalIDLen]
|
||||
addr := oldStoreIter.Key()[proposalIDLen:]
|
||||
newStoreKey := append(append(prefixBz, proposalID...), address.MustLengthPrefix(addr)...)
|
||||
|
||||
// Set new key on store. Values don't change.
|
||||
err := store.Set(newStoreKey, oldStoreIter.Value())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldStore.Delete(oldStoreIter.Key())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// migrateStoreWeightedVotes migrates a legacy vote to an ADR-037 weighted vote.
|
||||
// Important: the `oldVote` has its `Option` field set, whereas the new weighted
|
||||
// vote has its `Options` field set.
|
||||
func migrateVote(oldVote v1beta1.Vote) v1beta1.Vote {
|
||||
return v1beta1.Vote{
|
||||
ProposalId: oldVote.ProposalId,
|
||||
Voter: oldVote.Voter,
|
||||
Options: v1beta1.NewNonSplitVoteOption(oldVote.Option),
|
||||
}
|
||||
}
|
||||
|
||||
// migrateStoreWeightedVotes migrates in-place all legacy votes to ADR-037 weighted votes.
|
||||
func migrateStoreWeightedVotes(store corestoretypes.KVStore, cdc codec.BinaryCodec) error {
|
||||
iterator := storetypes.KVStorePrefixIterator(runtime.KVStoreAdapter(store), types.VotesKeyPrefix)
|
||||
|
||||
defer iterator.Close()
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
var oldVote v1beta1.Vote
|
||||
err := cdc.Unmarshal(iterator.Value(), &oldVote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newVote := migrateVote(oldVote)
|
||||
fmt.Println("migrateStoreWeightedVotes newVote=", newVote)
|
||||
bz, err := cdc.Marshal(&newVote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = store.Set(iterator.Key(), bz)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MigrateStore performs in-place store migrations from v1 (v0.40) to v2 (v0.43). The
|
||||
// migration includes:
|
||||
//
|
||||
// - Change addresses to be length-prefixed.
|
||||
// - Change all legacy votes to ADR-037 weighted votes.
|
||||
func MigrateStore(ctx sdk.Context, storeService corestoretypes.KVStoreService, cdc codec.BinaryCodec) error {
|
||||
store := storeService.OpenKVStore(ctx)
|
||||
err := migratePrefixProposalAddress(store, types.DepositsKeyPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = migratePrefixProposalAddress(store, types.VotesKeyPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return migrateStoreWeightedVotes(store, cdc)
|
||||
}
|
||||
@ -1,117 +0,0 @@
|
||||
package v2_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/address"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v1"
|
||||
v2 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v2"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
)
|
||||
|
||||
func TestMigrateStore(t *testing.T) {
|
||||
cdc := moduletestutil.MakeTestEncodingConfig().Codec
|
||||
govKey := storetypes.NewKVStoreKey("gov")
|
||||
ctx := testutil.DefaultContext(govKey, storetypes.NewTransientStoreKey("transient_test"))
|
||||
store := ctx.KVStore(govKey)
|
||||
|
||||
_, _, addr1 := testdata.KeyTestPubAddr()
|
||||
proposalID := uint64(6)
|
||||
now := time.Now()
|
||||
// Use dummy value for keys where we don't test values.
|
||||
dummyValue := []byte("foo")
|
||||
// Use real values for votes, as we're testing weighted votes.
|
||||
oldVote := v1beta1.Vote{ProposalId: 1, Voter: "foobar", Option: v1beta1.OptionNoWithVeto}
|
||||
oldVoteValue := cdc.MustMarshal(&oldVote)
|
||||
newVote := v1beta1.Vote{ProposalId: 1, Voter: "foobar", Options: v1beta1.WeightedVoteOptions{{Option: v1beta1.OptionNoWithVeto, Weight: math.LegacyNewDec(1)}}}
|
||||
newVoteValue := cdc.MustMarshal(&newVote)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
oldKey, oldValue, newKey, newValue []byte
|
||||
}{
|
||||
{
|
||||
"ProposalKey",
|
||||
v1.ProposalKey(proposalID), dummyValue,
|
||||
append(types.ProposalsKeyPrefix, sdk.Uint64ToBigEndian(proposalID)...), dummyValue,
|
||||
},
|
||||
{
|
||||
"ActiveProposalQueue",
|
||||
v1.ActiveProposalQueueKey(proposalID, now), dummyValue,
|
||||
activeProposalQueueKey(proposalID, now), dummyValue,
|
||||
},
|
||||
{
|
||||
"InactiveProposalQueue",
|
||||
v1.InactiveProposalQueueKey(proposalID, now), dummyValue,
|
||||
inactiveProposalQueueKey(proposalID, now), dummyValue,
|
||||
},
|
||||
{
|
||||
"ProposalIDKey",
|
||||
v1.ProposalIDKey, dummyValue,
|
||||
types.ProposalIDKey, dummyValue,
|
||||
},
|
||||
{
|
||||
"DepositKey",
|
||||
v1.DepositKey(proposalID, addr1), dummyValue,
|
||||
depositKey(proposalID, addr1), dummyValue,
|
||||
},
|
||||
{
|
||||
"VotesKeyPrefix",
|
||||
v1.VoteKey(proposalID, addr1), oldVoteValue,
|
||||
voteKey(proposalID, addr1), newVoteValue,
|
||||
},
|
||||
}
|
||||
|
||||
// Set all the old keys to the store
|
||||
for _, tc := range testCases {
|
||||
store.Set(tc.oldKey, tc.oldValue)
|
||||
}
|
||||
|
||||
// Run migratio
|
||||
storeService := runtime.NewKVStoreService(govKey)
|
||||
err := v2.MigrateStore(ctx, storeService, cdc)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Make sure the new keys are set and old keys are deleted.
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if !bytes.Equal(tc.oldKey, tc.newKey) {
|
||||
require.Nil(t, store.Get(tc.oldKey))
|
||||
}
|
||||
require.Equal(t, tc.newValue, store.Get(tc.newKey))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(tip): remove all the functions below once we delete the migrations
|
||||
|
||||
func depositKey(proposalID uint64, depositorAddr sdk.AccAddress) []byte {
|
||||
return append(append(types.DepositsKeyPrefix, sdk.Uint64ToBigEndian(proposalID)...), address.MustLengthPrefix(depositorAddr.Bytes())...)
|
||||
}
|
||||
|
||||
func voteKey(proposalID uint64, addr sdk.AccAddress) []byte {
|
||||
return append(append(types.VotesKeyPrefix, sdk.Uint64ToBigEndian(proposalID)...), address.MustLengthPrefix(addr.Bytes())...)
|
||||
}
|
||||
|
||||
func activeProposalQueueKey(proposalID uint64, endTime time.Time) []byte {
|
||||
return append(append(types.ActiveProposalQueuePrefix, sdk.FormatTimeBytes(endTime)...), sdk.Uint64ToBigEndian(proposalID)...)
|
||||
}
|
||||
|
||||
// InactiveProposalQueueKey returns the key for a proposalID in the inactiveProposalQueue
|
||||
func inactiveProposalQueueKey(proposalID uint64, endTime time.Time) []byte {
|
||||
return append(append(types.InactiveProposalQueuePrefix, sdk.FormatTimeBytes(endTime)...), sdk.Uint64ToBigEndian(proposalID)...)
|
||||
}
|
||||
@ -8,11 +8,15 @@ import (
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
)
|
||||
|
||||
const (
|
||||
// ModuleName is the name of the module
|
||||
ModuleName = "gov"
|
||||
)
|
||||
|
||||
// ConvertToLegacyProposal takes a new proposal and attempts to convert it to the
|
||||
// legacy proposal format. This conversion is best effort. New proposal types that
|
||||
// don't have a legacy message will return a "nil" content.
|
||||
@ -131,113 +135,3 @@ func ConvertToLegacyDeposit(deposit *v1.Deposit) v1beta1.Deposit {
|
||||
Amount: types.NewCoins(deposit.Amount...),
|
||||
}
|
||||
}
|
||||
|
||||
func convertToNewDeposits(oldDeps v1beta1.Deposits) v1.Deposits {
|
||||
newDeps := make([]*v1.Deposit, len(oldDeps))
|
||||
for i, oldDep := range oldDeps {
|
||||
newDeps[i] = &v1.Deposit{
|
||||
ProposalId: oldDep.ProposalId,
|
||||
Depositor: oldDep.Depositor,
|
||||
Amount: oldDep.Amount,
|
||||
}
|
||||
}
|
||||
|
||||
return newDeps
|
||||
}
|
||||
|
||||
func convertToNewVotes(oldVotes v1beta1.Votes) (v1.Votes, error) {
|
||||
newVotes := make([]*v1.Vote, len(oldVotes))
|
||||
for i, oldVote := range oldVotes {
|
||||
var newWVOs []*v1.WeightedVoteOption
|
||||
|
||||
// We deprecated Vote.Option in v043. However, it might still be set.
|
||||
// - if only Options is set, or both Option & Options are set, we read from Options,
|
||||
// - if Options is not set, and Option is set, we read from Option,
|
||||
// - if none are set, we throw error.
|
||||
switch {
|
||||
case oldVote.Options != nil:
|
||||
newWVOs = make([]*v1.WeightedVoteOption, len(oldVote.Options))
|
||||
for j, oldWVO := range oldVote.Options {
|
||||
newWVOs[j] = v1.NewWeightedVoteOption(v1.VoteOption(oldWVO.Option), oldWVO.Weight)
|
||||
}
|
||||
|
||||
case oldVote.Option != v1beta1.OptionEmpty:
|
||||
newWVOs = v1.NewNonSplitVoteOption(v1.VoteOption(oldVote.Option))
|
||||
default:
|
||||
return nil, fmt.Errorf("vote does not have neither InterfaceRegistryOptions nor Option")
|
||||
}
|
||||
|
||||
newVotes[i] = &v1.Vote{
|
||||
ProposalId: oldVote.ProposalId,
|
||||
Voter: oldVote.Voter,
|
||||
Options: newWVOs,
|
||||
}
|
||||
}
|
||||
|
||||
return newVotes, nil
|
||||
}
|
||||
|
||||
func convertToNewDepParams(oldDepParams v1beta1.DepositParams) v1.DepositParams {
|
||||
return v1.DepositParams{
|
||||
MinDeposit: oldDepParams.MinDeposit,
|
||||
MaxDepositPeriod: &oldDepParams.MaxDepositPeriod,
|
||||
}
|
||||
}
|
||||
|
||||
func convertToNewVotingParams(oldVoteParams v1beta1.VotingParams) v1.VotingParams {
|
||||
return v1.VotingParams{
|
||||
VotingPeriod: &oldVoteParams.VotingPeriod,
|
||||
}
|
||||
}
|
||||
|
||||
func convertToNewTallyParams(oldTallyParams v1beta1.TallyParams) v1.TallyParams {
|
||||
return v1.TallyParams{
|
||||
Quorum: oldTallyParams.Quorum.String(),
|
||||
Threshold: oldTallyParams.Threshold.String(),
|
||||
VetoThreshold: oldTallyParams.VetoThreshold.String(),
|
||||
}
|
||||
}
|
||||
|
||||
func convertToNewProposal(oldProp v1beta1.Proposal) (v1.Proposal, error) {
|
||||
msg, err := v1.NewLegacyContent(oldProp.GetContent(), authtypes.NewModuleAddress(ModuleName).String())
|
||||
if err != nil {
|
||||
return v1.Proposal{}, err
|
||||
}
|
||||
msgAny, err := codectypes.NewAnyWithValue(msg)
|
||||
if err != nil {
|
||||
return v1.Proposal{}, err
|
||||
}
|
||||
|
||||
return v1.Proposal{
|
||||
Id: oldProp.ProposalId,
|
||||
Messages: []*codectypes.Any{msgAny},
|
||||
Status: v1.ProposalStatus(oldProp.Status),
|
||||
FinalTallyResult: &v1.TallyResult{
|
||||
YesCount: oldProp.FinalTallyResult.Yes.String(),
|
||||
NoCount: oldProp.FinalTallyResult.No.String(),
|
||||
AbstainCount: oldProp.FinalTallyResult.Abstain.String(),
|
||||
NoWithVetoCount: oldProp.FinalTallyResult.NoWithVeto.String(),
|
||||
},
|
||||
SubmitTime: &oldProp.SubmitTime,
|
||||
DepositEndTime: &oldProp.DepositEndTime,
|
||||
TotalDeposit: oldProp.TotalDeposit,
|
||||
VotingStartTime: &oldProp.VotingStartTime,
|
||||
VotingEndTime: &oldProp.VotingEndTime,
|
||||
Title: oldProp.GetContent().GetTitle(),
|
||||
Summary: oldProp.GetContent().GetDescription(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func convertToNewProposals(oldProps v1beta1.Proposals) (v1.Proposals, error) {
|
||||
newProps := make([]*v1.Proposal, len(oldProps))
|
||||
for i, oldProp := range oldProps {
|
||||
p, err := convertToNewProposal(oldProp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newProps[i] = &p
|
||||
}
|
||||
|
||||
return newProps, nil
|
||||
}
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
)
|
||||
|
||||
// MigrateJSON accepts exported v2 (v0.43) x/gov genesis state and migrates it to
|
||||
// v3 (V0.46) x/gov genesis state. The migration includes:
|
||||
//
|
||||
// - Updating everything to v1.
|
||||
// - Migrating proposals to be Msg-based.
|
||||
func MigrateJSON(oldState *v1beta1.GenesisState) (*v1.GenesisState, error) {
|
||||
newProps, err := convertToNewProposals(oldState.Proposals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newVotes, err := convertToNewVotes(oldState.Votes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
depParams, votingParms, tallyParams := convertToNewDepParams(oldState.DepositParams), convertToNewVotingParams(oldState.VotingParams), convertToNewTallyParams(oldState.TallyParams)
|
||||
|
||||
return &v1.GenesisState{
|
||||
StartingProposalId: oldState.StartingProposalId,
|
||||
Deposits: convertToNewDeposits(oldState.Deposits),
|
||||
Votes: newVotes,
|
||||
Proposals: newProps,
|
||||
DepositParams: &depParams,
|
||||
VotingParams: &votingParms,
|
||||
TallyParams: &tallyParams,
|
||||
}, nil
|
||||
}
|
||||
@ -1,165 +0,0 @@
|
||||
package v3_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
sdkmath "cosmossdk.io/math"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
v3 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v3"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
)
|
||||
|
||||
var voter = sdk.MustAccAddressFromBech32("cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh")
|
||||
|
||||
func TestMigrateJSON(t *testing.T) {
|
||||
encodingConfig := moduletestutil.MakeTestEncodingConfig(gov.AppModuleBasic{})
|
||||
clientCtx := client.Context{}.
|
||||
WithInterfaceRegistry(encodingConfig.InterfaceRegistry).
|
||||
WithTxConfig(encodingConfig.TxConfig).
|
||||
WithCodec(encodingConfig.Codec)
|
||||
|
||||
govGenState := v1beta1.DefaultGenesisState()
|
||||
propTime := time.Unix(1e9, 0)
|
||||
contentAny, err := codectypes.NewAnyWithValue(v1beta1.NewTextProposal("my title", "my desc").(proto.Message))
|
||||
require.NoError(t, err)
|
||||
govGenState.Proposals = v1beta1.Proposals{
|
||||
v1beta1.Proposal{
|
||||
ProposalId: 1,
|
||||
Content: contentAny,
|
||||
SubmitTime: propTime,
|
||||
DepositEndTime: propTime,
|
||||
VotingStartTime: propTime,
|
||||
VotingEndTime: propTime,
|
||||
Status: v1beta1.StatusDepositPeriod,
|
||||
FinalTallyResult: v1beta1.EmptyTallyResult(),
|
||||
TotalDeposit: sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(123))),
|
||||
},
|
||||
}
|
||||
govGenState.Votes = v1beta1.Votes{
|
||||
v1beta1.Vote{ProposalId: 1, Voter: voter.String(), Option: v1beta1.OptionAbstain},
|
||||
v1beta1.Vote{ProposalId: 2, Voter: voter.String(), Options: v1beta1.NewNonSplitVoteOption(v1beta1.OptionNo)},
|
||||
}
|
||||
|
||||
migrated, err := v3.MigrateJSON(govGenState)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Make sure the migrated proposal's Msg signer is the gov acct.
|
||||
require.Equal(t,
|
||||
authtypes.NewModuleAddress(types.ModuleName).String(),
|
||||
migrated.Proposals[0].Messages[0].GetCachedValue().(*v1.MsgExecLegacyContent).Authority,
|
||||
)
|
||||
|
||||
bz, err := clientCtx.Codec.MarshalJSON(migrated)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Indent the JSON bz correctly.
|
||||
var jsonObj map[string]interface{}
|
||||
err = json.Unmarshal(bz, &jsonObj)
|
||||
require.NoError(t, err)
|
||||
indentedBz, err := json.MarshalIndent(jsonObj, "", "\t")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Make sure about:
|
||||
// - Proposals use MsgExecLegacyContent
|
||||
expected := `{
|
||||
"constitution": "",
|
||||
"deposit_params": {
|
||||
"max_deposit_period": "172800s",
|
||||
"min_deposit": [
|
||||
{
|
||||
"amount": "10000000",
|
||||
"denom": "stake"
|
||||
}
|
||||
]
|
||||
},
|
||||
"deposits": [],
|
||||
"params": null,
|
||||
"proposals": [
|
||||
{
|
||||
"deposit_end_time": "2001-09-09T01:46:40Z",
|
||||
"expedited": false,
|
||||
"failed_reason": "",
|
||||
"final_tally_result": {
|
||||
"abstain_count": "0",
|
||||
"no_count": "0",
|
||||
"no_with_veto_count": "0",
|
||||
"yes_count": "0"
|
||||
},
|
||||
"id": "1",
|
||||
"messages": [
|
||||
{
|
||||
"@type": "/cosmos.gov.v1.MsgExecLegacyContent",
|
||||
"authority": "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn",
|
||||
"content": {
|
||||
"@type": "/cosmos.gov.v1beta1.TextProposal",
|
||||
"description": "my desc",
|
||||
"title": "my title"
|
||||
}
|
||||
}
|
||||
],
|
||||
"metadata": "",
|
||||
"proposer": "",
|
||||
"status": "PROPOSAL_STATUS_DEPOSIT_PERIOD",
|
||||
"submit_time": "2001-09-09T01:46:40Z",
|
||||
"summary": "my desc",
|
||||
"title": "my title",
|
||||
"total_deposit": [
|
||||
{
|
||||
"amount": "123",
|
||||
"denom": "stake"
|
||||
}
|
||||
],
|
||||
"voting_end_time": "2001-09-09T01:46:40Z",
|
||||
"voting_start_time": "2001-09-09T01:46:40Z"
|
||||
}
|
||||
],
|
||||
"starting_proposal_id": "1",
|
||||
"tally_params": {
|
||||
"quorum": "0.334000000000000000",
|
||||
"threshold": "0.500000000000000000",
|
||||
"veto_threshold": "0.334000000000000000"
|
||||
},
|
||||
"votes": [
|
||||
{
|
||||
"metadata": "",
|
||||
"options": [
|
||||
{
|
||||
"option": "VOTE_OPTION_ABSTAIN",
|
||||
"weight": "1.000000000000000000"
|
||||
}
|
||||
],
|
||||
"proposal_id": "1",
|
||||
"voter": "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh"
|
||||
},
|
||||
{
|
||||
"metadata": "",
|
||||
"options": [
|
||||
{
|
||||
"option": "VOTE_OPTION_NO",
|
||||
"weight": "1.000000000000000000"
|
||||
}
|
||||
],
|
||||
"proposal_id": "2",
|
||||
"voter": "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh"
|
||||
}
|
||||
],
|
||||
"voting_params": {
|
||||
"voting_period": "172800s"
|
||||
}
|
||||
}`
|
||||
|
||||
require.Equal(t, expected, string(indentedBz))
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
package v3
|
||||
|
||||
const (
|
||||
// ModuleName is the name of the module
|
||||
ModuleName = "gov"
|
||||
)
|
||||
@ -1,98 +0,0 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
corestoretypes "cosmossdk.io/core/store"
|
||||
"cosmossdk.io/store/prefix"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v1"
|
||||
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
)
|
||||
|
||||
// migrateProposals migrates all legacy proposals into MsgExecLegacyContent
|
||||
// proposals.
|
||||
func migrateProposals(store storetypes.KVStore, cdc codec.BinaryCodec) error {
|
||||
propStore := prefix.NewStore(store, v1.ProposalsKeyPrefix)
|
||||
|
||||
iter := propStore.Iterator(nil, nil)
|
||||
defer iter.Close()
|
||||
|
||||
for ; iter.Valid(); iter.Next() {
|
||||
var oldProp govv1beta1.Proposal
|
||||
err := cdc.Unmarshal(iter.Value(), &oldProp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newProp, err := convertToNewProposal(oldProp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bz, err := cdc.Marshal(&newProp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set new value on store.
|
||||
propStore.Set(iter.Key(), bz)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// migrateVotes migrates all v1beta1 weighted votes (with sdk.Dec as weight)
|
||||
// to v1 weighted votes (with string as weight)
|
||||
func migrateVotes(store storetypes.KVStore, cdc codec.BinaryCodec) error {
|
||||
votesStore := prefix.NewStore(store, v1.VotesKeyPrefix)
|
||||
|
||||
iter := votesStore.Iterator(nil, nil)
|
||||
defer iter.Close()
|
||||
|
||||
for ; iter.Valid(); iter.Next() {
|
||||
var oldVote govv1beta1.Vote
|
||||
err := cdc.Unmarshal(iter.Value(), &oldVote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newVote := govv1.Vote{
|
||||
ProposalId: oldVote.ProposalId,
|
||||
Voter: oldVote.Voter,
|
||||
}
|
||||
newOptions := make([]*govv1.WeightedVoteOption, len(oldVote.Options))
|
||||
for i, o := range oldVote.Options {
|
||||
newOptions[i] = &govv1.WeightedVoteOption{
|
||||
Option: govv1.VoteOption(o.Option),
|
||||
Weight: o.Weight.String(), // Convert to decimal string
|
||||
}
|
||||
}
|
||||
newVote.Options = newOptions
|
||||
bz, err := cdc.Marshal(&newVote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set new value on store.
|
||||
votesStore.Set(iter.Key(), bz)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MigrateStore performs in-place store migrations from v2 (v0.43) to v3 (v0.46). The
|
||||
// migration includes:
|
||||
//
|
||||
// - Migrate proposals to be Msg-based.
|
||||
func MigrateStore(ctx sdk.Context, storeService corestoretypes.KVStoreService, cdc codec.BinaryCodec) error {
|
||||
store := storeService.OpenKVStore(ctx)
|
||||
|
||||
if err := migrateVotes(runtime.KVStoreAdapter(store), cdc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return migrateProposals(runtime.KVStoreAdapter(store), cdc)
|
||||
}
|
||||
@ -1,98 +0,0 @@
|
||||
package v3_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
v1gov "github.com/cosmos/cosmos-sdk/x/gov/migrations/v1"
|
||||
v3gov "github.com/cosmos/cosmos-sdk/x/gov/migrations/v3"
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
)
|
||||
|
||||
func TestMigrateStore(t *testing.T) {
|
||||
cdc := moduletestutil.MakeTestEncodingConfig(gov.AppModuleBasic{}).Codec
|
||||
govKey := storetypes.NewKVStoreKey("gov")
|
||||
ctx := testutil.DefaultContext(govKey, storetypes.NewTransientStoreKey("transient_test"))
|
||||
store := ctx.KVStore(govKey)
|
||||
|
||||
propTime := time.Unix(1e9, 0)
|
||||
|
||||
// Create 2 proposals
|
||||
prop1, err := v1beta1.NewProposal(v1beta1.NewTextProposal("my title 1", "my desc 1"), 1, propTime, propTime)
|
||||
require.NoError(t, err)
|
||||
prop1Bz, err := cdc.Marshal(&prop1)
|
||||
require.NoError(t, err)
|
||||
prop2, err := v1beta1.NewProposal(v1beta1.NewTextProposal("my title 2", "my desc 2"), 2, propTime, propTime)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
prop2Bz, err := cdc.Marshal(&prop2)
|
||||
require.NoError(t, err)
|
||||
|
||||
store.Set(v1gov.ProposalKey(prop1.ProposalId), prop1Bz)
|
||||
store.Set(v1gov.ProposalKey(prop2.ProposalId), prop2Bz)
|
||||
|
||||
// Vote on prop 1
|
||||
options := []v1beta1.WeightedVoteOption{
|
||||
{Option: v1beta1.OptionNo, Weight: math.LegacyMustNewDecFromStr("0.3")},
|
||||
{Option: v1beta1.OptionYes, Weight: math.LegacyMustNewDecFromStr("0.7")},
|
||||
}
|
||||
vote1 := v1beta1.Vote{ProposalId: 1, Voter: voter.String(), Options: options}
|
||||
vote1Bz := cdc.MustMarshal(&vote1)
|
||||
store.Set(v1gov.VoteKey(1, voter), vote1Bz)
|
||||
|
||||
// Run migrations.
|
||||
storeService := runtime.NewKVStoreService(govKey)
|
||||
err = v3gov.MigrateStore(ctx, storeService, cdc)
|
||||
require.NoError(t, err)
|
||||
|
||||
var newProp1 v1.Proposal
|
||||
err = cdc.Unmarshal(store.Get(v1gov.ProposalKey(prop1.ProposalId)), &newProp1)
|
||||
require.NoError(t, err)
|
||||
compareProps(t, prop1, newProp1)
|
||||
|
||||
var newProp2 v1.Proposal
|
||||
err = cdc.Unmarshal(store.Get(v1gov.ProposalKey(prop2.ProposalId)), &newProp2)
|
||||
require.NoError(t, err)
|
||||
compareProps(t, prop2, newProp2)
|
||||
|
||||
var newVote1 v1.Vote
|
||||
err = cdc.Unmarshal(store.Get(v1gov.VoteKey(prop1.ProposalId, voter)), &newVote1)
|
||||
require.NoError(t, err)
|
||||
// Without the votes migration, we would have 300000000000000000 in state,
|
||||
// because of how sdk.Dec stores itself in state.
|
||||
require.Equal(t, "0.300000000000000000", newVote1.Options[0].Weight)
|
||||
require.Equal(t, "0.700000000000000000", newVote1.Options[1].Weight)
|
||||
}
|
||||
|
||||
func compareProps(t *testing.T, oldProp v1beta1.Proposal, newProp v1.Proposal) {
|
||||
t.Helper()
|
||||
require.Equal(t, oldProp.ProposalId, newProp.Id)
|
||||
require.Equal(t, oldProp.TotalDeposit.String(), sdk.Coins(newProp.TotalDeposit).String())
|
||||
require.Equal(t, oldProp.Status.String(), newProp.Status.String())
|
||||
require.Equal(t, oldProp.FinalTallyResult.Yes.String(), newProp.FinalTallyResult.YesCount)
|
||||
require.Equal(t, oldProp.FinalTallyResult.No.String(), newProp.FinalTallyResult.NoCount)
|
||||
require.Equal(t, oldProp.FinalTallyResult.NoWithVeto.String(), newProp.FinalTallyResult.NoWithVetoCount)
|
||||
require.Equal(t, oldProp.FinalTallyResult.Abstain.String(), newProp.FinalTallyResult.AbstainCount)
|
||||
|
||||
newContent := newProp.Messages[0].GetCachedValue().(*v1.MsgExecLegacyContent).Content.GetCachedValue().(v1beta1.Content)
|
||||
require.Equal(t, oldProp.Content.GetCachedValue().(v1beta1.Content), newContent)
|
||||
|
||||
// Compare UNIX times, as a simple Equal gives difference between Local and
|
||||
// UTC times.
|
||||
// ref: https://github.com/golang/go/issues/19486#issuecomment-292968278
|
||||
require.Equal(t, oldProp.SubmitTime.Unix(), newProp.SubmitTime.Unix())
|
||||
require.Equal(t, oldProp.DepositEndTime.Unix(), newProp.DepositEndTime.Unix())
|
||||
require.Equal(t, oldProp.VotingStartTime.Unix(), newProp.VotingStartTime.Unix())
|
||||
require.Equal(t, oldProp.VotingEndTime.Unix(), newProp.VotingEndTime.Unix())
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
package v4
|
||||
|
||||
import (
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
)
|
||||
|
||||
// MigrateJSON accepts exported v3 (v0.46) x/gov genesis state and migrates it to
|
||||
// v4 (v0.47) x/gov genesis state. The migration includes:
|
||||
//
|
||||
// Params migrations from x/params to gov
|
||||
// Addition of the new min initial deposit ratio parameter that is set to 0 by default.
|
||||
// Proposals in voting period are tracked in a separate index.
|
||||
func MigrateJSON(oldState *v1.GenesisState) (*v1.GenesisState, error) {
|
||||
defaultParams := v1.DefaultParams()
|
||||
|
||||
params := v1.NewParams(
|
||||
oldState.DepositParams.MinDeposit,
|
||||
defaultParams.ExpeditedMinDeposit,
|
||||
*oldState.DepositParams.MaxDepositPeriod,
|
||||
*oldState.VotingParams.VotingPeriod,
|
||||
*defaultParams.ExpeditedVotingPeriod,
|
||||
oldState.TallyParams.Quorum,
|
||||
oldState.TallyParams.Threshold,
|
||||
defaultParams.ExpeditedThreshold,
|
||||
oldState.TallyParams.VetoThreshold,
|
||||
defaultParams.MinInitialDepositRatio,
|
||||
defaultParams.ProposalCancelRatio,
|
||||
defaultParams.ProposalCancelDest,
|
||||
defaultParams.BurnProposalDepositPrevote,
|
||||
defaultParams.BurnVoteQuorum,
|
||||
defaultParams.BurnVoteVeto,
|
||||
)
|
||||
|
||||
return &v1.GenesisState{
|
||||
StartingProposalId: oldState.StartingProposalId,
|
||||
Deposits: oldState.Deposits,
|
||||
Votes: oldState.Votes,
|
||||
Proposals: oldState.Proposals,
|
||||
Params: ¶ms,
|
||||
}, nil
|
||||
}
|
||||
@ -1,98 +0,0 @@
|
||||
package v4_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
v4 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v4"
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
)
|
||||
|
||||
func TestMigrateJSON(t *testing.T) {
|
||||
encodingConfig := moduletestutil.MakeTestEncodingConfig(gov.AppModuleBasic{})
|
||||
clientCtx := client.Context{}.
|
||||
WithInterfaceRegistry(encodingConfig.InterfaceRegistry).
|
||||
WithTxConfig(encodingConfig.TxConfig).
|
||||
WithCodec(encodingConfig.Codec)
|
||||
|
||||
govGenState := v1.DefaultGenesisState()
|
||||
oldGovState := &v1.GenesisState{
|
||||
StartingProposalId: govGenState.StartingProposalId,
|
||||
Deposits: govGenState.Deposits,
|
||||
Votes: govGenState.Votes,
|
||||
Proposals: govGenState.Proposals,
|
||||
DepositParams: &v1.DepositParams{
|
||||
MinDeposit: govGenState.Params.MinDeposit,
|
||||
MaxDepositPeriod: govGenState.Params.MaxDepositPeriod,
|
||||
},
|
||||
VotingParams: &v1.VotingParams{
|
||||
VotingPeriod: govGenState.Params.VotingPeriod,
|
||||
},
|
||||
TallyParams: &v1.TallyParams{
|
||||
Quorum: govGenState.Params.Quorum,
|
||||
Threshold: govGenState.Params.Threshold,
|
||||
VetoThreshold: govGenState.Params.VetoThreshold,
|
||||
},
|
||||
}
|
||||
|
||||
migrated, err := v4.MigrateJSON(oldGovState)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, migrated, govGenState)
|
||||
|
||||
bz, err := clientCtx.Codec.MarshalJSON(migrated)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Indent the JSON bz correctly.
|
||||
var jsonObj map[string]interface{}
|
||||
err = json.Unmarshal(bz, &jsonObj)
|
||||
require.NoError(t, err)
|
||||
indentedBz, err := json.MarshalIndent(jsonObj, "", "\t")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Make sure about:
|
||||
// - Proposals use MsgExecLegacyContent
|
||||
expected := `{
|
||||
"constitution": "",
|
||||
"deposit_params": null,
|
||||
"deposits": [],
|
||||
"params": {
|
||||
"burn_proposal_deposit_prevote": false,
|
||||
"burn_vote_quorum": false,
|
||||
"burn_vote_veto": true,
|
||||
"expedited_min_deposit": [
|
||||
{
|
||||
"amount": "50000000",
|
||||
"denom": "stake"
|
||||
}
|
||||
],
|
||||
"expedited_threshold": "0.667000000000000000",
|
||||
"expedited_voting_period": "86400s",
|
||||
"max_deposit_period": "172800s",
|
||||
"min_deposit": [
|
||||
{
|
||||
"amount": "10000000",
|
||||
"denom": "stake"
|
||||
}
|
||||
],
|
||||
"min_initial_deposit_ratio": "0.000000000000000000",
|
||||
"proposal_cancel_dest": "",
|
||||
"proposal_cancel_ratio": "0.500000000000000000",
|
||||
"quorum": "0.334000000000000000",
|
||||
"threshold": "0.500000000000000000",
|
||||
"veto_threshold": "0.334000000000000000",
|
||||
"voting_period": "172800s"
|
||||
},
|
||||
"proposals": [],
|
||||
"starting_proposal_id": "1",
|
||||
"tally_params": null,
|
||||
"votes": [],
|
||||
"voting_params": null
|
||||
}`
|
||||
|
||||
require.Equal(t, expected, string(indentedBz))
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package v4
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
const (
|
||||
// ModuleName is the name of the module
|
||||
ModuleName = "gov"
|
||||
)
|
||||
|
||||
var (
|
||||
// ParamsKey is the key of x/gov params
|
||||
ParamsKey = []byte{0x30}
|
||||
|
||||
// - 0x04<proposalID_Bytes>: ProposalContents
|
||||
VotingPeriodProposalKeyPrefix = []byte{0x04}
|
||||
)
|
||||
|
||||
// VotingPeriodProposalKey gets if a proposal is in voting period.
|
||||
func VotingPeriodProposalKey(proposalID uint64) []byte {
|
||||
return append(VotingPeriodProposalKeyPrefix, GetProposalIDBytes(proposalID)...)
|
||||
}
|
||||
|
||||
// GetProposalIDBytes returns the byte representation of the proposalID
|
||||
func GetProposalIDBytes(proposalID uint64) (proposalIDBz []byte) {
|
||||
proposalIDBz = make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(proposalIDBz, proposalID)
|
||||
return
|
||||
}
|
||||
@ -1,138 +0,0 @@
|
||||
package v4
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
corestoretypes "cosmossdk.io/core/store"
|
||||
"cosmossdk.io/store/prefix"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/exported"
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v1"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
)
|
||||
|
||||
func migrateParams(ctx sdk.Context, store storetypes.KVStore, legacySubspace exported.ParamSubspace, cdc codec.BinaryCodec) error {
|
||||
dp := govv1.DepositParams{}
|
||||
vp := govv1.VotingParams{}
|
||||
tp := govv1.TallyParams{}
|
||||
legacySubspace.Get(ctx, govv1.ParamStoreKeyDepositParams, &dp)
|
||||
legacySubspace.Get(ctx, govv1.ParamStoreKeyVotingParams, &vp)
|
||||
legacySubspace.Get(ctx, govv1.ParamStoreKeyTallyParams, &tp)
|
||||
|
||||
defaultParams := govv1.DefaultParams()
|
||||
params := govv1.NewParams(
|
||||
dp.MinDeposit,
|
||||
defaultParams.ExpeditedMinDeposit,
|
||||
*dp.MaxDepositPeriod,
|
||||
*vp.VotingPeriod,
|
||||
*defaultParams.ExpeditedVotingPeriod,
|
||||
tp.Quorum,
|
||||
tp.Threshold,
|
||||
defaultParams.ExpeditedThreshold,
|
||||
tp.VetoThreshold,
|
||||
defaultParams.MinInitialDepositRatio,
|
||||
defaultParams.ProposalCancelRatio,
|
||||
defaultParams.ProposalCancelDest,
|
||||
defaultParams.BurnProposalDepositPrevote,
|
||||
defaultParams.BurnVoteQuorum,
|
||||
defaultParams.BurnVoteVeto,
|
||||
)
|
||||
|
||||
bz, err := cdc.Marshal(¶ms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
store.Set(ParamsKey, bz)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func migrateProposalVotingPeriod(ctx sdk.Context, store storetypes.KVStore, cdc codec.BinaryCodec) error {
|
||||
propStore := prefix.NewStore(store, v1.ProposalsKeyPrefix)
|
||||
|
||||
iter := propStore.Iterator(nil, nil)
|
||||
defer iter.Close()
|
||||
|
||||
for ; iter.Valid(); iter.Next() {
|
||||
var prop govv1.Proposal
|
||||
err := cdc.Unmarshal(iter.Value(), &prop)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if prop.Status == govv1.StatusVotingPeriod {
|
||||
store.Set(VotingPeriodProposalKey(prop.Id), []byte{1})
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MigrateStore performs in-place store migrations from v3 (v0.46) to v4 (v0.47). The
|
||||
// migration includes:
|
||||
//
|
||||
// Params migrations from x/params to gov
|
||||
// Addition of the new min initial deposit ratio parameter that is set to 0 by default.
|
||||
// Proposals in voting period are tracked in a separate index.
|
||||
func MigrateStore(ctx sdk.Context, storeService corestoretypes.KVStoreService, legacySubspace exported.ParamSubspace, cdc codec.BinaryCodec) error {
|
||||
store := runtime.KVStoreAdapter(storeService.OpenKVStore(ctx))
|
||||
if err := migrateProposalVotingPeriod(ctx, store, cdc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return migrateParams(ctx, store, legacySubspace, cdc)
|
||||
}
|
||||
|
||||
// AddProposerAddressToProposal will add proposer to proposal and set to the store. This function is optional.
|
||||
func AddProposerAddressToProposal(ctx sdk.Context, storeService corestoretypes.KVStoreService, cdc codec.BinaryCodec, proposals map[uint64]string) error {
|
||||
proposalIDs := make([]uint64, 0, len(proposals))
|
||||
|
||||
for proposalID := range proposals {
|
||||
proposalIDs = append(proposalIDs, proposalID)
|
||||
}
|
||||
|
||||
// sort the proposalIDs
|
||||
sort.Slice(proposalIDs, func(i, j int) bool { return proposalIDs[i] < proposalIDs[j] })
|
||||
|
||||
store := runtime.KVStoreAdapter(storeService.OpenKVStore(ctx))
|
||||
|
||||
for _, proposalID := range proposalIDs {
|
||||
if len(proposals[proposalID]) == 0 {
|
||||
return fmt.Errorf("found missing proposer for proposal ID: %d", proposalID)
|
||||
}
|
||||
|
||||
if _, err := sdk.AccAddressFromBech32(proposals[proposalID]); err != nil {
|
||||
return fmt.Errorf("invalid proposer address : %s", proposals[proposalID])
|
||||
}
|
||||
|
||||
bz := store.Get(append(types.ProposalsKeyPrefix, sdk.Uint64ToBigEndian(proposalID)...))
|
||||
var proposal govv1.Proposal
|
||||
if err := cdc.Unmarshal(bz, &proposal); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Check if proposal is active
|
||||
if proposal.Status != govv1.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD &&
|
||||
proposal.Status != govv1.ProposalStatus_PROPOSAL_STATUS_DEPOSIT_PERIOD {
|
||||
return fmt.Errorf("invalid proposal : %s, proposal not active", proposals[proposalID])
|
||||
}
|
||||
|
||||
proposal.Proposer = proposals[proposalID]
|
||||
|
||||
// set the new proposal with proposer
|
||||
bz, err := cdc.Marshal(&proposal)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
store.Set(append(types.ProposalsKeyPrefix, sdk.Uint64ToBigEndian(proposalID)...), bz)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -1,138 +0,0 @@
|
||||
package v4_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
v1gov "github.com/cosmos/cosmos-sdk/x/gov/migrations/v1"
|
||||
v4 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v4"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
)
|
||||
|
||||
var (
|
||||
_, _, addr = testdata.KeyTestPubAddr()
|
||||
govAcct = authtypes.NewModuleAddress(types.ModuleName)
|
||||
TestProposal = getTestProposal()
|
||||
)
|
||||
|
||||
type mockSubspace struct {
|
||||
dp v1.DepositParams
|
||||
vp v1.VotingParams
|
||||
tp v1.TallyParams
|
||||
}
|
||||
|
||||
func newMockSubspace(p v1.Params) mockSubspace {
|
||||
return mockSubspace{
|
||||
dp: v1.DepositParams{
|
||||
MinDeposit: p.MinDeposit,
|
||||
MaxDepositPeriod: p.MaxDepositPeriod,
|
||||
},
|
||||
vp: v1.VotingParams{
|
||||
VotingPeriod: p.VotingPeriod,
|
||||
},
|
||||
tp: v1.TallyParams{
|
||||
Quorum: p.Quorum,
|
||||
Threshold: p.Threshold,
|
||||
VetoThreshold: p.VetoThreshold,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (ms mockSubspace) Get(ctx sdk.Context, key []byte, ptr interface{}) {
|
||||
switch string(key) {
|
||||
case string(v1.ParamStoreKeyDepositParams):
|
||||
*ptr.(*v1.DepositParams) = ms.dp
|
||||
case string(v1.ParamStoreKeyVotingParams):
|
||||
*ptr.(*v1.VotingParams) = ms.vp
|
||||
case string(v1.ParamStoreKeyTallyParams):
|
||||
*ptr.(*v1.TallyParams) = ms.tp
|
||||
}
|
||||
}
|
||||
|
||||
func TestMigrateStore(t *testing.T) {
|
||||
cdc := moduletestutil.MakeTestEncodingConfig(gov.AppModuleBasic{}, bank.AppModuleBasic{}).Codec
|
||||
govKey := storetypes.NewKVStoreKey("gov")
|
||||
ctx := testutil.DefaultContext(govKey, storetypes.NewTransientStoreKey("transient_test"))
|
||||
store := ctx.KVStore(govKey)
|
||||
|
||||
legacySubspace := newMockSubspace(v1.DefaultParams())
|
||||
|
||||
propTime := time.Unix(1e9, 0)
|
||||
|
||||
// Create 2 proposals
|
||||
prop1Content, err := v1.NewLegacyContent(v1beta1.NewTextProposal("Test", "description"), authtypes.NewModuleAddress("gov").String())
|
||||
require.NoError(t, err)
|
||||
proposal1, err := v1.NewProposal([]sdk.Msg{prop1Content}, 1, propTime, propTime, "some metadata for the legacy content", "Test", "description", sdk.AccAddress("cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r"), false)
|
||||
require.NoError(t, err)
|
||||
prop1Bz, err := cdc.Marshal(&proposal1)
|
||||
require.NoError(t, err)
|
||||
store.Set(v1gov.ProposalKey(proposal1.Id), prop1Bz)
|
||||
|
||||
proposal2, err := v1.NewProposal(getTestProposal(), 2, propTime, propTime, "some metadata for the legacy content", "Test", "description", sdk.AccAddress("cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r"), false)
|
||||
proposal2.Status = v1.StatusVotingPeriod
|
||||
require.NoError(t, err)
|
||||
prop2Bz, err := cdc.Marshal(&proposal2)
|
||||
require.NoError(t, err)
|
||||
store.Set(v1gov.ProposalKey(proposal2.Id), prop2Bz)
|
||||
|
||||
// Run migrations.
|
||||
storeService := runtime.NewKVStoreService(govKey)
|
||||
err = v4.MigrateStore(ctx, storeService, legacySubspace, cdc)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check params
|
||||
var params v1.Params
|
||||
bz := store.Get(v4.ParamsKey)
|
||||
require.NoError(t, cdc.Unmarshal(bz, ¶ms))
|
||||
require.NotNil(t, params)
|
||||
require.Equal(t, legacySubspace.dp.MinDeposit, params.MinDeposit)
|
||||
require.Equal(t, legacySubspace.dp.MaxDepositPeriod, params.MaxDepositPeriod)
|
||||
require.Equal(t, legacySubspace.vp.VotingPeriod, params.VotingPeriod)
|
||||
require.Equal(t, legacySubspace.tp.Quorum, params.Quorum)
|
||||
require.Equal(t, legacySubspace.tp.Threshold, params.Threshold)
|
||||
require.Equal(t, legacySubspace.tp.VetoThreshold, params.VetoThreshold)
|
||||
require.Equal(t, math.LegacyZeroDec().String(), params.MinInitialDepositRatio)
|
||||
|
||||
// Check proposals' status
|
||||
var migratedProp1 v1.Proposal
|
||||
bz = store.Get(v1gov.ProposalKey(proposal1.Id))
|
||||
require.NoError(t, cdc.Unmarshal(bz, &migratedProp1))
|
||||
require.Equal(t, v1.StatusDepositPeriod, migratedProp1.Status)
|
||||
|
||||
var migratedProp2 v1.Proposal
|
||||
bz = store.Get(v1gov.ProposalKey(proposal2.Id))
|
||||
require.NoError(t, cdc.Unmarshal(bz, &migratedProp2))
|
||||
require.Equal(t, v1.StatusVotingPeriod, migratedProp2.Status)
|
||||
|
||||
// Check if proposal 2 is in the new store but not proposal 1
|
||||
require.Nil(t, store.Get(v4.VotingPeriodProposalKey(proposal1.Id)))
|
||||
require.Equal(t, []byte{0x1}, store.Get(v4.VotingPeriodProposalKey(proposal2.Id)))
|
||||
}
|
||||
|
||||
func getTestProposal() []sdk.Msg {
|
||||
legacyProposalMsg, err := v1.NewLegacyContent(v1beta1.NewTextProposal("Title", "description"), authtypes.NewModuleAddress(types.ModuleName).String())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return []sdk.Msg{
|
||||
banktypes.NewMsgSend(govAcct, addr, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000)))),
|
||||
legacyProposalMsg,
|
||||
}
|
||||
}
|
||||
@ -5,17 +5,19 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
v4 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v4"
|
||||
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
)
|
||||
|
||||
// ParamsKey is the key of x/gov params
|
||||
var ParamsKey = []byte{0x30}
|
||||
|
||||
// MigrateStore performs in-place store migrations from v4 (v0.47) to v5 (v0.50). The
|
||||
// migration includes:
|
||||
//
|
||||
// Addition of the new proposal expedited parameters that are set to 0 by default.
|
||||
func MigrateStore(ctx sdk.Context, storeService corestoretypes.KVStoreService, cdc codec.BinaryCodec) error {
|
||||
store := storeService.OpenKVStore(ctx)
|
||||
paramsBz, err := store.Get(v4.ParamsKey)
|
||||
paramsBz, err := store.Get(ParamsKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -38,5 +40,5 @@ func MigrateStore(ctx sdk.Context, storeService corestoretypes.KVStoreService, c
|
||||
return err
|
||||
}
|
||||
|
||||
return store.Set(v4.ParamsKey, bz)
|
||||
return store.Set(ParamsKey, bz)
|
||||
}
|
||||
|
||||
@ -13,7 +13,6 @@ import (
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
v4 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v4"
|
||||
v5 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v5"
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
)
|
||||
@ -25,7 +24,7 @@ func TestMigrateStore(t *testing.T) {
|
||||
store := ctx.KVStore(govKey)
|
||||
|
||||
var params v1.Params
|
||||
bz := store.Get(v4.ParamsKey)
|
||||
bz := store.Get(v5.ParamsKey)
|
||||
require.NoError(t, cdc.Unmarshal(bz, ¶ms))
|
||||
require.NotNil(t, params)
|
||||
require.Equal(t, "", params.ExpeditedThreshold)
|
||||
@ -37,7 +36,7 @@ func TestMigrateStore(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check params
|
||||
bz = store.Get(v4.ParamsKey)
|
||||
bz = store.Get(v5.ParamsKey)
|
||||
require.NoError(t, cdc.Unmarshal(bz, ¶ms))
|
||||
require.NotNil(t, params)
|
||||
require.Equal(t, v1.DefaultParams().ExpeditedMinDeposit, params.ExpeditedMinDeposit)
|
||||
|
||||
@ -134,22 +134,18 @@ type AppModule struct {
|
||||
keeper *keeper.Keeper
|
||||
accountKeeper govtypes.AccountKeeper
|
||||
bankKeeper govtypes.BankKeeper
|
||||
|
||||
// legacySubspace is used solely for migration of x/params managed parameters
|
||||
legacySubspace govtypes.ParamSubspace
|
||||
}
|
||||
|
||||
// NewAppModule creates a new AppModule object
|
||||
func NewAppModule(
|
||||
cdc codec.Codec, keeper *keeper.Keeper,
|
||||
ak govtypes.AccountKeeper, bk govtypes.BankKeeper, ss govtypes.ParamSubspace,
|
||||
ak govtypes.AccountKeeper, bk govtypes.BankKeeper,
|
||||
) AppModule {
|
||||
return AppModule{
|
||||
AppModuleBasic: AppModuleBasic{cdc: cdc, ac: ak.AddressCodec()},
|
||||
keeper: keeper,
|
||||
accountKeeper: ak,
|
||||
bankKeeper: bk,
|
||||
legacySubspace: ss,
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,6 +162,10 @@ func init() {
|
||||
appmodule.Invoke(InvokeAddRoutes, InvokeSetHooks))
|
||||
}
|
||||
|
||||
func ProvideKeyTable() paramtypes.KeyTable {
|
||||
return v1.ParamKeyTable() //nolint:staticcheck // we still need this for upgrades
|
||||
}
|
||||
|
||||
type ModuleInputs struct {
|
||||
depinject.In
|
||||
|
||||
@ -179,9 +179,6 @@ type ModuleInputs struct {
|
||||
BankKeeper govtypes.BankKeeper
|
||||
StakingKeeper govtypes.StakingKeeper
|
||||
DistributionKeeper govtypes.DistributionKeeper
|
||||
|
||||
// LegacySubspace is used solely for migration of x/params managed parameters
|
||||
LegacySubspace govtypes.ParamSubspace `optional:"true"`
|
||||
}
|
||||
|
||||
type ModuleOutputs struct {
|
||||
@ -215,16 +212,12 @@ func ProvideModule(in ModuleInputs) ModuleOutputs {
|
||||
defaultConfig,
|
||||
authority.String(),
|
||||
)
|
||||
m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.BankKeeper, in.LegacySubspace)
|
||||
m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.BankKeeper)
|
||||
hr := v1beta1.HandlerRoute{Handler: v1beta1.ProposalHandler, RouteKey: govtypes.RouterKey}
|
||||
|
||||
return ModuleOutputs{Module: m, Keeper: k, HandlerRoute: hr}
|
||||
}
|
||||
|
||||
func ProvideKeyTable() paramtypes.KeyTable {
|
||||
return v1.ParamKeyTable() //nolint:staticcheck // we still need this for upgrades
|
||||
}
|
||||
|
||||
func InvokeAddRoutes(keeper *keeper.Keeper, routes []v1beta1.HandlerRoute) {
|
||||
if keeper == nil || routes == nil {
|
||||
return
|
||||
@ -282,7 +275,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {
|
||||
v1beta1.RegisterQueryServer(cfg.QueryServer(), legacyQueryServer)
|
||||
v1.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServer(am.keeper))
|
||||
|
||||
m := keeper.NewMigrator(am.keeper, am.legacySubspace)
|
||||
m := keeper.NewMigrator(am.keeper)
|
||||
if err := cfg.RegisterMigration(govtypes.ModuleName, 1, m.Migrate1to2); err != nil {
|
||||
panic(fmt.Sprintf("failed to migrate x/gov from version 1 to 2: %v", err))
|
||||
}
|
||||
|
||||
@ -10,12 +10,6 @@ import (
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
// ParamSubspace defines the expected Subspace interface for parameters (noalias)
|
||||
type ParamSubspace interface {
|
||||
Get(ctx sdk.Context, key []byte, ptr interface{})
|
||||
Set(ctx sdk.Context, key []byte, param interface{})
|
||||
}
|
||||
|
||||
// StakingKeeper expected staking keeper (Validator and Delegator sets) (noalias)
|
||||
type StakingKeeper interface {
|
||||
ValidatorAddressCodec() addresscodec.Codec
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
package exported
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
)
|
||||
|
||||
type (
|
||||
ParamSet = paramtypes.ParamSet
|
||||
|
||||
// Subspace defines an interface that implements the legacy x/params Subspace
|
||||
// type.
|
||||
//
|
||||
// NOTE: This is used solely for migration of x/params managed parameters.
|
||||
Subspace interface {
|
||||
GetParamSet(ctx sdk.Context, ps ParamSet)
|
||||
}
|
||||
)
|
||||
@ -2,21 +2,17 @@ package keeper
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/mint/exported"
|
||||
v2 "github.com/cosmos/cosmos-sdk/x/mint/migrations/v2"
|
||||
)
|
||||
|
||||
// Migrator is a struct for handling in-place state migrations.
|
||||
type Migrator struct {
|
||||
keeper Keeper
|
||||
legacySubspace exported.Subspace
|
||||
keeper Keeper
|
||||
}
|
||||
|
||||
// NewMigrator returns Migrator instance for the state migration.
|
||||
func NewMigrator(k Keeper, ss exported.Subspace) Migrator {
|
||||
func NewMigrator(k Keeper) Migrator {
|
||||
return Migrator{
|
||||
keeper: k,
|
||||
legacySubspace: ss,
|
||||
keeper: k,
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,5 +21,5 @@ func NewMigrator(k Keeper, ss exported.Subspace) Migrator {
|
||||
// and managed by the x/params modules and stores them directly into the x/mint
|
||||
// module state.
|
||||
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
|
||||
return v2.Migrate(ctx, m.keeper.storeService.OpenKVStore(ctx), m.legacySubspace, m.keeper.cdc)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
storetypes "cosmossdk.io/core/store"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/mint/exported"
|
||||
"github.com/cosmos/cosmos-sdk/x/mint/types"
|
||||
)
|
||||
|
||||
const (
|
||||
ModuleName = "mint"
|
||||
)
|
||||
|
||||
var ParamsKey = []byte{0x01}
|
||||
|
||||
// Migrate migrates the x/mint module state from the consensus version 1 to
|
||||
// version 2. Specifically, it takes the parameters that are currently stored
|
||||
// and managed by the x/params modules and stores them directly into the x/mint
|
||||
// module state.
|
||||
func Migrate(
|
||||
ctx sdk.Context,
|
||||
store storetypes.KVStore,
|
||||
legacySubspace exported.Subspace,
|
||||
cdc codec.BinaryCodec,
|
||||
) error {
|
||||
var currParams types.Params
|
||||
legacySubspace.GetParamSet(ctx, &currParams)
|
||||
|
||||
if err := currParams.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bz := cdc.MustMarshal(&currParams)
|
||||
return store.Set(ParamsKey, bz)
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
package v2_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/mint"
|
||||
"github.com/cosmos/cosmos-sdk/x/mint/exported"
|
||||
v2 "github.com/cosmos/cosmos-sdk/x/mint/migrations/v2"
|
||||
"github.com/cosmos/cosmos-sdk/x/mint/types"
|
||||
)
|
||||
|
||||
type mockSubspace struct {
|
||||
ps types.Params
|
||||
}
|
||||
|
||||
func newMockSubspace(ps types.Params) mockSubspace {
|
||||
return mockSubspace{ps: ps}
|
||||
}
|
||||
|
||||
func (ms mockSubspace) GetParamSet(ctx sdk.Context, ps exported.ParamSet) {
|
||||
*ps.(*types.Params) = ms.ps
|
||||
}
|
||||
|
||||
func TestMigrate(t *testing.T) {
|
||||
encCfg := moduletestutil.MakeTestEncodingConfig(mint.AppModuleBasic{})
|
||||
cdc := encCfg.Codec
|
||||
|
||||
storeKey := storetypes.NewKVStoreKey(v2.ModuleName)
|
||||
tKey := storetypes.NewTransientStoreKey("transient_test")
|
||||
ctx := testutil.DefaultContext(storeKey, tKey)
|
||||
kvStoreService := runtime.NewKVStoreService(storeKey)
|
||||
store := kvStoreService.OpenKVStore(ctx)
|
||||
|
||||
legacySubspace := newMockSubspace(types.DefaultParams())
|
||||
require.NoError(t, v2.Migrate(ctx, store, legacySubspace, cdc))
|
||||
|
||||
var res types.Params
|
||||
bz, err := store.Get(v2.ParamsKey)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, cdc.Unmarshal(bz, &res))
|
||||
require.Equal(t, legacySubspace.ps, res)
|
||||
}
|
||||
@ -19,7 +19,6 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/mint/exported"
|
||||
"github.com/cosmos/cosmos-sdk/x/mint/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/mint/simulation"
|
||||
"github.com/cosmos/cosmos-sdk/x/mint/types"
|
||||
@ -88,9 +87,6 @@ type AppModule struct {
|
||||
keeper keeper.Keeper
|
||||
authKeeper types.AccountKeeper
|
||||
|
||||
// legacySubspace is used solely for migration of x/params managed parameters
|
||||
legacySubspace exported.Subspace
|
||||
|
||||
// inflationCalculator is used to calculate the inflation rate during BeginBlock.
|
||||
// If inflationCalculator is nil, the default inflation calculation logic is used.
|
||||
inflationCalculator types.InflationCalculationFn
|
||||
@ -103,7 +99,6 @@ func NewAppModule(
|
||||
keeper keeper.Keeper,
|
||||
ak types.AccountKeeper,
|
||||
ic types.InflationCalculationFn,
|
||||
ss exported.Subspace,
|
||||
) AppModule {
|
||||
if ic == nil {
|
||||
ic = types.DefaultInflationCalculationFn
|
||||
@ -114,7 +109,6 @@ func NewAppModule(
|
||||
keeper: keeper,
|
||||
authKeeper: ak,
|
||||
inflationCalculator: ic,
|
||||
legacySubspace: ss,
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,7 +124,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {
|
||||
types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
|
||||
types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServerImpl(am.keeper))
|
||||
|
||||
m := keeper.NewMigrator(am.keeper, am.legacySubspace)
|
||||
m := keeper.NewMigrator(am.keeper)
|
||||
|
||||
if err := cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2); err != nil {
|
||||
panic(fmt.Sprintf("failed to migrate x/%s from version 1 to 2: %v", types.ModuleName, err))
|
||||
@ -202,9 +196,6 @@ type ModuleInputs struct {
|
||||
Cdc codec.Codec
|
||||
InflationCalculationFn types.InflationCalculationFn `optional:"true"`
|
||||
|
||||
// LegacySubspace is used solely for migration of x/params managed parameters
|
||||
LegacySubspace exported.Subspace `optional:"true"`
|
||||
|
||||
AccountKeeper types.AccountKeeper
|
||||
BankKeeper types.BankKeeper
|
||||
StakingKeeper types.StakingKeeper
|
||||
@ -245,7 +236,7 @@ func ProvideModule(in ModuleInputs) ModuleOutputs {
|
||||
)
|
||||
|
||||
// when no inflation calculation function is provided it will use the default types.DefaultInflationCalculationFn
|
||||
m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.InflationCalculationFn, in.LegacySubspace)
|
||||
m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.InflationCalculationFn)
|
||||
|
||||
return ModuleOutputs{MintKeeper: k, Module: m}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user