CLI `migrate` command follow-up: decode & re-encode (#7464)

* Migrate staking module

* Add gov legacy

* Add comments

* Add x/distrib

* x/crisis

* x/mint

* Fix test

* migrate x/genutil

* Fix lint

* Fix staking constants

* Fix test

* Update x/genutil/legacy/v040/migrate.go

Co-authored-by: Marie Gauthier <marie.gauthier63@gmail.com>

* Add migrate script instead of change BondStatus constants

* Fix test

* Fix another test

Co-authored-by: Marie Gauthier <marie.gauthier63@gmail.com>
Co-authored-by: Cory <cjlevinson@gmail.com>
This commit is contained in:
Amaury Martiny 2020-10-09 21:09:43 +02:00 committed by GitHub
parent f8e3fcb524
commit c14a3a7cb2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 786 additions and 41 deletions

View File

@ -47,6 +47,7 @@ func convertBaseVestingAccount(old *v039auth.BaseVestingAccount) *v040vesting.Ba
// it to v0.40 x/auth genesis state. The migration includes: // it to v0.40 x/auth genesis state. The migration includes:
// //
// - Removing coins from account encoding. // - Removing coins from account encoding.
// - Re-encode in v0.40 GenesisState.
func Migrate(authGenState v039auth.GenesisState) *v040auth.GenesisState { func Migrate(authGenState v039auth.GenesisState) *v040auth.GenesisState {
// Convert v0.39 accounts to v0.40 ones. // Convert v0.39 accounts to v0.40 ones.
var v040Accounts = make([]v040auth.GenesisAccount, len(authGenState.Accounts)) var v040Accounts = make([]v040auth.GenesisAccount, len(authGenState.Accounts))

View File

@ -12,6 +12,7 @@ import (
// //
// - Moving balances from x/auth to x/bank genesis state. // - Moving balances from x/auth to x/bank genesis state.
// - Moving supply from x/supply to x/bank genesis state. // - Moving supply from x/supply to x/bank genesis state.
// - Re-encode in v0.40 GenesisState.
func Migrate( func Migrate(
bankGenState v038bank.GenesisState, bankGenState v038bank.GenesisState,
authGenState v039auth.GenesisState, authGenState v039auth.GenesisState,

View File

@ -0,0 +1,13 @@
package v039
import sdk "github.com/cosmos/cosmos-sdk/types"
const (
ModuleName = "crisis"
)
type (
GenesisState struct {
ConstantFee sdk.Coin `json:"constant_fee" yaml:"constant_fee"`
}
)

View File

@ -0,0 +1,16 @@
package v040
import (
v039crisis "github.com/cosmos/cosmos-sdk/x/crisis/legacy/v039"
v040crisis "github.com/cosmos/cosmos-sdk/x/crisis/types"
)
// Migrate accepts exported v0.39 x/crisis genesis state and
// migrates it to v0.40 x/crisis genesis state. The migration includes:
//
// - Re-encode in v0.40 GenesisState.
func Migrate(crisisGenState v039crisis.GenesisState) *v040crisis.GenesisState {
return &v040crisis.GenesisState{
ConstantFee: crisisGenState.ConstantFee,
}
}

View File

@ -0,0 +1,5 @@
package v040
const (
ModuleName = "crisis"
)

View File

@ -0,0 +1,108 @@
package v040
import (
v038distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v038"
v040distribution "github.com/cosmos/cosmos-sdk/x/distribution/types"
)
// Migrate accepts exported x/distribution genesis state from v0.38 and migrates it
// to v0.40 x/distribution genesis state. The migration includes:
//
// - Convert addresses from bytes to bech32 strings.
// - Re-encode in v0.40 GenesisState.
func Migrate(oldDistributionState v038distribution.GenesisState) *v040distribution.GenesisState {
newDelegatorWithdrawInfos := make([]v040distribution.DelegatorWithdrawInfo, len(oldDistributionState.DelegatorWithdrawInfos))
for i, oldDelegatorWithdrawInfo := range oldDistributionState.DelegatorWithdrawInfos {
newDelegatorWithdrawInfos[i] = v040distribution.DelegatorWithdrawInfo{
DelegatorAddress: oldDelegatorWithdrawInfo.DelegatorAddress.String(),
WithdrawAddress: oldDelegatorWithdrawInfo.WithdrawAddress.String(),
}
}
newValidatorOutstandingRewards := make([]v040distribution.ValidatorOutstandingRewardsRecord, len(oldDistributionState.OutstandingRewards))
for i, oldValidatorOutstandingReward := range oldDistributionState.OutstandingRewards {
newValidatorOutstandingRewards[i] = v040distribution.ValidatorOutstandingRewardsRecord{
ValidatorAddress: oldValidatorOutstandingReward.ValidatorAddress.String(),
OutstandingRewards: oldValidatorOutstandingReward.OutstandingRewards,
}
}
newValidatorAccumulatedCommissions := make([]v040distribution.ValidatorAccumulatedCommissionRecord, len(oldDistributionState.ValidatorAccumulatedCommissions))
for i, oldValidatorAccumulatedCommission := range oldDistributionState.ValidatorAccumulatedCommissions {
newValidatorAccumulatedCommissions[i] = v040distribution.ValidatorAccumulatedCommissionRecord{
ValidatorAddress: oldValidatorAccumulatedCommission.ValidatorAddress.String(),
Accumulated: v040distribution.ValidatorAccumulatedCommission{
Commission: oldValidatorAccumulatedCommission.Accumulated,
},
}
}
newValidatorHistoricalRewards := make([]v040distribution.ValidatorHistoricalRewardsRecord, len(oldDistributionState.ValidatorHistoricalRewards))
for i, oldValidatorHistoricalReward := range oldDistributionState.ValidatorHistoricalRewards {
newValidatorHistoricalRewards[i] = v040distribution.ValidatorHistoricalRewardsRecord{
ValidatorAddress: oldValidatorHistoricalReward.ValidatorAddress.String(),
Period: oldValidatorHistoricalReward.Period,
Rewards: v040distribution.ValidatorHistoricalRewards{
CumulativeRewardRatio: oldValidatorHistoricalReward.Rewards.CumulativeRewardRatio,
ReferenceCount: uint32(oldValidatorHistoricalReward.Rewards.ReferenceCount),
},
}
}
newValidatorCurrentRewards := make([]v040distribution.ValidatorCurrentRewardsRecord, len(oldDistributionState.ValidatorCurrentRewards))
for i, oldValidatorCurrentReward := range oldDistributionState.ValidatorCurrentRewards {
newValidatorCurrentRewards[i] = v040distribution.ValidatorCurrentRewardsRecord{
ValidatorAddress: oldValidatorCurrentReward.ValidatorAddress.String(),
Rewards: v040distribution.ValidatorCurrentRewards{
Rewards: oldValidatorCurrentReward.Rewards.Rewards,
Period: oldValidatorCurrentReward.Rewards.Period,
},
}
}
newDelegatorStartingInfos := make([]v040distribution.DelegatorStartingInfoRecord, len(oldDistributionState.DelegatorStartingInfos))
for i, oldDelegatorStartingInfo := range oldDistributionState.DelegatorStartingInfos {
newDelegatorStartingInfos[i] = v040distribution.DelegatorStartingInfoRecord{
DelegatorAddress: oldDelegatorStartingInfo.DelegatorAddress.String(),
ValidatorAddress: oldDelegatorStartingInfo.ValidatorAddress.String(),
StartingInfo: v040distribution.DelegatorStartingInfo{
PreviousPeriod: oldDelegatorStartingInfo.StartingInfo.PreviousPeriod,
Stake: oldDelegatorStartingInfo.StartingInfo.Stake,
Height: oldDelegatorStartingInfo.StartingInfo.Height,
},
}
}
newValidatorSlashEvents := make([]v040distribution.ValidatorSlashEventRecord, len(oldDistributionState.ValidatorSlashEvents))
for i, oldValidatorSlashEvent := range oldDistributionState.ValidatorSlashEvents {
newValidatorSlashEvents[i] = v040distribution.ValidatorSlashEventRecord{
ValidatorAddress: oldValidatorSlashEvent.ValidatorAddress.String(),
Height: oldValidatorSlashEvent.Height,
Period: oldValidatorSlashEvent.Period,
ValidatorSlashEvent: v040distribution.ValidatorSlashEvent{
ValidatorPeriod: oldValidatorSlashEvent.Event.ValidatorPeriod,
Fraction: oldValidatorSlashEvent.Event.Fraction,
},
}
}
return &v040distribution.GenesisState{
Params: v040distribution.Params{
CommunityTax: oldDistributionState.Params.CommunityTax,
BaseProposerReward: oldDistributionState.Params.BaseProposerReward,
BonusProposerReward: oldDistributionState.Params.BonusProposerReward,
WithdrawAddrEnabled: oldDistributionState.Params.WithdrawAddrEnabled,
},
FeePool: v040distribution.FeePool{
CommunityPool: oldDistributionState.FeePool.CommunityPool,
},
DelegatorWithdrawInfos: newDelegatorWithdrawInfos,
PreviousProposer: oldDistributionState.PreviousProposer.String(),
OutstandingRewards: newValidatorOutstandingRewards,
ValidatorAccumulatedCommissions: newValidatorAccumulatedCommissions,
ValidatorHistoricalRewards: newValidatorHistoricalRewards,
ValidatorCurrentRewards: newValidatorCurrentRewards,
DelegatorStartingInfos: newDelegatorStartingInfos,
ValidatorSlashEvents: newValidatorSlashEvents,
}
}

View File

@ -0,0 +1,6 @@
package v040
// Default parameter values
const (
ModuleName = "distribution"
)

View File

@ -1,46 +1,48 @@
package v040 package v040
import ( import (
"github.com/cosmos/cosmos-sdk/client" "fmt"
codectypes "github.com/cosmos/cosmos-sdk/codec/types" codectypes "github.com/cosmos/cosmos-sdk/codec/types"
v038evidence "github.com/cosmos/cosmos-sdk/x/evidence/legacy/v038" v038evidence "github.com/cosmos/cosmos-sdk/x/evidence/legacy/v038"
v040evidence "github.com/cosmos/cosmos-sdk/x/evidence/types" v040evidence "github.com/cosmos/cosmos-sdk/x/evidence/types"
) )
func migrateEvidence(oldEvidence v038evidence.Evidence) *codectypes.Any {
switch oldEvidence := oldEvidence.(type) {
case v038evidence.Equivocation:
{
newEquivocation := &v040evidence.Equivocation{
Height: oldEvidence.Height,
Time: oldEvidence.Time,
Power: oldEvidence.Power,
ConsensusAddress: oldEvidence.ConsensusAddress.String(),
}
any, err := codectypes.NewAnyWithValue(newEquivocation)
if err != nil {
panic(err)
}
return any
}
default:
panic(fmt.Errorf("'%T' is not a valid evidence type", oldEvidence))
}
}
// Migrate accepts exported v0.38 x/evidence genesis state and migrates it to // Migrate accepts exported v0.38 x/evidence genesis state and migrates it to
// v0.40 x/evidence genesis state. The migration includes: // v0.40 x/evidence genesis state. The migration includes:
// //
// - Removing the `Params` field. // - Removing the `Params` field.
// - Converting Equivocations into Anys. // - Converting Equivocations into Anys.
func Migrate(evidenceState v038evidence.GenesisState, _ client.Context) *v040evidence.GenesisState { // - Re-encode in v0.40 GenesisState.
var newEquivocations = make([]v040evidence.Equivocation, len(evidenceState.Evidence)) func Migrate(evidenceState v038evidence.GenesisState) *v040evidence.GenesisState {
for i, evidence := range evidenceState.Evidence { var newEvidences = make([]*codectypes.Any, len(evidenceState.Evidence))
equivocation, ok := evidence.(v038evidence.Equivocation) for i, oldEvidence := range evidenceState.Evidence {
if !ok { newEvidences[i] = migrateEvidence(oldEvidence)
// There's only equivocation in 0.38.
continue
}
newEquivocations[i] = v040evidence.Equivocation{
Height: equivocation.Height,
Time: equivocation.Time,
Power: equivocation.Power,
ConsensusAddress: equivocation.ConsensusAddress.String(),
}
}
// Then convert the equivocations into Any.
newEvidence := make([]*codectypes.Any, len(newEquivocations))
for i := range newEquivocations {
any, err := codectypes.NewAnyWithValue(&newEquivocations[i])
if err != nil {
panic(err)
}
newEvidence[i] = any
} }
return &v040evidence.GenesisState{ return &v040evidence.GenesisState{
Evidence: newEvidence, Evidence: newEvidences,
} }
} }

View File

@ -31,7 +31,7 @@ func TestMigrate(t *testing.T) {
}}, }},
} }
migrated := v040evidence.Migrate(evidenceGenState, clientCtx) migrated := v040evidence.Migrate(evidenceGenState)
expected := `{"evidence":[{"@type":"/cosmos.evidence.v1beta1.Equivocation","height":"20","time":"0001-01-01T00:00:00Z","power":"100","consensus_address":"cosmosvalcons1xxkueklal9vejv9unqu80w9vptyepfa99x2a3w"}]}` expected := `{"evidence":[{"@type":"/cosmos.evidence.v1beta1.Equivocation","height":"20","time":"0001-01-01T00:00:00Z","power":"100","consensus_address":"cosmosvalcons1xxkueklal9vejv9unqu80w9vptyepfa99x2a3w"}]}`
bz, err := clientCtx.JSONMarshaler.MarshalJSON(migrated) bz, err := clientCtx.JSONMarshaler.MarshalJSON(migrated)

View File

@ -90,10 +90,10 @@ func Migrate(
// get staking module accounts coins // get staking module accounts coins
for _, validator := range vals { for _, validator := range vals {
switch validator.Status { switch validator.Status {
case sdk.Bonded: case v034staking.Bonded:
bondedAmt = bondedAmt.Add(validator.Tokens) bondedAmt = bondedAmt.Add(validator.Tokens)
case sdk.Unbonding, sdk.Unbonded: case v034staking.Unbonding, v034staking.Unbonded:
notBondedAmt = notBondedAmt.Add(validator.Tokens) notBondedAmt = notBondedAmt.Add(validator.Tokens)
default: default:

View File

@ -0,0 +1,12 @@
package v039
import "encoding/json"
const (
ModuleName = "genutil"
)
// GenesisState defines the raw genesis transaction in JSON
type GenesisState struct {
GenTxs []json.RawMessage `json:"gentxs" yaml:"gentxs"`
}

View File

@ -9,13 +9,30 @@ import (
v036supply "github.com/cosmos/cosmos-sdk/x/bank/legacy/v036" v036supply "github.com/cosmos/cosmos-sdk/x/bank/legacy/v036"
v038bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v038" v038bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v038"
v040bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v040" v040bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v040"
v039crisis "github.com/cosmos/cosmos-sdk/x/crisis/legacy/v039"
v040crisis "github.com/cosmos/cosmos-sdk/x/crisis/legacy/v040"
v038distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v038"
v040distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v040"
v038evidence "github.com/cosmos/cosmos-sdk/x/evidence/legacy/v038" v038evidence "github.com/cosmos/cosmos-sdk/x/evidence/legacy/v038"
v040evidence "github.com/cosmos/cosmos-sdk/x/evidence/legacy/v040" v040evidence "github.com/cosmos/cosmos-sdk/x/evidence/legacy/v040"
v039genutil "github.com/cosmos/cosmos-sdk/x/genutil/legacy/v039"
"github.com/cosmos/cosmos-sdk/x/genutil/types" "github.com/cosmos/cosmos-sdk/x/genutil/types"
v036gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v036"
v040gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v040"
v039mint "github.com/cosmos/cosmos-sdk/x/mint/legacy/v039"
v040mint "github.com/cosmos/cosmos-sdk/x/mint/legacy/v040"
v039slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v039" v039slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v039"
v040slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v040" v040slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v040"
v038staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v038"
v040staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v040"
) )
func migrateGenutil(oldGenState v039genutil.GenesisState) *types.GenesisState {
return &types.GenesisState{
GenTxs: oldGenState.GenTxs,
}
}
// Migrate migrates exported state from v0.39 to a v0.40 genesis state. // Migrate migrates exported state from v0.39 to a v0.40 genesis state.
func Migrate(appState types.AppMap, clientCtx client.Context) types.AppMap { func Migrate(appState types.AppMap, clientCtx client.Context) types.AppMap {
v039Codec := codec.NewLegacyAmino() v039Codec := codec.NewLegacyAmino()
@ -62,6 +79,34 @@ func Migrate(appState types.AppMap, clientCtx client.Context) types.AppMap {
appState[v040auth.ModuleName] = v040Codec.MustMarshalJSON(v040auth.Migrate(authGenState)) appState[v040auth.ModuleName] = v040Codec.MustMarshalJSON(v040auth.Migrate(authGenState))
} }
// Migrate x/crisis.
if appState[v039crisis.ModuleName] != nil {
// unmarshal relative source genesis application state
var crisisGenState v039crisis.GenesisState
v039Codec.MustUnmarshalJSON(appState[v039crisis.ModuleName], &crisisGenState)
// delete deprecated x/crisis genesis state
delete(appState, v039crisis.ModuleName)
// Migrate relative source genesis application state and marshal it into
// the respective key.
appState[v040crisis.ModuleName] = v040Codec.MustMarshalJSON(v040crisis.Migrate(crisisGenState))
}
// Migrate x/distribution.
if appState[v038distribution.ModuleName] != nil {
// unmarshal relative source genesis application state
var distributionGenState v038distribution.GenesisState
v039Codec.MustUnmarshalJSON(appState[v038distribution.ModuleName], &distributionGenState)
// delete deprecated x/distribution genesis state
delete(appState, v038distribution.ModuleName)
// Migrate relative source genesis application state and marshal it into
// the respective key.
appState[v040distribution.ModuleName] = v040Codec.MustMarshalJSON(v040distribution.Migrate(distributionGenState))
}
// Migrate x/evidence. // Migrate x/evidence.
if appState[v038evidence.ModuleName] != nil { if appState[v038evidence.ModuleName] != nil {
// unmarshal relative source genesis application state // unmarshal relative source genesis application state
@ -73,7 +118,35 @@ func Migrate(appState types.AppMap, clientCtx client.Context) types.AppMap {
// Migrate relative source genesis application state and marshal it into // Migrate relative source genesis application state and marshal it into
// the respective key. // the respective key.
appState[v040evidence.ModuleName] = v040Codec.MustMarshalJSON(v040evidence.Migrate(evidenceGenState, clientCtx)) appState[v040evidence.ModuleName] = v040Codec.MustMarshalJSON(v040evidence.Migrate(evidenceGenState))
}
// Migrate x/gov.
if appState[v036gov.ModuleName] != nil {
// unmarshal relative source genesis application state
var govGenState v036gov.GenesisState
v039Codec.MustUnmarshalJSON(appState[v036gov.ModuleName], &govGenState)
// delete deprecated x/gov genesis state
delete(appState, v036gov.ModuleName)
// Migrate relative source genesis application state and marshal it into
// the respective key.
appState[v040gov.ModuleName] = v040Codec.MustMarshalJSON(v040gov.Migrate(govGenState))
}
// Migrate x/mint.
if appState[v039mint.ModuleName] != nil {
// unmarshal relative source genesis application state
var mintGenState v039mint.GenesisState
v039Codec.MustUnmarshalJSON(appState[v039mint.ModuleName], &mintGenState)
// delete deprecated x/mint genesis state
delete(appState, v039mint.ModuleName)
// Migrate relative source genesis application state and marshal it into
// the respective key.
appState[v040mint.ModuleName] = v040Codec.MustMarshalJSON(v040mint.Migrate(mintGenState))
} }
// Migrate x/slashing. // Migrate x/slashing.
@ -82,7 +155,7 @@ func Migrate(appState types.AppMap, clientCtx client.Context) types.AppMap {
var slashingGenState v039slashing.GenesisState var slashingGenState v039slashing.GenesisState
v039Codec.MustUnmarshalJSON(appState[v039slashing.ModuleName], &slashingGenState) v039Codec.MustUnmarshalJSON(appState[v039slashing.ModuleName], &slashingGenState)
// delete deprecated x/evidence genesis state // delete deprecated x/slashing genesis state
delete(appState, v039slashing.ModuleName) delete(appState, v039slashing.ModuleName)
// Migrate relative source genesis application state and marshal it into // Migrate relative source genesis application state and marshal it into
@ -90,5 +163,33 @@ func Migrate(appState types.AppMap, clientCtx client.Context) types.AppMap {
appState[v040slashing.ModuleName] = v040Codec.MustMarshalJSON(v040slashing.Migrate(slashingGenState)) appState[v040slashing.ModuleName] = v040Codec.MustMarshalJSON(v040slashing.Migrate(slashingGenState))
} }
// Migrate x/staking.
if appState[v038staking.ModuleName] != nil {
// unmarshal relative source genesis application state
var stakingGenState v038staking.GenesisState
v039Codec.MustUnmarshalJSON(appState[v038staking.ModuleName], &stakingGenState)
// delete deprecated x/staking genesis state
delete(appState, v038staking.ModuleName)
// Migrate relative source genesis application state and marshal it into
// the respective key.
appState[v040staking.ModuleName] = v040Codec.MustMarshalJSON(v040staking.Migrate(stakingGenState))
}
// Migrate x/genutil
if appState[v039genutil.ModuleName] != nil {
// unmarshal relative source genesis application state
var genutilGenState v039genutil.GenesisState
v039Codec.MustUnmarshalJSON(appState[v039genutil.ModuleName], &genutilGenState)
// delete deprecated x/staking genesis state
delete(appState, v039genutil.ModuleName)
// Migrate relative source genesis application state and marshal it into
// the respective key.
appState[ModuleName] = v040Codec.MustMarshalJSON(migrateGenutil(genutilGenState))
}
return appState return appState
} }

View File

@ -0,0 +1,5 @@
package v040
const (
ModuleName = "genutil"
)

View File

@ -0,0 +1,141 @@
package v040
import (
"fmt"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
v034gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v034"
v036gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v036"
v040gov "github.com/cosmos/cosmos-sdk/x/gov/types"
)
func migrateVoteOption(oldVoteOption v034gov.VoteOption) v040gov.VoteOption {
switch oldVoteOption {
case v034gov.OptionEmpty:
return v040gov.OptionEmpty
case v034gov.OptionYes:
return v040gov.OptionYes
case v034gov.OptionAbstain:
return v040gov.OptionAbstain
case v034gov.OptionNo:
return v040gov.OptionNo
case v034gov.OptionNoWithVeto:
return v040gov.OptionNoWithVeto
default:
panic(fmt.Errorf("'%s' is not a valid vote option", oldVoteOption))
}
}
func migrateProposalStatus(oldProposalStatus v034gov.ProposalStatus) v040gov.ProposalStatus {
switch oldProposalStatus {
case v034gov.StatusNil:
return v040gov.StatusNil
case v034gov.StatusDepositPeriod:
return v040gov.StatusDepositPeriod
case v034gov.StatusVotingPeriod:
return v040gov.StatusVotingPeriod
case v034gov.StatusPassed:
return v040gov.StatusPassed
case v034gov.StatusRejected:
return v040gov.StatusRejected
case v034gov.StatusFailed:
return v040gov.StatusFailed
default:
panic(fmt.Errorf("'%s' is not a valid proposal status", oldProposalStatus))
}
}
func migrateContent(oldContent v036gov.Content) *codectypes.Any {
switch oldContent := oldContent.(type) {
case *v040gov.TextProposal:
{
// Convert the content into Any.
contentAny, err := codectypes.NewAnyWithValue(oldContent)
if err != nil {
panic(err)
}
return contentAny
}
default:
panic(fmt.Errorf("'%T' is not a valid proposal content type", oldContent))
}
}
// Migrate accepts exported v0.36 x/gov genesis state and migrates it to
// v0.40 x/gov genesis state. The migration includes:
//
// - Convert vote option & proposal status from byte to enum.
// - Migrate proposal content to Any.
// - Convert addresses from bytes to bech32 strings.
// - Re-encode in v0.40 GenesisState.
func Migrate(oldGovState v036gov.GenesisState) *v040gov.GenesisState {
newDeposits := make([]v040gov.Deposit, len(oldGovState.Deposits))
for i, oldDeposit := range oldGovState.Deposits {
newDeposits[i] = v040gov.Deposit{
ProposalId: oldDeposit.ProposalID,
Depositor: oldDeposit.Depositor.String(),
Amount: oldDeposit.Amount,
}
}
newVotes := make([]v040gov.Vote, len(oldGovState.Votes))
for i, oldVote := range oldGovState.Votes {
newVotes[i] = v040gov.Vote{
ProposalId: oldVote.ProposalID,
Voter: oldVote.Voter.String(),
Option: migrateVoteOption(oldVote.Option),
}
}
newProposals := make([]v040gov.Proposal, len(oldGovState.Proposals))
for i, oldProposal := range oldGovState.Proposals {
newProposals[i] = v040gov.Proposal{
ProposalId: oldProposal.ProposalID,
Content: migrateContent(oldProposal.Content),
Status: migrateProposalStatus(oldProposal.Status),
FinalTallyResult: v040gov.TallyResult{
Yes: oldProposal.FinalTallyResult.Yes,
Abstain: oldProposal.FinalTallyResult.Abstain,
No: oldProposal.FinalTallyResult.No,
NoWithVeto: oldProposal.FinalTallyResult.NoWithVeto,
},
SubmitTime: oldProposal.SubmitTime,
DepositEndTime: oldProposal.DepositEndTime,
TotalDeposit: oldProposal.TotalDeposit,
VotingStartTime: oldProposal.VotingStartTime,
VotingEndTime: oldProposal.VotingEndTime,
}
}
return &v040gov.GenesisState{
StartingProposalId: oldGovState.StartingProposalID,
Deposits: newDeposits,
Votes: newVotes,
Proposals: newProposals,
DepositParams: v040gov.DepositParams{
MinDeposit: oldGovState.DepositParams.MinDeposit,
MaxDepositPeriod: oldGovState.DepositParams.MaxDepositPeriod,
},
VotingParams: v040gov.VotingParams{
VotingPeriod: oldGovState.VotingParams.VotingPeriod,
},
TallyParams: v040gov.TallyParams{
Quorum: oldGovState.TallyParams.Quorum,
Threshold: oldGovState.TallyParams.Threshold,
VetoThreshold: oldGovState.TallyParams.Veto,
},
}
}

View File

@ -0,0 +1,6 @@
package v040
// Default parameter values
const (
ModuleName = "gov"
)

View File

@ -0,0 +1,31 @@
package v039
import sdk "github.com/cosmos/cosmos-sdk/types"
const (
ModuleName = "mint"
)
type (
// Minter represents the minting state.
Minter struct {
Inflation sdk.Dec `json:"inflation" yaml:"inflation"` // current annual inflation rate
AnnualProvisions sdk.Dec `json:"annual_provisions" yaml:"annual_provisions"` // current annual expected provisions
}
// mint parameters
Params struct {
MintDenom string `json:"mint_denom" yaml:"mint_denom"` // type of coin to mint
InflationRateChange sdk.Dec `json:"inflation_rate_change" yaml:"inflation_rate_change"` // maximum annual change in inflation rate
InflationMax sdk.Dec `json:"inflation_max" yaml:"inflation_max"` // maximum inflation rate
InflationMin sdk.Dec `json:"inflation_min" yaml:"inflation_min"` // minimum inflation rate
GoalBonded sdk.Dec `json:"goal_bonded" yaml:"goal_bonded"` // goal of percent bonded atoms
BlocksPerYear uint64 `json:"blocks_per_year" yaml:"blocks_per_year"` // expected blocks per year
}
// GenesisState - minter state
GenesisState struct {
Minter Minter `json:"minter" yaml:"minter"` // minter object
Params Params `json:"params" yaml:"params"` // inflation params
}
)

View File

@ -0,0 +1,27 @@
package v040
import (
v039mint "github.com/cosmos/cosmos-sdk/x/mint/legacy/v039"
v040mint "github.com/cosmos/cosmos-sdk/x/mint/types"
)
// Migrate accepts exported v0.39 x/mint genesis state and
// migrates it to v0.40 x/mint genesis state. The migration includes:
//
// - Re-encode in v0.40 GenesisState.
func Migrate(mintGenState v039mint.GenesisState) *v040mint.GenesisState {
return &v040mint.GenesisState{
Minter: v040mint.Minter{
Inflation: mintGenState.Minter.Inflation,
AnnualProvisions: mintGenState.Minter.AnnualProvisions,
},
Params: v040mint.Params{
MintDenom: mintGenState.Params.MintDenom,
InflationRateChange: mintGenState.Params.InflationRateChange,
InflationMax: mintGenState.Params.InflationMax,
InflationMin: mintGenState.Params.InflationMin,
GoalBonded: mintGenState.Params.GoalBonded,
BlocksPerYear: mintGenState.Params.BlocksPerYear,
},
}
}

View File

@ -0,0 +1,5 @@
package v040
const (
ModuleName = "mint"
)

View File

@ -11,6 +11,8 @@ import (
// to v0.40 x/slashing genesis state. The migration includes: // to v0.40 x/slashing genesis state. The migration includes:
// //
// - Chaning SigningInfos and MissedBlocks from map to array. // - Chaning SigningInfos and MissedBlocks from map to array.
// - Convert addresses from bytes to bech32 strings.
// - Re-encode in v0.40 GenesisState.
func Migrate(oldGenState v039slashing.GenesisState) *v040slashing.GenesisState { func Migrate(oldGenState v039slashing.GenesisState) *v040slashing.GenesisState {
// Note that the two following `for` loop over a map's keys, so are not // Note that the two following `for` loop over a map's keys, so are not
// deterministic. // deterministic.

View File

@ -15,7 +15,21 @@ const (
ModuleName = "staking" ModuleName = "staking"
) )
// staking constants
const (
Unbonded BondStatus = 0x00
Unbonding BondStatus = 0x01
Bonded BondStatus = 0x02
BondStatusUnbonded = "Unbonded"
BondStatusUnbonding = "Unbonding"
BondStatusBonded = "Bonded"
)
type ( type (
// BondStatus is the status of a validator
BondStatus byte
Pool struct { Pool struct {
NotBondedTokens sdk.Int `json:"not_bonded_tokens"` NotBondedTokens sdk.Int `json:"not_bonded_tokens"`
BondedTokens sdk.Int `json:"bonded_tokens"` BondedTokens sdk.Int `json:"bonded_tokens"`
@ -51,7 +65,7 @@ type (
OperatorAddress sdk.ValAddress `json:"operator_address"` // the bech32 address of the validator's operator 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 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? Jailed bool `json:"jailed"` // has the validator been jailed from bonded status?
Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded) Status BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded)
Tokens sdk.Int `json:"tokens"` // delegated tokens (incl. self-delegation) Tokens sdk.Int `json:"tokens"` // delegated tokens (incl. self-delegation)
DelegatorShares sdk.Dec `json:"delegator_shares"` // total shares issued to a validator's delegators DelegatorShares sdk.Dec `json:"delegator_shares"` // total shares issued to a validator's delegators
Description Description `json:"description"` // description terms for the validator Description Description `json:"description"` // description terms for the validator
@ -65,7 +79,7 @@ type (
OperatorAddress sdk.ValAddress `json:"operator_address"` OperatorAddress sdk.ValAddress `json:"operator_address"`
ConsPubKey crypto.PubKey `json:"consensus_pubkey"` ConsPubKey crypto.PubKey `json:"consensus_pubkey"`
Jailed bool `json:"jailed"` Jailed bool `json:"jailed"`
Status sdk.BondStatus `json:"status"` Status BondStatus `json:"status"`
Tokens sdk.Int `json:"tokens"` Tokens sdk.Int `json:"tokens"`
DelegatorShares sdk.Dec `json:"delegator_shares"` DelegatorShares sdk.Dec `json:"delegator_shares"`
Description Description `json:"description"` Description Description `json:"description"`

View File

@ -32,7 +32,7 @@ type (
OperatorAddress sdk.ValAddress `json:"operator_address" yaml:"operator_address"` OperatorAddress sdk.ValAddress `json:"operator_address" yaml:"operator_address"`
ConsPubKey crypto.PubKey `json:"consensus_pubkey" yaml:"consensus_pubkey"` ConsPubKey crypto.PubKey `json:"consensus_pubkey" yaml:"consensus_pubkey"`
Jailed bool `json:"jailed" yaml:"jailed"` Jailed bool `json:"jailed" yaml:"jailed"`
Status sdk.BondStatus `json:"status" yaml:"status"` Status v034staking.BondStatus `json:"status" yaml:"status"`
Tokens sdk.Int `json:"tokens" yaml:"tokens"` Tokens sdk.Int `json:"tokens" yaml:"tokens"`
DelegatorShares sdk.Dec `json:"delegator_shares" yaml:"delegator_shares"` DelegatorShares sdk.Dec `json:"delegator_shares" yaml:"delegator_shares"`
Description v034staking.Description `json:"description" yaml:"description"` Description v034staking.Description `json:"description" yaml:"description"`
@ -46,7 +46,7 @@ type (
OperatorAddress sdk.ValAddress `json:"operator_address" yaml:"operator_address"` OperatorAddress sdk.ValAddress `json:"operator_address" yaml:"operator_address"`
ConsPubKey string `json:"consensus_pubkey" yaml:"consensus_pubkey"` ConsPubKey string `json:"consensus_pubkey" yaml:"consensus_pubkey"`
Jailed bool `json:"jailed" yaml:"jailed"` Jailed bool `json:"jailed" yaml:"jailed"`
Status sdk.BondStatus `json:"status" yaml:"status"` Status v034staking.BondStatus `json:"status" yaml:"status"`
Tokens sdk.Int `json:"tokens" yaml:"tokens"` Tokens sdk.Int `json:"tokens" yaml:"tokens"`
DelegatorShares sdk.Dec `json:"delegator_shares" yaml:"delegator_shares"` DelegatorShares sdk.Dec `json:"delegator_shares" yaml:"delegator_shares"`
Description v034staking.Description `json:"description" yaml:"description"` Description v034staking.Description `json:"description" yaml:"description"`

View File

@ -30,7 +30,7 @@ type (
OperatorAddress sdk.ValAddress `json:"operator_address" yaml:"operator_address"` OperatorAddress sdk.ValAddress `json:"operator_address" yaml:"operator_address"`
ConsPubKey crypto.PubKey `json:"consensus_pubkey" yaml:"consensus_pubkey"` ConsPubKey crypto.PubKey `json:"consensus_pubkey" yaml:"consensus_pubkey"`
Jailed bool `json:"jailed" yaml:"jailed"` Jailed bool `json:"jailed" yaml:"jailed"`
Status sdk.BondStatus `json:"status" yaml:"status"` Status v034staking.BondStatus `json:"status" yaml:"status"`
Tokens sdk.Int `json:"tokens" yaml:"tokens"` Tokens sdk.Int `json:"tokens" yaml:"tokens"`
DelegatorShares sdk.Dec `json:"delegator_shares" yaml:"delegator_shares"` DelegatorShares sdk.Dec `json:"delegator_shares" yaml:"delegator_shares"`
Description Description `json:"description" yaml:"description"` Description Description `json:"description" yaml:"description"`
@ -44,7 +44,7 @@ type (
OperatorAddress sdk.ValAddress `json:"operator_address" yaml:"operator_address"` OperatorAddress sdk.ValAddress `json:"operator_address" yaml:"operator_address"`
ConsPubKey string `json:"consensus_pubkey" yaml:"consensus_pubkey"` ConsPubKey string `json:"consensus_pubkey" yaml:"consensus_pubkey"`
Jailed bool `json:"jailed" yaml:"jailed"` Jailed bool `json:"jailed" yaml:"jailed"`
Status sdk.BondStatus `json:"status" yaml:"status"` Status v034staking.BondStatus `json:"status" yaml:"status"`
Tokens sdk.Int `json:"tokens" yaml:"tokens"` Tokens sdk.Int `json:"tokens" yaml:"tokens"`
DelegatorShares sdk.Dec `json:"delegator_shares" yaml:"delegator_shares"` DelegatorShares sdk.Dec `json:"delegator_shares" yaml:"delegator_shares"`
Description Description `json:"description" yaml:"description"` Description Description `json:"description" yaml:"description"`
@ -56,8 +56,16 @@ type (
Validators []Validator Validators []Validator
Params struct {
UnbondingTime time.Duration `json:"unbonding_time" yaml:"unbonding_time"` // time duration of unbonding
MaxValidators uint16 `json:"max_validators" yaml:"max_validators"` // maximum number of validators (max uint16 = 65535)
MaxEntries uint16 `json:"max_entries" yaml:"max_entries"` // max entries for either unbonding delegation or redelegation (per pair/trio)
HistoricalEntries uint16 `json:"historical_entries" yaml:"historical_entries"` // number of historical entries to persist
BondDenom string `json:"bond_denom" yaml:"bond_denom"` // bondable coin denomination
}
GenesisState struct { GenesisState struct {
Params v034staking.Params `json:"params"` Params Params `json:"params"`
LastTotalPower sdk.Int `json:"last_total_power"` LastTotalPower sdk.Int `json:"last_total_power"`
LastValidatorPowers []v034staking.LastValidatorPower `json:"last_validator_powers"` LastValidatorPowers []v034staking.LastValidatorPower `json:"last_validator_powers"`
Validators Validators `json:"validators"` Validators Validators `json:"validators"`
@ -87,7 +95,13 @@ func NewGenesisState(
) GenesisState { ) GenesisState {
return GenesisState{ return GenesisState{
Params: params, Params: Params{
UnbondingTime: params.UnbondingTime,
MaxValidators: params.MaxValidators,
MaxEntries: params.MaxEntries,
BondDenom: params.BondDenom,
HistoricalEntries: 0,
},
LastTotalPower: lastTotalPower, LastTotalPower: lastTotalPower,
LastValidatorPowers: lastValPowers, LastValidatorPowers: lastValPowers,
Validators: validators, Validators: validators,

View File

@ -0,0 +1,137 @@
package v040
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
v034staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v034"
v038staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v038"
v040staking "github.com/cosmos/cosmos-sdk/x/staking/types"
)
func migrateBondStatus(oldStatus v034staking.BondStatus) sdk.BondStatus {
switch oldStatus {
case v034staking.Unbonded:
return sdk.Unbonded
case v034staking.Unbonding:
return sdk.Unbonding
case v034staking.Bonded:
return sdk.Bonded
default:
panic(fmt.Errorf("invalid bond status %d", oldStatus))
}
}
// Migrate accepts exported v0.38 x/staking genesis state and migrates it to
// v0.40 x/staking genesis state. The migration includes:
//
// - Convert addresses from bytes to bech32 strings.
// - Update BondStatus staking constants.
// - Re-encode in v0.40 GenesisState.
func Migrate(stakingState v038staking.GenesisState) *v040staking.GenesisState {
newLastValidatorPowers := make([]v040staking.LastValidatorPower, len(stakingState.LastValidatorPowers))
for i, oldLastValidatorPower := range stakingState.LastValidatorPowers {
newLastValidatorPowers[i] = v040staking.LastValidatorPower{
Address: oldLastValidatorPower.Address.String(),
Power: oldLastValidatorPower.Power,
}
}
newValidators := make([]v040staking.Validator, len(stakingState.Validators))
for i, oldValidator := range stakingState.Validators {
newValidators[i] = v040staking.Validator{
OperatorAddress: oldValidator.OperatorAddress.String(),
ConsensusPubkey: sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, oldValidator.ConsPubKey),
Jailed: oldValidator.Jailed,
Status: migrateBondStatus(oldValidator.Status),
Tokens: oldValidator.Tokens,
DelegatorShares: oldValidator.DelegatorShares,
Description: v040staking.Description{
Moniker: oldValidator.Description.Moniker,
Identity: oldValidator.Description.Identity,
Website: oldValidator.Description.Website,
SecurityContact: oldValidator.Description.SecurityContact,
Details: oldValidator.Description.Details,
},
UnbondingHeight: oldValidator.UnbondingHeight,
UnbondingTime: oldValidator.UnbondingCompletionTime,
Commission: v040staking.Commission{
CommissionRates: v040staking.CommissionRates{
Rate: oldValidator.Commission.Rate,
MaxRate: oldValidator.Commission.MaxRate,
MaxChangeRate: oldValidator.Commission.MaxChangeRate,
},
UpdateTime: oldValidator.Commission.UpdateTime,
},
MinSelfDelegation: oldValidator.MinSelfDelegation,
}
}
newDelegations := make([]v040staking.Delegation, len(stakingState.Delegations))
for i, oldDelegation := range stakingState.Delegations {
newDelegations[i] = v040staking.Delegation{
DelegatorAddress: oldDelegation.DelegatorAddress.String(),
ValidatorAddress: oldDelegation.ValidatorAddress.String(),
Shares: oldDelegation.Shares,
}
}
newUnbondingDelegations := make([]v040staking.UnbondingDelegation, len(stakingState.UnbondingDelegations))
for i, oldUnbondingDelegation := range stakingState.UnbondingDelegations {
newEntries := make([]v040staking.UnbondingDelegationEntry, len(oldUnbondingDelegation.Entries))
for j, oldEntry := range oldUnbondingDelegation.Entries {
newEntries[j] = v040staking.UnbondingDelegationEntry{
CreationHeight: oldEntry.CreationHeight,
CompletionTime: oldEntry.CompletionTime,
InitialBalance: oldEntry.InitialBalance,
Balance: oldEntry.Balance,
}
}
newUnbondingDelegations[i] = v040staking.UnbondingDelegation{
DelegatorAddress: oldUnbondingDelegation.DelegatorAddress.String(),
ValidatorAddress: oldUnbondingDelegation.ValidatorAddress.String(),
Entries: newEntries,
}
}
newRedelegations := make([]v040staking.Redelegation, len(stakingState.Redelegations))
for i, oldRedelegation := range stakingState.Redelegations {
newEntries := make([]v040staking.RedelegationEntry, len(oldRedelegation.Entries))
for j, oldEntry := range oldRedelegation.Entries {
newEntries[j] = v040staking.RedelegationEntry{
CreationHeight: oldEntry.CreationHeight,
CompletionTime: oldEntry.CompletionTime,
InitialBalance: oldEntry.InitialBalance,
SharesDst: oldEntry.SharesDst,
}
}
newRedelegations[i] = v040staking.Redelegation{
DelegatorAddress: oldRedelegation.DelegatorAddress.String(),
ValidatorSrcAddress: oldRedelegation.ValidatorSrcAddress.String(),
ValidatorDstAddress: oldRedelegation.ValidatorDstAddress.String(),
Entries: newEntries,
}
}
return &v040staking.GenesisState{
Params: v040staking.Params{
UnbondingTime: stakingState.Params.UnbondingTime,
MaxValidators: uint32(stakingState.Params.MaxValidators),
MaxEntries: uint32(stakingState.Params.MaxEntries),
HistoricalEntries: uint32(stakingState.Params.HistoricalEntries),
BondDenom: stakingState.Params.BondDenom,
},
LastTotalPower: stakingState.LastTotalPower,
LastValidatorPowers: newLastValidatorPowers,
Validators: newValidators,
Delegations: newDelegations,
UnbondingDelegations: newUnbondingDelegations,
Redelegations: newRedelegations,
Exported: stakingState.Exported,
}
}

View File

@ -0,0 +1,93 @@
package v040_test
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/simapp"
v034staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v034"
v038staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v038"
v040staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v040"
)
func TestMigrate(t *testing.T) {
encodingConfig := simapp.MakeEncodingConfig()
clientCtx := client.Context{}.
WithInterfaceRegistry(encodingConfig.InterfaceRegistry).
WithTxConfig(encodingConfig.TxConfig).
WithLegacyAmino(encodingConfig.Amino).
WithJSONMarshaler(encodingConfig.Marshaler)
consPubKey := ed25519.GenPrivKeyFromSecret([]byte("val0")).PubKey()
stakingGenState := v038staking.GenesisState{
Validators: v038staking.Validators{v038staking.Validator{
ConsPubKey: consPubKey,
Status: v034staking.Unbonded,
}},
}
migrated := v040staking.Migrate(stakingGenState)
bz, err := clientCtx.JSONMarshaler.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, "", " ")
require.NoError(t, err)
// Make sure about:
// - consensus_pubkey: should be bech32 pubkey
// - validator's status should be 1 (new unbonded)
expected := `{
"delegations": [],
"exported": false,
"last_total_power": "0",
"last_validator_powers": [],
"params": {
"bond_denom": "",
"historical_entries": 0,
"max_entries": 0,
"max_validators": 0,
"unbonding_time": "0s"
},
"redelegations": [],
"unbonding_delegations": [],
"validators": [
{
"commission": {
"commission_rates": {
"max_change_rate": "0",
"max_rate": "0",
"rate": "0"
},
"update_time": "0001-01-01T00:00:00Z"
},
"consensus_pubkey": "cosmosvalconspub1zcjduepq9ymett3nlv6fytn7lqxzd3q3ckvd79eqlcf3wkhgamcl4rzghesq83ecpx",
"delegator_shares": "0",
"description": {
"details": "",
"identity": "",
"moniker": "",
"security_contact": "",
"website": ""
},
"jailed": false,
"min_self_delegation": "0",
"operator_address": "",
"status": 1,
"tokens": "0",
"unbonding_height": "0",
"unbonding_time": "0001-01-01T00:00:00Z"
}
]
}`
require.Equal(t, expected, string(indentedBz))
}

View File

@ -0,0 +1,5 @@
package v040
const (
ModuleName = "staking"
)