Merge PR #4686: v0.36 supply changes to genesis migration

This commit is contained in:
Federico Kunze 2019-07-18 14:43:56 +02:00 committed by Alexander Bezobchuk
parent 257d3bfbf2
commit a922dad346
35 changed files with 1531 additions and 1250 deletions

View File

@ -56,6 +56,16 @@ var (
slashing.AppModuleBasic{},
supply.AppModuleBasic{},
)
// module account permissions
maccPerms = map[string][]string{
auth.FeeCollectorName: nil,
distr.ModuleName: nil,
mint.ModuleName: {supply.Minter},
staking.BondedPoolName: {supply.Burner, supply.Staking},
staking.NotBondedPoolName: {supply.Burner, supply.Staking},
gov.ModuleName: {supply.Burner},
}
)
// custom tx codec
@ -105,8 +115,10 @@ type SimApp struct {
}
// NewSimApp returns a reference to an initialized SimApp.
func NewSimApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
invCheckPeriod uint, baseAppOptions ...func(*bam.BaseApp)) *SimApp {
func NewSimApp(
logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
invCheckPeriod uint, baseAppOptions ...func(*bam.BaseApp),
) *SimApp {
cdc := MakeCodec()
@ -114,7 +126,7 @@ func NewSimApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bo
bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetAppVersion(version.Version)
var app = &SimApp{
app := &SimApp{
BaseApp: bApp,
cdc: cdc,
invCheckPeriod: invCheckPeriod,
@ -143,16 +155,6 @@ func NewSimApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bo
govSubspace := app.paramsKeeper.Subspace(gov.DefaultParamspace)
crisisSubspace := app.paramsKeeper.Subspace(crisis.DefaultParamspace)
// account permissions
maccPerms := map[string][]string{
auth.FeeCollectorName: nil,
distr.ModuleName: nil,
mint.ModuleName: []string{supply.Minter},
staking.BondedPoolName: []string{supply.Burner, supply.Staking},
staking.NotBondedPoolName: []string{supply.Burner, supply.Staking},
gov.ModuleName: []string{supply.Burner},
}
// add keepers
app.accountKeeper = auth.NewAccountKeeper(app.cdc, app.keyAccount, authSubspace, auth.ProtoBaseAccount)
app.bankKeeper = bank.NewBaseKeeper(app.accountKeeper, bankSubspace, bank.DefaultCodespace)
@ -202,9 +204,9 @@ func NewSimApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bo
// genutils must occur after staking so that pools are properly
// initialized with tokens from genesis accounts.
app.mm.SetOrderInitGenesis(genaccounts.ModuleName, supply.ModuleName, distr.ModuleName,
app.mm.SetOrderInitGenesis(genaccounts.ModuleName, distr.ModuleName,
staking.ModuleName, auth.ModuleName, bank.ModuleName, slashing.ModuleName,
gov.ModuleName, mint.ModuleName, crisis.ModuleName, genutil.ModuleName)
gov.ModuleName, mint.ModuleName, supply.ModuleName, crisis.ModuleName, genutil.ModuleName)
app.mm.RegisterInvariants(&app.crisisKeeper)
app.mm.RegisterRoutes(app.Router(), app.QueryRouter())
@ -250,3 +252,13 @@ func (app *SimApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.
func (app *SimApp) LoadHeight(height int64) error {
return app.LoadVersion(height, app.keyMain)
}
// ModuleAccountAddrs returns all the app's module account addresses.
func (app *SimApp) ModuleAccountAddrs() map[string]bool {
modAccAddrs := make(map[string]bool)
for acc := range maccPerms {
modAccAddrs[app.supplyKeeper.GetModuleAddress(acc).String()] = true
}
return modAccAddrs
}

View File

@ -48,10 +48,11 @@ func init() {
// helper function for populating input for SimulateFromSeed
func getSimulateFromSeedInput(tb testing.TB, w io.Writer, app *SimApp) (
testing.TB, io.Writer, *baseapp.BaseApp, simulation.AppStateFn, int64,
simulation.WeightedOperations, sdk.Invariants, int, int, bool, bool, bool, bool) {
simulation.WeightedOperations, sdk.Invariants, int, int, bool, bool, bool, bool, map[string]bool) {
return tb, w, app.BaseApp, appStateFn, seed,
testAndRunTxs(app), invariants(app), numBlocks, blockSize, commit, lean, onOperation, allInvariants
testAndRunTxs(app), invariants(app), numBlocks, blockSize, commit,
lean, onOperation, allInvariants, app.ModuleAccountAddrs()
}
func appStateFn(
@ -604,6 +605,7 @@ func TestAppStateDeterminism(t *testing.T) {
false,
false,
false,
app.ModuleAccountAddrs(),
)
appHash := app.LastCommitID().Hash
appHashList[j] = appHash
@ -630,6 +632,7 @@ func BenchmarkInvariants(b *testing.B) {
_, err := simulation.SimulateFromSeed(
b, ioutil.Discard, app.BaseApp, appStateFn, seed, testAndRunTxs(app),
[]sdk.Invariant{}, numBlocks, blockSize, commit, lean, onOperation, false,
app.ModuleAccountAddrs(),
)
if err != nil {
fmt.Println(err)

View File

@ -0,0 +1,26 @@
// DONTCOVER
// nolint
package v0_34
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
const (
ModuleName = "auth"
)
type (
Params struct {
MaxMemoCharacters uint64 `json:"max_memo_characters"`
TxSigLimit uint64 `json:"tx_sig_limit"`
TxSizeCostPerByte uint64 `json:"tx_size_cost_per_byte"`
SigVerifyCostED25519 uint64 `json:"sig_verify_cost_ed25519"`
SigVerifyCostSecp256k1 uint64 `json:"sig_verify_cost_secp256k1"`
}
GenesisState struct {
CollectedFees sdk.Coins `json:"collected_fees"`
Params Params `json:"params"`
}
)

View File

@ -0,0 +1,14 @@
// DONTCOVER
// nolint
package v0_36
import (
v034auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_34"
)
// Migrate accepts exported genesis state from v0.34 and migrates it to v0.36
// genesis state. This migration removes the CollectedFees coins from the old
// FeeCollectorKeeper.
func Migrate(oldGenState v034auth.GenesisState) GenesisState {
return NewGenesisState(oldGenState.Params)
}

View File

@ -0,0 +1,25 @@
package v0_36
import (
"github.com/cosmos/cosmos-sdk/types"
v034auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_34"
"testing"
"github.com/stretchr/testify/require"
)
func TestMigrate(t *testing.T) {
var genesisState GenesisState
require.NotPanics(t, func() {
genesisState = Migrate(v034auth.GenesisState{
CollectedFees: types.Coins{
{
Amount: types.NewInt(10),
Denom: "stake",
},
},
Params: v034auth.Params{}, // forwarded structure: filling and checking will be testing a no-op
})
})
require.Equal(t, genesisState, GenesisState{Params: v034auth.Params{}})
}

View File

@ -0,0 +1,19 @@
// DONTCOVER
// nolint
package v0_36
import v034auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_34"
const (
ModuleName = "auth"
)
type (
GenesisState struct {
Params v034auth.Params `json:"params"`
}
)
func NewGenesisState(params v034auth.Params) GenesisState {
return GenesisState{params}
}

View File

@ -12,7 +12,7 @@ const (
StoreKey = "acc"
// FeeCollectorName the root string for the fee collector account address
FeeCollectorName = "FeeCollector"
FeeCollectorName = "fee_collector"
// QuerierRoute is the querier route for acc
QuerierRoute = StoreKey

View File

@ -157,19 +157,9 @@ func (k Keeper) withdrawDelegationRewards(ctx sdk.Context, val exported.Validato
val.GetOperator(), del.GetDelegatorAddr(), rewardsRaw, rewards))
}
// decrement reference count of starting period
startingInfo := k.GetDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr())
startingPeriod := startingInfo.PreviousPeriod
k.decrementReferenceCount(ctx, del.GetValidatorAddr(), startingPeriod)
// truncate coins, return remainder to community pool
coins, remainder := rewards.TruncateDecimal()
k.SetValidatorOutstandingRewards(ctx, del.GetValidatorAddr(), outstanding.Sub(rewards))
feePool := k.GetFeePool(ctx)
feePool.CommunityPool = feePool.CommunityPool.Add(remainder)
k.SetFeePool(ctx, feePool)
// add coins to user account
if !coins.IsZero() {
withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, del.GetDelegatorAddr())
@ -179,6 +169,18 @@ func (k Keeper) withdrawDelegationRewards(ctx sdk.Context, val exported.Validato
}
}
// update the outstanding rewards and the community pool only if the
// transaction was successful
k.SetValidatorOutstandingRewards(ctx, del.GetValidatorAddr(), outstanding.Sub(rewards))
feePool := k.GetFeePool(ctx)
feePool.CommunityPool = feePool.CommunityPool.Add(remainder)
k.SetFeePool(ctx, feePool)
// decrement reference count of starting period
startingInfo := k.GetDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr())
startingPeriod := startingInfo.PreviousPeriod
k.decrementReferenceCount(ctx, del.GetValidatorAddr(), startingPeriod)
// remove delegator starting info
k.DeleteDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr())

View File

@ -8,68 +8,6 @@ import (
// genesis state. All entries are identical except for validator slashing events
// which now include the period.
func Migrate(oldGenState v034distr.GenesisState) GenesisState {
feePool := FeePool{CommunityPool: oldGenState.FeePool.CommunityPool}
dwifos := make([]DelegatorWithdrawInfo, len(oldGenState.DelegatorWithdrawInfos))
for i, info := range oldGenState.DelegatorWithdrawInfos {
dwifos[i] = DelegatorWithdrawInfo{
DelegatorAddress: info.DelegatorAddress,
WithdrawAddress: info.WithdrawAddress,
}
}
outRewards := make([]ValidatorOutstandingRewardsRecord, len(oldGenState.OutstandingRewards))
for i, rew := range oldGenState.OutstandingRewards {
outRewards[i] = ValidatorOutstandingRewardsRecord{
ValidatorAddress: rew.ValidatorAddress,
OutstandingRewards: rew.OutstandingRewards,
}
}
accumComm := make([]ValidatorAccumulatedCommissionRecord, len(oldGenState.ValidatorAccumulatedCommissions))
for i, comm := range oldGenState.ValidatorAccumulatedCommissions {
accumComm[i] = ValidatorAccumulatedCommissionRecord{
ValidatorAddress: comm.ValidatorAddress,
Accumulated: comm.Accumulated,
}
}
histRewards := make([]ValidatorHistoricalRewardsRecord, len(oldGenState.ValidatorHistoricalRewards))
for i, rew := range oldGenState.ValidatorHistoricalRewards {
histRewards[i] = ValidatorHistoricalRewardsRecord{
ValidatorAddress: rew.ValidatorAddress,
Period: rew.Period,
Rewards: ValidatorHistoricalRewards{
CumulativeRewardRatio: rew.Rewards.CumulativeRewardRatio,
ReferenceCount: rew.Rewards.ReferenceCount,
},
}
}
currRewards := make([]ValidatorCurrentRewardsRecord, len(oldGenState.ValidatorCurrentRewards))
for i, rew := range oldGenState.ValidatorCurrentRewards {
currRewards[i] = ValidatorCurrentRewardsRecord{
ValidatorAddress: rew.ValidatorAddress,
Rewards: ValidatorCurrentRewards{
Rewards: rew.Rewards.Rewards,
Period: rew.Rewards.Period,
},
}
}
delStartingInfos := make([]DelegatorStartingInfoRecord, len(oldGenState.DelegatorStartingInfos))
for i, delInfo := range oldGenState.DelegatorStartingInfos {
delStartingInfos[i] = DelegatorStartingInfoRecord{
DelegatorAddress: delInfo.DelegatorAddress,
ValidatorAddress: delInfo.ValidatorAddress,
StartingInfo: DelegatorStartingInfo{
PreviousPeriod: delInfo.StartingInfo.PreviousPeriod,
Stake: delInfo.StartingInfo.Stake,
Height: delInfo.StartingInfo.Height,
},
}
}
// migrate slash events which now have the period included
slashEvents := make([]ValidatorSlashEventRecord, len(oldGenState.ValidatorSlashEvents))
for i, se := range oldGenState.ValidatorSlashEvents {
@ -77,17 +15,16 @@ func Migrate(oldGenState v034distr.GenesisState) GenesisState {
ValidatorAddress: se.ValidatorAddress,
Height: se.Height,
Period: se.Event.ValidatorPeriod,
Event: ValidatorSlashEvent{
ValidatorPeriod: se.Event.ValidatorPeriod,
Fraction: se.Event.Fraction,
},
Event: se.Event,
}
}
return NewGenesisState(
feePool, oldGenState.CommunityTax, oldGenState.BaseProposerReward,
oldGenState.FeePool, oldGenState.CommunityTax, oldGenState.BaseProposerReward,
oldGenState.BonusProposerReward, oldGenState.WithdrawAddrEnabled,
dwifos, oldGenState.PreviousProposer, outRewards, accumComm,
histRewards, currRewards, delStartingInfos, slashEvents,
oldGenState.DelegatorWithdrawInfos, oldGenState.PreviousProposer,
oldGenState.OutstandingRewards, oldGenState.ValidatorAccumulatedCommissions,
oldGenState.ValidatorHistoricalRewards, oldGenState.ValidatorCurrentRewards,
oldGenState.DelegatorStartingInfos, slashEvents,
)
}

View File

@ -0,0 +1,63 @@
package v0_36
import (
"github.com/cosmos/cosmos-sdk/types"
v034distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_34"
"github.com/tendermint/tendermint/crypto/secp256k1"
"testing"
"github.com/stretchr/testify/require"
)
var (
priv = secp256k1.GenPrivKey()
addr = types.AccAddress(priv.PubKey().Address())
valAddr, _ = types.ValAddressFromBech32(addr.String())
event = v034distr.ValidatorSlashEvent{
ValidatorPeriod: 1,
Fraction: types.Dec{},
}
)
func TestMigrate(t *testing.T) {
var genesisState GenesisState
require.NotPanics(t, func() {
genesisState = Migrate(v034distr.GenesisState{
ValidatorSlashEvents: []v034distr.ValidatorSlashEventRecord{
{
ValidatorAddress: valAddr,
Height: 1,
Event: event,
},
},
})
})
require.Equal(t, genesisState.ValidatorSlashEvents[0], ValidatorSlashEventRecord{
ValidatorAddress: valAddr,
Height: 1,
Period: event.ValidatorPeriod,
Event: event,
})
}
func TestMigrateEmptyRecord(t *testing.T) {
var genesisState GenesisState
require.NotPanics(t, func() {
genesisState = Migrate(v034distr.GenesisState{
ValidatorSlashEvents: []v034distr.ValidatorSlashEventRecord{{}},
})
})
require.Equal(t, genesisState.ValidatorSlashEvents[0], ValidatorSlashEventRecord{
ValidatorAddress: valAddr,
Height: 0,
Period: 0,
Event: v034distr.ValidatorSlashEvent{
ValidatorPeriod: 0,
Fraction: types.Dec{},
},
})
}

View File

@ -4,6 +4,7 @@ package v0_36
import (
sdk "github.com/cosmos/cosmos-sdk/types"
v034distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_34"
)
// ----------------------------------------------------------------------------
@ -17,93 +18,36 @@ const (
type (
ValidatorAccumulatedCommission = sdk.DecCoins
ValidatorCurrentRewards struct {
Rewards sdk.DecCoins `json:"rewards"`
Period uint64 `json:"period"`
}
ValidatorHistoricalRewards struct {
CumulativeRewardRatio sdk.DecCoins `json:"cumulative_reward_ratio"`
ReferenceCount uint16 `json:"reference_count"`
}
DelegatorWithdrawInfo struct {
DelegatorAddress sdk.AccAddress `json:"delegator_address"`
WithdrawAddress sdk.AccAddress `json:"withdraw_address"`
}
ValidatorOutstandingRewardsRecord struct {
ValidatorAddress sdk.ValAddress `json:"validator_address"`
OutstandingRewards sdk.DecCoins `json:"outstanding_rewards"`
}
ValidatorAccumulatedCommissionRecord struct {
ValidatorAddress sdk.ValAddress `json:"validator_address"`
Accumulated ValidatorAccumulatedCommission `json:"accumulated"`
}
ValidatorHistoricalRewardsRecord struct {
ValidatorAddress sdk.ValAddress `json:"validator_address"`
Period uint64 `json:"period"`
Rewards ValidatorHistoricalRewards `json:"rewards"`
}
ValidatorCurrentRewardsRecord struct {
ValidatorAddress sdk.ValAddress `json:"validator_address"`
Rewards ValidatorCurrentRewards `json:"rewards"`
}
DelegatorStartingInfo struct {
PreviousPeriod uint64 `json:"previous_period"`
Stake sdk.Dec `json:"stake"`
Height uint64 `json:"creation_height"`
}
DelegatorStartingInfoRecord struct {
DelegatorAddress sdk.AccAddress `json:"delegator_address"`
ValidatorAddress sdk.ValAddress `json:"validator_address"`
StartingInfo DelegatorStartingInfo `json:"starting_info"`
}
ValidatorSlashEvent struct {
ValidatorPeriod uint64 `json:"validator_period"`
Fraction sdk.Dec `json:"fraction"`
}
ValidatorSlashEventRecord struct {
ValidatorAddress sdk.ValAddress `json:"validator_address"`
Height uint64 `json:"height"`
Period uint64 `json:"period"`
Event ValidatorSlashEvent `json:"validator_slash_event"`
}
FeePool struct {
CommunityPool sdk.DecCoins `json:"community_pool"`
ValidatorAddress sdk.ValAddress `json:"validator_address"`
Height uint64 `json:"height"`
Period uint64 `json:"period"`
Event v034distr.ValidatorSlashEvent `json:"validator_slash_event"`
}
GenesisState struct {
FeePool FeePool `json:"fee_pool"`
CommunityTax sdk.Dec `json:"community_tax"`
BaseProposerReward sdk.Dec `json:"base_proposer_reward"`
BonusProposerReward sdk.Dec `json:"bonus_proposer_reward"`
WithdrawAddrEnabled bool `json:"withdraw_addr_enabled"`
DelegatorWithdrawInfos []DelegatorWithdrawInfo `json:"delegator_withdraw_infos"`
PreviousProposer sdk.ConsAddress `json:"previous_proposer"`
OutstandingRewards []ValidatorOutstandingRewardsRecord `json:"outstanding_rewards"`
ValidatorAccumulatedCommissions []ValidatorAccumulatedCommissionRecord `json:"validator_accumulated_commissions"`
ValidatorHistoricalRewards []ValidatorHistoricalRewardsRecord `json:"validator_historical_rewards"`
ValidatorCurrentRewards []ValidatorCurrentRewardsRecord `json:"validator_current_rewards"`
DelegatorStartingInfos []DelegatorStartingInfoRecord `json:"delegator_starting_infos"`
ValidatorSlashEvents []ValidatorSlashEventRecord `json:"validator_slash_events"`
FeePool v034distr.FeePool `json:"fee_pool"`
CommunityTax sdk.Dec `json:"community_tax"`
BaseProposerReward sdk.Dec `json:"base_proposer_reward"`
BonusProposerReward sdk.Dec `json:"bonus_proposer_reward"`
WithdrawAddrEnabled bool `json:"withdraw_addr_enabled"`
DelegatorWithdrawInfos []v034distr.DelegatorWithdrawInfo `json:"delegator_withdraw_infos"`
PreviousProposer sdk.ConsAddress `json:"previous_proposer"`
OutstandingRewards []v034distr.ValidatorOutstandingRewardsRecord `json:"outstanding_rewards"`
ValidatorAccumulatedCommissions []v034distr.ValidatorAccumulatedCommissionRecord `json:"validator_accumulated_commissions"`
ValidatorHistoricalRewards []v034distr.ValidatorHistoricalRewardsRecord `json:"validator_historical_rewards"`
ValidatorCurrentRewards []v034distr.ValidatorCurrentRewardsRecord `json:"validator_current_rewards"`
DelegatorStartingInfos []v034distr.DelegatorStartingInfoRecord `json:"delegator_starting_infos"`
ValidatorSlashEvents []ValidatorSlashEventRecord `json:"validator_slash_events"`
}
)
func NewGenesisState(
feePool FeePool, communityTax, baseProposerReward, bonusProposerReward sdk.Dec,
withdrawAddrEnabled bool, dwis []DelegatorWithdrawInfo, pp sdk.ConsAddress,
r []ValidatorOutstandingRewardsRecord, acc []ValidatorAccumulatedCommissionRecord,
historical []ValidatorHistoricalRewardsRecord, cur []ValidatorCurrentRewardsRecord,
dels []DelegatorStartingInfoRecord, slashes []ValidatorSlashEventRecord,
feePool v034distr.FeePool, communityTax, baseProposerReward, bonusProposerReward sdk.Dec,
withdrawAddrEnabled bool, dwis []v034distr.DelegatorWithdrawInfo, pp sdk.ConsAddress,
r []v034distr.ValidatorOutstandingRewardsRecord, acc []v034distr.ValidatorAccumulatedCommissionRecord,
historical []v034distr.ValidatorHistoricalRewardsRecord, cur []v034distr.ValidatorCurrentRewardsRecord,
dels []v034distr.DelegatorStartingInfoRecord, slashes []ValidatorSlashEventRecord,
) GenesisState {
return GenesisState{

View File

@ -0,0 +1,28 @@
// DONTCOVER
// nolint
package v0_34
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
const (
ModuleName = "accounts"
)
type (
GenesisAccount struct {
Address sdk.AccAddress `json:"address"`
Coins sdk.Coins `json:"coins"`
Sequence uint64 `json:"sequence_number"`
AccountNumber uint64 `json:"account_number"`
OriginalVesting sdk.Coins `json:"original_vesting"`
DelegatedFree sdk.Coins `json:"delegated_free"`
DelegatedVesting sdk.Coins `json:"delegated_vesting"`
StartTime int64 `json:"start_time"`
EndTime int64 `json:"end_time"`
}
GenesisState []GenesisAccount
)

View File

@ -0,0 +1,179 @@
// DONTCOVER
// nolint
package v0_36
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
v034distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_34"
v034accounts "github.com/cosmos/cosmos-sdk/x/genaccounts/legacy/v0_34"
v034gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v0_34"
v034staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_34"
"github.com/tendermint/tendermint/crypto"
)
const (
notBondedPoolName = "not_bonded_tokens_pool"
bondedPoolName = "bonded_tokens_pool"
feeCollectorName = "fee_collector"
mintModuleName = "mint"
basic = "basic"
minter = "minter"
burner = "burner"
staking = "staking"
)
// Migrate accepts exported genesis state from v0.34 and migrates it to v0.36
// genesis state. It deletes the governance base accounts and creates the new module accounts.
// The remaining accounts are updated to the new GenesisAccount type from 0.36
func Migrate(
oldGenState v034accounts.GenesisState, fees sdk.Coins, communityPool sdk.DecCoins,
deposits []v034gov.DepositWithMetadata, vals v034staking.Validators, ubds []v034staking.UnbondingDelegation,
valOutRewards []v034distr.ValidatorOutstandingRewardsRecord, bondDenom, distrModuleName, govModuleName string,
) GenesisState {
depositedCoinsAccAddr := sdk.AccAddress(crypto.AddressHash([]byte("govDepositedCoins")))
burnedDepositCoinsAccAddr := sdk.AccAddress(crypto.AddressHash([]byte("govBurnedDepositCoins")))
bondedAmt := sdk.ZeroInt()
notBondedAmt := sdk.ZeroInt()
// remove the two previous governance base accounts for deposits and burned
// coins from rejected proposals add six new module accounts:
// distribution, gov, mint, fee collector, bonded and not bonded pool
var (
newGenState GenesisState
govCoins sdk.Coins
extraAccounts = 6
)
for _, acc := range oldGenState {
switch {
case acc.Address.Equals(depositedCoinsAccAddr):
// remove gov deposits base account
govCoins = acc.Coins
extraAccounts -= 1
case acc.Address.Equals(burnedDepositCoinsAccAddr):
// remove gov burned deposits base account
extraAccounts -= 1
default:
newGenState = append(
newGenState,
NewGenesisAccount(
acc.Address, acc.Coins, acc.Sequence,
acc.OriginalVesting, acc.DelegatedFree, acc.DelegatedVesting,
acc.StartTime, acc.EndTime, "", []string{},
),
)
}
}
var expDeposits sdk.Coins
for _, deposit := range deposits {
expDeposits = expDeposits.Add(deposit.Deposit.Amount)
}
if !expDeposits.IsEqual(govCoins) {
panic(
fmt.Sprintf(
"pre migration deposit base account coins ≠ stored deposits coins (%s ≠ %s)",
expDeposits.String(), govCoins.String(),
),
)
}
// get staking module accounts coins
for _, validator := range vals {
switch validator.Status {
case sdk.Bonded:
bondedAmt = bondedAmt.Add(validator.Tokens)
case sdk.Unbonding, sdk.Unbonded:
notBondedAmt = notBondedAmt.Add(validator.Tokens)
default:
panic("invalid validator status")
}
}
for _, ubd := range ubds {
for _, entry := range ubd.Entries {
notBondedAmt = notBondedAmt.Add(entry.Balance)
}
}
bondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, bondedAmt))
notBondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, notBondedAmt))
// get distr module account coins
var distrDecCoins sdk.DecCoins
for _, reward := range valOutRewards {
distrDecCoins = distrDecCoins.Add(reward.OutstandingRewards)
}
distrCoins, _ := distrDecCoins.Add(communityPool).TruncateDecimal()
// get module account addresses
feeCollectorAddr := sdk.AccAddress(crypto.AddressHash([]byte(feeCollectorName)))
govAddr := sdk.AccAddress(crypto.AddressHash([]byte(govModuleName)))
bondedAddr := sdk.AccAddress(crypto.AddressHash([]byte(bondedPoolName)))
notBondedAddr := sdk.AccAddress(crypto.AddressHash([]byte(notBondedPoolName)))
distrAddr := sdk.AccAddress(crypto.AddressHash([]byte(distrModuleName)))
mintAddr := sdk.AccAddress(crypto.AddressHash([]byte(mintModuleName)))
// create module genesis accounts
feeCollectorModuleAcc := NewGenesisAccount(
feeCollectorAddr, fees, 0,
sdk.Coins{}, sdk.Coins{}, sdk.Coins{},
0, 0, feeCollectorName, []string{basic},
)
govModuleAcc := NewGenesisAccount(
govAddr, govCoins, 0,
sdk.Coins{}, sdk.Coins{}, sdk.Coins{},
0, 0, govModuleName, []string{burner},
)
distrModuleAcc := NewGenesisAccount(
distrAddr, distrCoins, 0,
sdk.Coins{}, sdk.Coins{}, sdk.Coins{},
0, 0, distrModuleName, []string{basic},
)
bondedModuleAcc := NewGenesisAccount(
bondedAddr, bondedCoins, 0,
sdk.Coins{}, sdk.Coins{}, sdk.Coins{},
0, 0, bondedPoolName, []string{burner, staking},
)
notBondedModuleAcc := NewGenesisAccount(
notBondedAddr, notBondedCoins, 0,
sdk.Coins{}, sdk.Coins{}, sdk.Coins{},
0, 0, notBondedPoolName, []string{burner, staking},
)
mintModuleAcc := NewGenesisAccount(
mintAddr, sdk.Coins{}, 0,
sdk.Coins{}, sdk.Coins{}, sdk.Coins{},
0, 0, mintModuleName, []string{minter},
)
newGenState = append(
newGenState,
[]GenesisAccount{
feeCollectorModuleAcc, govModuleAcc, distrModuleAcc,
bondedModuleAcc, notBondedModuleAcc, mintModuleAcc,
}...,
)
// verify the total number of accounts is correct
if len(newGenState) != len(oldGenState)+extraAccounts {
panic(
fmt.Sprintf(
"invalid total number of genesis accounts; got: %d, expected: %d",
len(newGenState), len(oldGenState)+extraAccounts),
)
}
return newGenState
}

View File

@ -0,0 +1,123 @@
package v0_36
import (
"github.com/cosmos/cosmos-sdk/types"
v034distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_34"
v034accounts "github.com/cosmos/cosmos-sdk/x/genaccounts/legacy/v0_34"
v034gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v0_34"
v034staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_34"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/secp256k1"
"testing"
"github.com/stretchr/testify/require"
)
var (
priv = secp256k1.GenPrivKey()
addr = types.AccAddress(priv.PubKey().Address())
depositedCoinsAccAddr = types.AccAddress(crypto.AddressHash([]byte("govDepositedCoins")))
burnedDepositCoinsAccAddr = types.AccAddress(crypto.AddressHash([]byte("govBurnedDepositCoins")))
coins = types.Coins{types.NewInt64Coin(types.DefaultBondDenom, 10)}
halfCoins = types.Coins{types.NewInt64Coin(types.DefaultBondDenom, 5)}
accountDeposited = v034accounts.GenesisAccount{
Address: depositedCoinsAccAddr,
Coins: coins,
Sequence: 1,
AccountNumber: 1,
OriginalVesting: coins,
DelegatedFree: coins,
DelegatedVesting: coins,
StartTime: 0,
EndTime: 0,
}
accountBurned = v034accounts.GenesisAccount{
Address: burnedDepositCoinsAccAddr,
Coins: coins,
Sequence: 2,
AccountNumber: 2,
OriginalVesting: coins,
DelegatedFree: coins,
DelegatedVesting: coins,
StartTime: 0,
EndTime: 0,
}
deposit = v034gov.DepositWithMetadata{
ProposalID: 1,
Deposit: v034gov.Deposit{
ProposalID: 1,
Depositor: addr,
Amount: coins,
},
}
)
func TestMigrateEmptyRecord(t *testing.T) {
type args struct {
accounts v034accounts.GenesisState
deposits []v034gov.DepositWithMetadata
}
tests := []struct {
name string
args args
}{
{"No Accounts", args{v034accounts.GenesisState{}, []v034gov.DepositWithMetadata{}}},
{"Deposited account", args{v034accounts.GenesisState{accountDeposited}, []v034gov.DepositWithMetadata{deposit}}},
{"Burned account", args{v034accounts.GenesisState{accountBurned}, []v034gov.DepositWithMetadata{}}},
{"Burned and deposited accounts", args{v034accounts.GenesisState{accountDeposited, accountBurned}, []v034gov.DepositWithMetadata{deposit}}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.NotPanics(t, func() {
Migrate(
tt.args.accounts,
types.Coins{},
types.DecCoins{},
tt.args.deposits,
v034staking.Validators{},
[]v034staking.UnbondingDelegation{},
[]v034distr.ValidatorOutstandingRewardsRecord{},
types.DefaultBondDenom,
v034distr.ModuleName,
v034gov.ModuleName,
)
})
})
}
}
func TestMigrateWrongDeposit(t *testing.T) {
require.Panics(t, func() {
Migrate(
v034accounts.GenesisState{
accountDeposited,
accountBurned,
},
types.Coins{},
types.DecCoins{},
[]v034gov.DepositWithMetadata{
{
ProposalID: 1,
Deposit: v034gov.Deposit{
ProposalID: 1,
Depositor: addr,
Amount: halfCoins,
},
},
},
v034staking.Validators{},
[]v034staking.UnbondingDelegation{},
[]v034distr.ValidatorOutstandingRewardsRecord{},
types.DefaultBondDenom,
v034distr.ModuleName,
v034gov.ModuleName,
)
})
}

View File

@ -0,0 +1,53 @@
// DONTCOVER
// nolint
package v0_36
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
const (
ModuleName = "accounts"
)
type (
GenesisAccount struct {
Address sdk.AccAddress `json:"address" yaml:"address"`
Coins sdk.Coins `json:"coins" yaml:"coins"`
Sequence uint64 `json:"sequence_number" yaml:"sequence_number"`
AccountNumber uint64 `json:"account_number" yaml:"account_number"`
OriginalVesting sdk.Coins `json:"original_vesting" yaml:"original_vesting"`
DelegatedFree sdk.Coins `json:"delegated_free" yaml:"delegated_free"`
DelegatedVesting sdk.Coins `json:"delegated_vesting" yaml:"delegated_vesting"`
StartTime int64 `json:"start_time" yaml:"start_time"`
EndTime int64 `json:"end_time" yaml:"end_time"`
ModuleName string `json:"module_name" yaml:"module_name"`
ModulePermissions []string `json:"module_permissions" yaml:"module_permissions"`
}
GenesisState []GenesisAccount
)
// NewGenesisAccount creates a new GenesisAccount object
func NewGenesisAccount(
address sdk.AccAddress, coins sdk.Coins, sequence uint64,
vestingAmount, delFree, delVesting sdk.Coins, vestingStartTime, vestingEndTime int64,
module string, permissions []string,
) GenesisAccount {
return GenesisAccount{
Address: address,
Coins: coins,
Sequence: sequence,
AccountNumber: 0, // ignored set by the account keeper during InitGenesis
OriginalVesting: vestingAmount,
DelegatedFree: delFree,
DelegatedVesting: delVesting,
StartTime: vestingStartTime,
EndTime: vestingEndTime,
ModuleName: module,
ModulePermissions: permissions,
}
}

View File

@ -2,11 +2,18 @@ package v036
import (
"github.com/cosmos/cosmos-sdk/codec"
v034auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_34"
v036auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_36"
v034distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_34"
v036distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_36"
v034genAccounts "github.com/cosmos/cosmos-sdk/x/genaccounts/legacy/v0_34"
v036genAccounts "github.com/cosmos/cosmos-sdk/x/genaccounts/legacy/v0_36"
"github.com/cosmos/cosmos-sdk/x/genutil"
v034gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v034"
v036gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v036"
v034gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v0_34"
v036gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v0_36"
v034staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_34"
v036staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_36"
v036supply "github.com/cosmos/cosmos-sdk/x/supply/legacy/v0_36"
)
// Migrate migrates exported state from v0.34 to a v0.36 genesis state.
@ -16,17 +23,52 @@ func Migrate(appState genutil.AppMap) genutil.AppMap {
v036Codec := codec.New()
codec.RegisterCrypto(v036Codec)
v034gov.RegisterCodec(v034Codec)
v036gov.RegisterCodec(v036Codec)
// migrate genesis state
// migrate genesis accounts state
if appState[v034genAccounts.ModuleName] != nil {
var genAccs v034genAccounts.GenesisState
v034Codec.MustUnmarshalJSON(appState[v034genAccounts.ModuleName], &genAccs)
var authGenState v034auth.GenesisState
v034Codec.MustUnmarshalJSON(appState[v034auth.ModuleName], &authGenState)
var govGenState v034gov.GenesisState
v034Codec.MustUnmarshalJSON(appState[v034gov.ModuleName], &govGenState)
var distrGenState v034distr.GenesisState
v034Codec.MustUnmarshalJSON(appState[v034distr.ModuleName], &distrGenState)
var stakingGenState v034staking.GenesisState
v034Codec.MustUnmarshalJSON(appState[v034staking.ModuleName], &stakingGenState)
delete(appState, v034genAccounts.ModuleName) // delete old key in case the name changed
appState[v036genAccounts.ModuleName] = v036Codec.MustMarshalJSON(
v036genAccounts.Migrate(
genAccs, authGenState.CollectedFees, distrGenState.FeePool.CommunityPool, govGenState.Deposits,
stakingGenState.Validators, stakingGenState.UnbondingDelegations, distrGenState.OutstandingRewards,
stakingGenState.Params.BondDenom, v036distr.ModuleName, v036gov.ModuleName,
),
)
}
// migrate auth state
if appState[v034auth.ModuleName] != nil {
var authGenState v034auth.GenesisState
v034Codec.MustUnmarshalJSON(appState[v034auth.ModuleName], &authGenState)
delete(appState, v034auth.ModuleName) // delete old key in case the name changed
appState[v036auth.ModuleName] = v036Codec.MustMarshalJSON(v036auth.Migrate(authGenState))
}
// migrate gov state
if appState[v034gov.ModuleName] != nil {
v034gov.RegisterCodec(v034Codec)
v036gov.RegisterCodec(v036Codec)
var govState v034gov.GenesisState
v034Codec.MustUnmarshalJSON(appState[v034gov.ModuleName], &govState)
var govGenState v034gov.GenesisState
v034Codec.MustUnmarshalJSON(appState[v034gov.ModuleName], &govGenState)
delete(appState, v034gov.ModuleName) // delete old key in case the name changed
appState[v036gov.ModuleName] = v036Codec.MustMarshalJSON(v036gov.MigrateGovernance(govState))
appState[v036gov.ModuleName] = v036Codec.MustMarshalJSON(v036gov.Migrate(govGenState))
}
// migrate distribution state
@ -38,5 +80,16 @@ func Migrate(appState genutil.AppMap) genutil.AppMap {
appState[v036distr.ModuleName] = v036Codec.MustMarshalJSON(v036distr.Migrate(slashingGenState))
}
// migrate staking state
if appState[v034staking.ModuleName] != nil {
var stakingGenState v034staking.GenesisState
v034Codec.MustUnmarshalJSON(appState[v034staking.ModuleName], &stakingGenState)
delete(appState, v034staking.ModuleName) // delete old key in case the name changed
appState[v036staking.ModuleName] = v036Codec.MustMarshalJSON(v036staking.Migrate(stakingGenState))
}
appState[v036supply.ModuleName] = v036Codec.MustMarshalJSON(v036supply.EmptyGenesisState())
return appState
}

View File

@ -1,513 +0,0 @@
package v034
import (
"encoding/json"
"fmt"
"strings"
"time"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Keys
const (
// ModuleName is the name of the module
ModuleName = "gov"
// StoreKey is the store key string for gov
StoreKey = ModuleName
// RouterKey is the message route for gov
RouterKey = ModuleName
// QuerierRoute is the querier route for gov
QuerierRoute = ModuleName
// DefaultParamspace default name for parameter store
DefaultParamspace = ModuleName
)
type GenesisState struct {
StartingProposalID uint64 `json:"starting_proposal_id"`
Deposits []DepositWithMetadata `json:"deposits"`
Votes []VoteWithMetadata `json:"votes"`
Proposals []Proposal `json:"proposals"`
DepositParams DepositParams `json:"deposit_params"`
VotingParams VotingParams `json:"voting_params"`
TallyParams TallyParams `json:"tally_params"`
}
type DepositWithMetadata struct {
ProposalID uint64 `json:"proposal_id"`
Deposit Deposit `json:"deposit"`
}
type VoteWithMetadata struct {
ProposalID uint64 `json:"proposal_id"`
Vote Vote `json:"vote"`
}
type Deposit struct {
ProposalID uint64 `json:"proposal_id"` // proposalID of the proposal
Depositor sdk.AccAddress `json:"depositor"` // Address of the depositor
Amount sdk.Coins `json:"amount"` // Deposit amount
}
type Deposits []Deposit
type Vote struct {
ProposalID uint64 `json:"proposal_id"` // proposalID of the proposal
Voter sdk.AccAddress `json:"voter"` // address of the voter
Option VoteOption `json:"option"` // option from OptionSet chosen by the voter
}
type Votes []Vote
// Param around deposits for governance
type DepositParams struct {
MinDeposit sdk.Coins `json:"min_deposit,omitempty"` // Minimum deposit for a proposal to enter voting period.
MaxDepositPeriod time.Duration `json:"max_deposit_period,omitempty"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months
}
type TallyParams struct {
Quorum sdk.Dec `json:"quorum,omitempty"` // Minimum percentage of total stake needed to vote for a result to be considered valid
Threshold sdk.Dec `json:"threshold,omitempty"` // Minimum proportion of Yes votes for proposal to pass. Initial value: 0.5
Veto sdk.Dec `json:"veto,omitempty"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
}
type VotingParams struct {
VotingPeriod time.Duration `json:"voting_period,omitempty"` // Length of the voting period.
}
type TallyResult struct {
Yes sdk.Int `json:"yes"`
Abstain sdk.Int `json:"abstain"`
No sdk.Int `json:"no"`
NoWithVeto sdk.Int `json:"no_with_veto"`
}
// ----------------------------------------------------------------------------
// ProposalStatus
// ----------------------------------------------------------------------------
// ProposalStatus is a type alias that represents a proposal status as a byte
type ProposalStatus byte
//nolint
const (
StatusNil ProposalStatus = 0x00
StatusDepositPeriod ProposalStatus = 0x01
StatusVotingPeriod ProposalStatus = 0x02
StatusPassed ProposalStatus = 0x03
StatusRejected ProposalStatus = 0x04
StatusFailed ProposalStatus = 0x05
)
// ProposalStatusToString turns a string into a ProposalStatus
func ProposalStatusFromString(str string) (ProposalStatus, error) {
switch str {
case "DepositPeriod":
return StatusDepositPeriod, nil
case "VotingPeriod":
return StatusVotingPeriod, nil
case "Passed":
return StatusPassed, nil
case "Rejected":
return StatusRejected, nil
case "Failed":
return StatusFailed, nil
case "":
return StatusNil, nil
default:
return ProposalStatus(0xff), fmt.Errorf("'%s' is not a valid proposal status", str)
}
}
// Marshal needed for protobuf compatibility
func (status ProposalStatus) Marshal() ([]byte, error) {
return []byte{byte(status)}, nil
}
// Unmarshal needed for protobuf compatibility
func (status *ProposalStatus) Unmarshal(data []byte) error {
*status = ProposalStatus(data[0])
return nil
}
// Marshals to JSON using string
func (status ProposalStatus) MarshalJSON() ([]byte, error) {
return json.Marshal(status.String())
}
// Unmarshals from JSON assuming Bech32 encoding
func (status *ProposalStatus) UnmarshalJSON(data []byte) error {
var s string
err := json.Unmarshal(data, &s)
if err != nil {
return err
}
bz2, err := ProposalStatusFromString(s)
if err != nil {
return err
}
*status = bz2
return nil
}
// String implements the Stringer interface.
func (status ProposalStatus) String() string {
switch status {
case StatusDepositPeriod:
return "DepositPeriod"
case StatusVotingPeriod:
return "VotingPeriod"
case StatusPassed:
return "Passed"
case StatusRejected:
return "Rejected"
case StatusFailed:
return "Failed"
default:
return ""
}
}
// Format implements the fmt.Formatter interface.
// nolint: errcheck
func (status ProposalStatus) Format(s fmt.State, verb rune) {
switch verb {
case 's':
s.Write([]byte(status.String()))
default:
// TODO: Do this conversion more directly
s.Write([]byte(fmt.Sprintf("%v", byte(status))))
}
}
// ----------------------------------------------------------------------------
// VoteOption
// ----------------------------------------------------------------------------
type VoteOption byte
// Vote options
const (
OptionEmpty VoteOption = 0x00
OptionYes VoteOption = 0x01
OptionAbstain VoteOption = 0x02
OptionNo VoteOption = 0x03
OptionNoWithVeto VoteOption = 0x04
)
// VoteOptionFromString returns a VoteOption from a string. It returns an error
// if the string is invalid.
func VoteOptionFromString(str string) (VoteOption, error) {
switch str {
case "Yes":
return OptionYes, nil
case "Abstain":
return OptionAbstain, nil
case "No":
return OptionNo, nil
case "NoWithVeto":
return OptionNoWithVeto, nil
default:
return VoteOption(0xff), fmt.Errorf("'%s' is not a valid vote option", str)
}
}
// Marshal needed for protobuf compatibility.
func (vo VoteOption) Marshal() ([]byte, error) {
return []byte{byte(vo)}, nil
}
// Unmarshal needed for protobuf compatibility.
func (vo *VoteOption) Unmarshal(data []byte) error {
*vo = VoteOption(data[0])
return nil
}
// Marshals to JSON using string.
func (vo VoteOption) MarshalJSON() ([]byte, error) {
return json.Marshal(vo.String())
}
// UnmarshalJSON decodes from JSON assuming Bech32 encoding.
func (vo *VoteOption) UnmarshalJSON(data []byte) error {
var s string
err := json.Unmarshal(data, &s)
if err != nil {
return err
}
bz2, err := VoteOptionFromString(s)
if err != nil {
return err
}
*vo = bz2
return nil
}
// String implements the Stringer interface.
func (vo VoteOption) String() string {
switch vo {
case OptionYes:
return "Yes"
case OptionAbstain:
return "Abstain"
case OptionNo:
return "No"
case OptionNoWithVeto:
return "NoWithVeto"
default:
return ""
}
}
// Format implements the fmt.Formatter interface.
// nolint: errcheck
func (vo VoteOption) Format(s fmt.State, verb rune) {
switch verb {
case 's':
s.Write([]byte(vo.String()))
default:
s.Write([]byte(fmt.Sprintf("%v", byte(vo))))
}
}
// ----------------------------------------------------------------------------
// Tally
// ----------------------------------------------------------------------------
// Equals returns if two proposals are equal.
func (tr TallyResult) Equals(comp TallyResult) bool {
return tr.Yes.Equal(comp.Yes) &&
tr.Abstain.Equal(comp.Abstain) &&
tr.No.Equal(comp.No) &&
tr.NoWithVeto.Equal(comp.NoWithVeto)
}
func (tr TallyResult) String() string {
return fmt.Sprintf(`Tally Result:
Yes: %s
Abstain: %s
No: %s
NoWithVeto: %s`, tr.Yes, tr.Abstain, tr.No, tr.NoWithVeto)
}
// ----------------------------------------------------------------------------
// Proposal
// ----------------------------------------------------------------------------
type Proposal struct {
ProposalContent `json:"proposal_content"` // Proposal content interface
ProposalID uint64 `json:"proposal_id"` // ID of the proposal
Status ProposalStatus `json:"proposal_status"` // Status of the Proposal {Pending, Active, Passed, Rejected}
FinalTallyResult TallyResult `json:"final_tally_result"` // Result of Tallys
SubmitTime time.Time `json:"submit_time"` // Time of the block where TxGovSubmitProposal was included
DepositEndTime time.Time `json:"deposit_end_time"` // Time that the Proposal would expire if deposit amount isn't met
TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit
VotingStartTime time.Time `json:"voting_start_time"` // Time of the block where MinDeposit was reached. -1 if MinDeposit is not reached
VotingEndTime time.Time `json:"voting_end_time"` // Time that the VotingPeriod for this proposal will end and votes will be tallied
}
// nolint
func (p Proposal) String() string {
return fmt.Sprintf(`Proposal %d:
Title: %s
Type: %s
Status: %s
Submit Time: %s
Deposit End Time: %s
Total Deposit: %s
Voting Start Time: %s
Voting End Time: %s
Description: %s`,
p.ProposalID, p.GetTitle(), p.ProposalType(),
p.Status, p.SubmitTime, p.DepositEndTime,
p.TotalDeposit, p.VotingStartTime, p.VotingEndTime, p.GetDescription(),
)
}
// ProposalContent is an interface that has title, description, and proposaltype
// that the governance module can use to identify them and generate human readable messages
// ProposalContent can have additional fields, which will handled by ProposalHandlers
// via type assertion, e.g. parameter change amount in ParameterChangeProposal
type ProposalContent interface {
GetTitle() string
GetDescription() string
ProposalType() ProposalKind
}
// Proposals is an array of proposal
type Proposals []Proposal
// nolint
func (p Proposals) String() string {
out := "ID - (Status) [Type] Title\n"
for _, prop := range p {
out += fmt.Sprintf("%d - (%s) [%s] %s\n",
prop.ProposalID, prop.Status,
prop.ProposalType(), prop.GetTitle())
}
return strings.TrimSpace(out)
}
// Text Proposals
type TextProposal struct {
Title string `json:"title"` // Title of the proposal
Description string `json:"description"` // Description of the proposal
}
func NewTextProposal(title, description string) TextProposal {
return TextProposal{
Title: title,
Description: description,
}
}
// Implements Proposal Interface
var _ ProposalContent = TextProposal{}
// nolint
func (tp TextProposal) GetTitle() string { return tp.Title }
func (tp TextProposal) GetDescription() string { return tp.Description }
func (tp TextProposal) ProposalType() ProposalKind { return ProposalTypeText }
// Software Upgrade Proposals
type SoftwareUpgradeProposal struct {
TextProposal
}
func NewSoftwareUpgradeProposal(title, description string) SoftwareUpgradeProposal {
return SoftwareUpgradeProposal{
TextProposal: NewTextProposal(title, description),
}
}
// Implements Proposal Interface
var _ ProposalContent = SoftwareUpgradeProposal{}
// nolint
func (sup SoftwareUpgradeProposal) ProposalType() ProposalKind { return ProposalTypeSoftwareUpgrade }
// ProposalQueue
type ProposalQueue []uint64
// ProposalKind
// Type that represents Proposal Type as a byte
type ProposalKind byte
//nolint
const (
ProposalTypeNil ProposalKind = 0x00
ProposalTypeText ProposalKind = 0x01
ProposalTypeParameterChange ProposalKind = 0x02
ProposalTypeSoftwareUpgrade ProposalKind = 0x03
)
// String to proposalType byte. Returns 0xff if invalid.
func ProposalTypeFromString(str string) (ProposalKind, error) {
switch str {
case "Text":
return ProposalTypeText, nil
case "ParameterChange":
return ProposalTypeParameterChange, nil
case "SoftwareUpgrade":
return ProposalTypeSoftwareUpgrade, nil
default:
return ProposalKind(0xff), fmt.Errorf("'%s' is not a valid proposal type", str)
}
}
// Marshal needed for protobuf compatibility
func (pt ProposalKind) Marshal() ([]byte, error) {
return []byte{byte(pt)}, nil
}
// Unmarshal needed for protobuf compatibility
func (pt *ProposalKind) Unmarshal(data []byte) error {
*pt = ProposalKind(data[0])
return nil
}
// Marshals to JSON using string
func (pt ProposalKind) MarshalJSON() ([]byte, error) {
return json.Marshal(pt.String())
}
// Unmarshals from JSON assuming Bech32 encoding
func (pt *ProposalKind) UnmarshalJSON(data []byte) error {
var s string
err := json.Unmarshal(data, &s)
if err != nil {
return err
}
bz2, err := ProposalTypeFromString(s)
if err != nil {
return err
}
*pt = bz2
return nil
}
// Turns VoteOption byte to String
func (pt ProposalKind) String() string {
switch pt {
case ProposalTypeText:
return "Text"
case ProposalTypeParameterChange:
return "ParameterChange"
case ProposalTypeSoftwareUpgrade:
return "SoftwareUpgrade"
default:
return ""
}
}
// For Printf / Sprintf, returns bech32 when using %s
// nolint: errcheck
func (pt ProposalKind) Format(s fmt.State, verb rune) {
switch verb {
case 's':
s.Write([]byte(pt.String()))
default:
// TODO: Do this conversion more directly
s.Write([]byte(fmt.Sprintf("%v", byte(pt))))
}
}
// ----------------------------------------------------------------------------
// Codec
// ----------------------------------------------------------------------------
func RegisterCodec(cdc *codec.Codec) {
cdc.RegisterInterface((*ProposalContent)(nil), nil)
cdc.RegisterConcrete(TextProposal{}, "gov/TextProposal", nil)
cdc.RegisterConcrete(SoftwareUpgradeProposal{}, "gov/SoftwareUpgradeProposal", nil)
}

View File

@ -1,76 +0,0 @@
package v036
import (
v034gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v034"
)
func MigrateGovernance(initialState v034gov.GenesisState) GenesisState {
targetGov := GenesisState{
StartingProposalID: initialState.StartingProposalID,
DepositParams: DepositParams{
MinDeposit: initialState.DepositParams.MinDeposit,
MaxDepositPeriod: initialState.DepositParams.MaxDepositPeriod,
},
TallyParams: TallyParams{
Quorum: initialState.TallyParams.Quorum,
Threshold: initialState.TallyParams.Threshold,
Veto: initialState.TallyParams.Veto,
},
VotingParams: VotingParams{
VotingPeriod: initialState.VotingParams.VotingPeriod,
},
}
var deposits Deposits
for _, p := range initialState.Deposits {
deposits = append(deposits, Deposit{
ProposalID: p.Deposit.ProposalID,
Amount: p.Deposit.Amount,
Depositor: p.Deposit.Depositor,
})
}
targetGov.Deposits = deposits
var votes Votes
for _, p := range initialState.Votes {
votes = append(votes, Vote{
ProposalID: p.Vote.ProposalID,
Option: VoteOption(p.Vote.Option),
Voter: p.Vote.Voter,
})
}
targetGov.Votes = votes
var proposals Proposals
for _, p := range initialState.Proposals {
proposal := Proposal{
Content: migrateContent(p.ProposalContent),
ProposalID: p.ProposalID,
Status: ProposalStatus(p.Status),
FinalTallyResult: TallyResult(p.FinalTallyResult),
SubmitTime: p.SubmitTime,
DepositEndTime: p.DepositEndTime,
TotalDeposit: p.TotalDeposit,
VotingStartTime: p.VotingStartTime,
VotingEndTime: p.VotingEndTime,
}
proposals = append(proposals, proposal)
}
targetGov.Proposals = proposals
return targetGov
}
func migrateContent(proposalContent v034gov.ProposalContent) (content Content) {
switch proposalContent.ProposalType() {
case v034gov.ProposalTypeText:
return NewTextProposal(proposalContent.GetTitle(), proposalContent.GetDescription())
case v034gov.ProposalTypeSoftwareUpgrade:
return NewSoftwareUpgradeProposal(proposalContent.GetTitle(), proposalContent.GetDescription())
default:
return nil
}
}

View File

@ -1,454 +0,0 @@
package v036
import (
"encoding/json"
"fmt"
"strings"
"time"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Keys
const (
// ModuleName is the name of the module
ModuleName = "gov"
// StoreKey is the store key string for gov
StoreKey = ModuleName
// RouterKey is the message route for gov
RouterKey = ModuleName
// QuerierRoute is the querier route for gov
QuerierRoute = ModuleName
// DefaultParamspace default name for parameter store
DefaultParamspace = ModuleName
)
// GenesisState represents v0.34.x genesis state for the governance module.
type GenesisState struct {
StartingProposalID uint64 `json:"starting_proposal_id"`
Deposits Deposits `json:"deposits"`
Votes Votes `json:"votes"`
Proposals []Proposal `json:"proposals"`
DepositParams DepositParams `json:"deposit_params"`
VotingParams VotingParams `json:"voting_params"`
TallyParams TallyParams `json:"tally_params"`
}
type Deposit struct {
ProposalID uint64 `json:"proposal_id"` // proposalID of the proposal
Depositor sdk.AccAddress `json:"depositor"` // Address of the depositor
Amount sdk.Coins `json:"amount"` // Deposit amount
}
type Deposits []Deposit
type Vote struct {
ProposalID uint64 `json:"proposal_id"` // proposalID of the proposal
Voter sdk.AccAddress `json:"voter"` // address of the voter
Option VoteOption `json:"option"` // option from OptionSet chosen by the voter
}
type Votes []Vote
// Param around deposits for governance
type DepositParams struct {
MinDeposit sdk.Coins `json:"min_deposit,omitempty"` // Minimum deposit for a proposal to enter voting period.
MaxDepositPeriod time.Duration `json:"max_deposit_period,omitempty"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months
}
type Content interface {
GetTitle() string
GetDescription() string
ProposalRoute() string
ProposalType() string
ValidateBasic() sdk.Error
String() string
}
type Proposal struct {
Content `json:"content"` // Proposal content interface
ProposalID uint64 `json:"id"` // ID of the proposal
Status ProposalStatus `json:"proposal_status"` // Status of the Proposal {Pending, Active, Passed, Rejected}
FinalTallyResult TallyResult `json:"final_tally_result"` // Result of Tallys
SubmitTime time.Time `json:"submit_time"` // Time of the block where TxGovSubmitProposal was included
DepositEndTime time.Time `json:"deposit_end_time"` // Time that the Proposal would expire if deposit amount isn't met
TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit
VotingStartTime time.Time `json:"voting_start_time"` // Time of the block where MinDeposit was reached. -1 if MinDeposit is not reached
VotingEndTime time.Time `json:"voting_end_time"` // Time that the VotingPeriod for this proposal will end and votes will be tallied
}
type Proposals []Proposal
type ProposalQueue []uint64
type TallyParams struct {
Quorum sdk.Dec `json:"quorum,omitempty"` // Minimum percentage of total stake needed to vote for a result to be considered valid
Threshold sdk.Dec `json:"threshold,omitempty"` // Minimum proportion of Yes votes for proposal to pass. Initial value: 0.5
Veto sdk.Dec `json:"veto,omitempty"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
}
// ----------------------------------------------------------------------------
// ProposalStatus
// ----------------------------------------------------------------------------
// ProposalStatus is a type alias that represents a proposal status as a byte
type ProposalStatus byte
//nolint
const (
StatusNil ProposalStatus = 0x00
StatusDepositPeriod ProposalStatus = 0x01
StatusVotingPeriod ProposalStatus = 0x02
StatusPassed ProposalStatus = 0x03
StatusRejected ProposalStatus = 0x04
StatusFailed ProposalStatus = 0x05
)
// ProposalStatusToString turns a string into a ProposalStatus
func ProposalStatusFromString(str string) (ProposalStatus, error) {
switch str {
case "DepositPeriod":
return StatusDepositPeriod, nil
case "VotingPeriod":
return StatusVotingPeriod, nil
case "Passed":
return StatusPassed, nil
case "Rejected":
return StatusRejected, nil
case "Failed":
return StatusFailed, nil
case "":
return StatusNil, nil
default:
return ProposalStatus(0xff), fmt.Errorf("'%s' is not a valid proposal status", str)
}
}
// Marshal needed for protobuf compatibility
func (status ProposalStatus) Marshal() ([]byte, error) {
return []byte{byte(status)}, nil
}
// Unmarshal needed for protobuf compatibility
func (status *ProposalStatus) Unmarshal(data []byte) error {
*status = ProposalStatus(data[0])
return nil
}
// Marshals to JSON using string
func (status ProposalStatus) MarshalJSON() ([]byte, error) {
return json.Marshal(status.String())
}
// Unmarshals from JSON assuming Bech32 encoding
func (status *ProposalStatus) UnmarshalJSON(data []byte) error {
var s string
err := json.Unmarshal(data, &s)
if err != nil {
return err
}
bz2, err := ProposalStatusFromString(s)
if err != nil {
return err
}
*status = bz2
return nil
}
// String implements the Stringer interface.
func (status ProposalStatus) String() string {
switch status {
case StatusDepositPeriod:
return "DepositPeriod"
case StatusVotingPeriod:
return "VotingPeriod"
case StatusPassed:
return "Passed"
case StatusRejected:
return "Rejected"
case StatusFailed:
return "Failed"
default:
return ""
}
}
// Format implements the fmt.Formatter interface.
// nolint: errcheck
func (status ProposalStatus) Format(s fmt.State, verb rune) {
switch verb {
case 's':
s.Write([]byte(status.String()))
default:
// TODO: Do this conversion more directly
s.Write([]byte(fmt.Sprintf("%v", byte(status))))
}
}
type VotingParams struct {
VotingPeriod time.Duration `json:"voting_period,omitempty"` // Length of the voting period.
}
type TallyResult struct {
Yes sdk.Int `json:"yes"`
Abstain sdk.Int `json:"abstain"`
No sdk.Int `json:"no"`
NoWithVeto sdk.Int `json:"no_with_veto"`
}
// ----------------------------------------------------------------------------
// VoteOption
// ----------------------------------------------------------------------------
type VoteOption byte
// Vote options
const (
OptionEmpty VoteOption = 0x00
OptionYes VoteOption = 0x01
OptionAbstain VoteOption = 0x02
OptionNo VoteOption = 0x03
OptionNoWithVeto VoteOption = 0x04
)
// VoteOptionFromString returns a VoteOption from a string. It returns an error
// if the string is invalid.
func VoteOptionFromString(str string) (VoteOption, error) {
switch str {
case "Yes":
return OptionYes, nil
case "Abstain":
return OptionAbstain, nil
case "No":
return OptionNo, nil
case "NoWithVeto":
return OptionNoWithVeto, nil
default:
return VoteOption(0xff), fmt.Errorf("'%s' is not a valid vote option", str)
}
}
// Marshal needed for protobuf compatibility.
func (vo VoteOption) Marshal() ([]byte, error) {
return []byte{byte(vo)}, nil
}
// Unmarshal needed for protobuf compatibility.
func (vo *VoteOption) Unmarshal(data []byte) error {
*vo = VoteOption(data[0])
return nil
}
// Marshals to JSON using string.
func (vo VoteOption) MarshalJSON() ([]byte, error) {
return json.Marshal(vo.String())
}
// UnmarshalJSON decodes from JSON assuming Bech32 encoding.
func (vo *VoteOption) UnmarshalJSON(data []byte) error {
var s string
err := json.Unmarshal(data, &s)
if err != nil {
return err
}
bz2, err := VoteOptionFromString(s)
if err != nil {
return err
}
*vo = bz2
return nil
}
// String implements the Stringer interface.
func (vo VoteOption) String() string {
switch vo {
case OptionYes:
return "Yes"
case OptionAbstain:
return "Abstain"
case OptionNo:
return "No"
case OptionNoWithVeto:
return "NoWithVeto"
default:
return ""
}
}
// Format implements the fmt.Formatter interface.
// nolint: errcheck
func (vo VoteOption) Format(s fmt.State, verb rune) {
switch verb {
case 's':
s.Write([]byte(vo.String()))
default:
s.Write([]byte(fmt.Sprintf("%v", byte(vo))))
}
}
// ----------------------------------------------------------------------------
// Tally
// ----------------------------------------------------------------------------
// Equals returns if two proposals are equal.
func (tr TallyResult) Equals(comp TallyResult) bool {
return tr.Yes.Equal(comp.Yes) &&
tr.Abstain.Equal(comp.Abstain) &&
tr.No.Equal(comp.No) &&
tr.NoWithVeto.Equal(comp.NoWithVeto)
}
func (tr TallyResult) String() string {
return fmt.Sprintf(`Tally Result:
Yes: %s
Abstain: %s
No: %s
NoWithVeto: %s`, tr.Yes, tr.Abstain, tr.No, tr.NoWithVeto)
}
// ----------------------------------------------------------------------------
// Proposal
// ----------------------------------------------------------------------------
// Proposal types
const (
ProposalTypeText string = "Text"
ProposalTypeSoftwareUpgrade string = "SoftwareUpgrade"
)
// Text Proposal
type TextProposal struct {
Title string `json:"title"`
Description string `json:"description"`
}
func NewTextProposal(title, description string) Content {
return TextProposal{title, description}
}
// Implements Proposal Interface
var _ Content = TextProposal{}
// nolint
func (tp TextProposal) GetTitle() string { return tp.Title }
func (tp TextProposal) GetDescription() string { return tp.Description }
func (tp TextProposal) ProposalRoute() string { return RouterKey }
func (tp TextProposal) ProposalType() string { return ProposalTypeText }
func (tp TextProposal) ValidateBasic() sdk.Error { return ValidateAbstract(DefaultCodespace, tp) }
const (
DefaultCodespace sdk.CodespaceType = "gov"
CodeInvalidContent sdk.CodeType = 6
CodeInvalidProposalType sdk.CodeType = 7
)
func ErrInvalidProposalContent(cs sdk.CodespaceType, msg string) sdk.Error {
return sdk.NewError(cs, CodeInvalidContent, fmt.Sprintf("invalid proposal content: %s", msg))
}
func ErrInvalidProposalType(codespace sdk.CodespaceType, proposalType string) sdk.Error {
return sdk.NewError(codespace, CodeInvalidProposalType, fmt.Sprintf("proposal type '%s' is not valid", proposalType))
}
// ValidateAbstract validates a proposal's abstract contents returning an error
// if invalid.
func ValidateAbstract(codespace sdk.CodespaceType, c Content) sdk.Error {
title := c.GetTitle()
if len(strings.TrimSpace(title)) == 0 {
return ErrInvalidProposalContent(codespace, "proposal title cannot be blank")
}
if len(title) > MaxTitleLength {
return ErrInvalidProposalContent(codespace, fmt.Sprintf("proposal title is longer than max length of %d", MaxTitleLength))
}
description := c.GetDescription()
if len(description) == 0 {
return ErrInvalidProposalContent(codespace, "proposal description cannot be blank")
}
if len(description) > MaxDescriptionLength {
return ErrInvalidProposalContent(codespace, fmt.Sprintf("proposal description is longer than max length of %d", MaxDescriptionLength))
}
return nil
}
// Constants pertaining to a Content object
const (
MaxDescriptionLength int = 5000
MaxTitleLength int = 140
)
func (tp TextProposal) String() string {
return fmt.Sprintf(`Text Proposal:
Title: %s
Description: %s
`, tp.Title, tp.Description)
}
// Software Upgrade Proposals
// TODO: We have to add fields for SUP specific arguments e.g. commit hash,
// upgrade date, etc.
type SoftwareUpgradeProposal struct {
Title string `json:"title"`
Description string `json:"description"`
}
func NewSoftwareUpgradeProposal(title, description string) Content {
return SoftwareUpgradeProposal{title, description}
}
// Implements Proposal Interface
var _ Content = SoftwareUpgradeProposal{}
// nolint
func (sup SoftwareUpgradeProposal) GetTitle() string { return sup.Title }
func (sup SoftwareUpgradeProposal) GetDescription() string { return sup.Description }
func (sup SoftwareUpgradeProposal) ProposalRoute() string { return RouterKey }
func (sup SoftwareUpgradeProposal) ProposalType() string { return ProposalTypeSoftwareUpgrade }
func (sup SoftwareUpgradeProposal) ValidateBasic() sdk.Error {
return ValidateAbstract(DefaultCodespace, sup)
}
func (sup SoftwareUpgradeProposal) String() string {
return fmt.Sprintf(`Software Upgrade Proposal:
Title: %s
Description: %s
`, sup.Title, sup.Description)
}
// ----------------------------------------------------------------------------
// Codec
// ----------------------------------------------------------------------------
func RegisterCodec(cdc *codec.Codec) {
cdc.RegisterInterface((*Content)(nil), nil)
cdc.RegisterConcrete(TextProposal{}, "cosmos-sdk/TextProposal", nil)
cdc.RegisterConcrete(SoftwareUpgradeProposal{}, "cosmos-sdk/SoftwareUpgradeProposal", nil)
}

345
x/gov/legacy/v0_34/types.go Normal file
View File

@ -0,0 +1,345 @@
// DONTCOVER
// nolint
package v0_34
import (
"encoding/json"
"fmt"
"time"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
)
var (
_ ProposalContent = TextProposal{}
_ ProposalContent = SoftwareUpgradeProposal{}
)
const (
ModuleName = "gov"
StatusNil ProposalStatus = 0x00
StatusDepositPeriod ProposalStatus = 0x01
StatusVotingPeriod ProposalStatus = 0x02
StatusPassed ProposalStatus = 0x03
StatusRejected ProposalStatus = 0x04
StatusFailed ProposalStatus = 0x05
OptionEmpty VoteOption = 0x00
OptionYes VoteOption = 0x01
OptionAbstain VoteOption = 0x02
OptionNo VoteOption = 0x03
OptionNoWithVeto VoteOption = 0x04
ProposalTypeNil ProposalKind = 0x00
ProposalTypeText ProposalKind = 0x01
ProposalTypeParameterChange ProposalKind = 0x02
ProposalTypeSoftwareUpgrade ProposalKind = 0x03
)
type (
SoftwareUpgradeProposal struct {
TextProposal
}
ProposalQueue []uint64
ProposalKind byte
VoteOption byte
ProposalStatus byte
ProposalContent interface {
GetTitle() string
GetDescription() string
ProposalType() ProposalKind
}
Proposals []Proposal
TextProposal struct {
Title string `json:"title"`
Description string `json:"description"`
}
Proposal struct {
ProposalContent `json:"proposal_content"`
ProposalID uint64 `json:"proposal_id"`
Status ProposalStatus `json:"proposal_status"`
FinalTallyResult TallyResult `json:"final_tally_result"`
SubmitTime time.Time `json:"submit_time"`
DepositEndTime time.Time `json:"deposit_end_time"`
TotalDeposit sdk.Coins `json:"total_deposit"`
VotingStartTime time.Time `json:"voting_start_time"`
VotingEndTime time.Time `json:"voting_end_time"`
}
TallyParams struct {
Quorum sdk.Dec `json:"quorum,omitempty"`
Threshold sdk.Dec `json:"threshold,omitempty"`
Veto sdk.Dec `json:"veto,omitempty"`
}
VotingParams struct {
VotingPeriod time.Duration `json:"voting_period,omitempty"`
}
TallyResult struct {
Yes sdk.Int `json:"yes"`
Abstain sdk.Int `json:"abstain"`
No sdk.Int `json:"no"`
NoWithVeto sdk.Int `json:"no_with_veto"`
}
Deposits []Deposit
Vote struct {
ProposalID uint64 `json:"proposal_id"`
Voter sdk.AccAddress `json:"voter"`
Option VoteOption `json:"option"`
}
Votes []Vote
DepositParams struct {
MinDeposit sdk.Coins `json:"min_deposit,omitempty"`
MaxDepositPeriod time.Duration `json:"max_deposit_period,omitempty"`
}
Deposit struct {
ProposalID uint64 `json:"proposal_id"`
Depositor sdk.AccAddress `json:"depositor"`
Amount sdk.Coins `json:"amount"`
}
DepositWithMetadata struct {
ProposalID uint64 `json:"proposal_id"`
Deposit Deposit `json:"deposit"`
}
VoteWithMetadata struct {
ProposalID uint64 `json:"proposal_id"`
Vote Vote `json:"vote"`
}
GenesisState struct {
StartingProposalID uint64 `json:"starting_proposal_id"`
Deposits []DepositWithMetadata `json:"deposits"`
Votes []VoteWithMetadata `json:"votes"`
Proposals []Proposal `json:"proposals"`
DepositParams DepositParams `json:"deposit_params"`
VotingParams VotingParams `json:"voting_params"`
TallyParams TallyParams `json:"tally_params"`
}
)
func (tp TextProposal) GetTitle() string { return tp.Title }
func (tp TextProposal) GetDescription() string { return tp.Description }
func (tp TextProposal) ProposalType() ProposalKind { return ProposalTypeText }
func (sup SoftwareUpgradeProposal) ProposalType() ProposalKind { return ProposalTypeSoftwareUpgrade }
// ProposalStatusToString turns a string into a ProposalStatus
func ProposalStatusFromString(str string) (ProposalStatus, error) {
switch str {
case "DepositPeriod":
return StatusDepositPeriod, nil
case "VotingPeriod":
return StatusVotingPeriod, nil
case "Passed":
return StatusPassed, nil
case "Rejected":
return StatusRejected, nil
case "Failed":
return StatusFailed, nil
case "":
return StatusNil, nil
default:
return ProposalStatus(0xff), fmt.Errorf("'%s' is not a valid proposal status", str)
}
}
func (status ProposalStatus) Marshal() ([]byte, error) {
return []byte{byte(status)}, nil
}
func (status *ProposalStatus) Unmarshal(data []byte) error {
*status = ProposalStatus(data[0])
return nil
}
func (status ProposalStatus) MarshalJSON() ([]byte, error) {
return json.Marshal(status.String())
}
func (status *ProposalStatus) UnmarshalJSON(data []byte) error {
var s string
err := json.Unmarshal(data, &s)
if err != nil {
return err
}
bz2, err := ProposalStatusFromString(s)
if err != nil {
return err
}
*status = bz2
return nil
}
func (status ProposalStatus) String() string {
switch status {
case StatusDepositPeriod:
return "DepositPeriod"
case StatusVotingPeriod:
return "VotingPeriod"
case StatusPassed:
return "Passed"
case StatusRejected:
return "Rejected"
case StatusFailed:
return "Failed"
default:
return ""
}
}
func VoteOptionFromString(str string) (VoteOption, error) {
switch str {
case "Yes":
return OptionYes, nil
case "Abstain":
return OptionAbstain, nil
case "No":
return OptionNo, nil
case "NoWithVeto":
return OptionNoWithVeto, nil
default:
return VoteOption(0xff), fmt.Errorf("'%s' is not a valid vote option", str)
}
}
func (vo VoteOption) Marshal() ([]byte, error) {
return []byte{byte(vo)}, nil
}
func (vo *VoteOption) Unmarshal(data []byte) error {
*vo = VoteOption(data[0])
return nil
}
func (vo VoteOption) MarshalJSON() ([]byte, error) {
return json.Marshal(vo.String())
}
func (vo *VoteOption) UnmarshalJSON(data []byte) error {
var s string
err := json.Unmarshal(data, &s)
if err != nil {
return err
}
bz2, err := VoteOptionFromString(s)
if err != nil {
return err
}
*vo = bz2
return nil
}
func (vo VoteOption) String() string {
switch vo {
case OptionYes:
return "Yes"
case OptionAbstain:
return "Abstain"
case OptionNo:
return "No"
case OptionNoWithVeto:
return "NoWithVeto"
default:
return ""
}
}
func ProposalTypeFromString(str string) (ProposalKind, error) {
switch str {
case "Text":
return ProposalTypeText, nil
case "ParameterChange":
return ProposalTypeParameterChange, nil
case "SoftwareUpgrade":
return ProposalTypeSoftwareUpgrade, nil
default:
return ProposalKind(0xff), fmt.Errorf("'%s' is not a valid proposal type", str)
}
}
func (pt ProposalKind) Marshal() ([]byte, error) {
return []byte{byte(pt)}, nil
}
func (pt *ProposalKind) Unmarshal(data []byte) error {
*pt = ProposalKind(data[0])
return nil
}
func (pt ProposalKind) MarshalJSON() ([]byte, error) {
return json.Marshal(pt.String())
}
func (pt *ProposalKind) UnmarshalJSON(data []byte) error {
var s string
err := json.Unmarshal(data, &s)
if err != nil {
return err
}
bz2, err := ProposalTypeFromString(s)
if err != nil {
return err
}
*pt = bz2
return nil
}
func (pt ProposalKind) String() string {
switch pt {
case ProposalTypeText:
return "Text"
case ProposalTypeParameterChange:
return "ParameterChange"
case ProposalTypeSoftwareUpgrade:
return "SoftwareUpgrade"
default:
return ""
}
}
func RegisterCodec(cdc *codec.Codec) {
cdc.RegisterInterface((*ProposalContent)(nil), nil)
cdc.RegisterConcrete(TextProposal{}, "gov/TextProposal", nil)
cdc.RegisterConcrete(SoftwareUpgradeProposal{}, "gov/SoftwareUpgradeProposal", nil)
}

View File

@ -0,0 +1,51 @@
package v0_36
import (
v034gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v0_34"
)
// Migrate accepts exported genesis state from v0.34 and migrates it to v0.36
// genesis state. This migration flattens the deposits and votes and updates the
// proposal content to the new
func Migrate(oldGenState v034gov.GenesisState) GenesisState {
deposits := make(v034gov.Deposits, len(oldGenState.Deposits))
for i, deposit := range oldGenState.Deposits {
deposits[i] = deposit.Deposit
}
votes := make(v034gov.Votes, len(oldGenState.Votes))
for i, vote := range oldGenState.Votes {
votes[i] = vote.Vote
}
proposals := make([]Proposal, len(oldGenState.Proposals))
for i, proposal := range oldGenState.Proposals {
proposals[i] = Proposal{
Content: migrateContent(proposal.ProposalContent),
ProposalID: proposal.ProposalID,
Status: proposal.Status,
FinalTallyResult: proposal.FinalTallyResult,
SubmitTime: proposal.SubmitTime,
DepositEndTime: proposal.DepositEndTime,
TotalDeposit: proposal.TotalDeposit,
VotingStartTime: proposal.VotingStartTime,
VotingEndTime: proposal.VotingEndTime,
}
}
return NewGenesisState(
oldGenState.StartingProposalID, deposits, votes, proposals,
oldGenState.DepositParams, oldGenState.VotingParams, oldGenState.TallyParams,
)
}
func migrateContent(proposalContent v034gov.ProposalContent) (content Content) {
switch proposalContent.ProposalType() {
case v034gov.ProposalTypeText:
return NewTextProposal(proposalContent.GetTitle(), proposalContent.GetDescription())
case v034gov.ProposalTypeSoftwareUpgrade:
return NewSoftwareUpgradeProposal(proposalContent.GetTitle(), proposalContent.GetDescription())
default:
return nil
}
}

164
x/gov/legacy/v0_36/types.go Normal file
View File

@ -0,0 +1,164 @@
// DONTCOVER
// nolint
package v0_36
import (
"fmt"
"strings"
"time"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
v034gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v0_34"
)
const (
ModuleName = "gov"
RouterKey = ModuleName
DefaultCodespace sdk.CodespaceType = "gov"
ProposalTypeText string = "Text"
ProposalTypeSoftwareUpgrade string = "SoftwareUpgrade"
MaxDescriptionLength int = 5000
MaxTitleLength int = 140
CodeInvalidContent sdk.CodeType = 6
)
var (
_ Content = TextProposal{}
_ Content = SoftwareUpgradeProposal{}
)
type (
Proposals []Proposal
ProposalQueue []uint64
TextProposal struct {
Title string `json:"title"`
Description string `json:"description"`
}
SoftwareUpgradeProposal struct {
Title string `json:"title"`
Description string `json:"description"`
}
Content interface {
GetTitle() string
GetDescription() string
ProposalRoute() string
ProposalType() string
ValidateBasic() sdk.Error
String() string
}
Proposal struct {
Content `json:"content"`
ProposalID uint64 `json:"id"`
Status v034gov.ProposalStatus `json:"proposal_status"`
FinalTallyResult v034gov.TallyResult `json:"final_tally_result"`
SubmitTime time.Time `json:"submit_time"`
DepositEndTime time.Time `json:"deposit_end_time"`
TotalDeposit sdk.Coins `json:"total_deposit"`
VotingStartTime time.Time `json:"voting_start_time"`
VotingEndTime time.Time `json:"voting_end_time"`
}
GenesisState struct {
StartingProposalID uint64 `json:"starting_proposal_id"`
Deposits v034gov.Deposits `json:"deposits"`
Votes v034gov.Votes `json:"votes"`
Proposals []Proposal `json:"proposals"`
DepositParams v034gov.DepositParams `json:"deposit_params"`
VotingParams v034gov.VotingParams `json:"voting_params"`
TallyParams v034gov.TallyParams `json:"tally_params"`
}
)
func NewGenesisState(
startingProposalID uint64, deposits v034gov.Deposits, votes v034gov.Votes, proposals []Proposal,
depositParams v034gov.DepositParams, votingParams v034gov.VotingParams, tallyParams v034gov.TallyParams,
) GenesisState {
return GenesisState{
StartingProposalID: startingProposalID,
Deposits: deposits,
Votes: votes,
Proposals: proposals,
DepositParams: depositParams,
VotingParams: votingParams,
TallyParams: tallyParams,
}
}
func NewTextProposal(title, description string) Content {
return TextProposal{title, description}
}
func (tp TextProposal) GetTitle() string { return tp.Title }
func (tp TextProposal) GetDescription() string { return tp.Description }
func (tp TextProposal) ProposalRoute() string { return RouterKey }
func (tp TextProposal) ProposalType() string { return ProposalTypeText }
func (tp TextProposal) ValidateBasic() sdk.Error { return ValidateAbstract(DefaultCodespace, tp) }
func (tp TextProposal) String() string {
return fmt.Sprintf(`Text Proposal:
Title: %s
Description: %s
`, tp.Title, tp.Description)
}
func NewSoftwareUpgradeProposal(title, description string) Content {
return SoftwareUpgradeProposal{title, description}
}
func (sup SoftwareUpgradeProposal) GetTitle() string { return sup.Title }
func (sup SoftwareUpgradeProposal) GetDescription() string { return sup.Description }
func (sup SoftwareUpgradeProposal) ProposalRoute() string { return RouterKey }
func (sup SoftwareUpgradeProposal) ProposalType() string { return ProposalTypeSoftwareUpgrade }
func (sup SoftwareUpgradeProposal) ValidateBasic() sdk.Error {
return ValidateAbstract(DefaultCodespace, sup)
}
func (sup SoftwareUpgradeProposal) String() string {
return fmt.Sprintf(`Software Upgrade Proposal:
Title: %s
Description: %s
`, sup.Title, sup.Description)
}
func ErrInvalidProposalContent(cs sdk.CodespaceType, msg string) sdk.Error {
return sdk.NewError(cs, CodeInvalidContent, fmt.Sprintf("invalid proposal content: %s", msg))
}
func ValidateAbstract(codespace sdk.CodespaceType, c Content) sdk.Error {
title := c.GetTitle()
if len(strings.TrimSpace(title)) == 0 {
return ErrInvalidProposalContent(codespace, "proposal title cannot be blank")
}
if len(title) > MaxTitleLength {
return ErrInvalidProposalContent(codespace, fmt.Sprintf("proposal title is longer than max length of %d", MaxTitleLength))
}
description := c.GetDescription()
if len(description) == 0 {
return ErrInvalidProposalContent(codespace, "proposal description cannot be blank")
}
if len(description) > MaxDescriptionLength {
return ErrInvalidProposalContent(codespace, fmt.Sprintf("proposal description is longer than max length of %d", MaxDescriptionLength))
}
return nil
}
func RegisterCodec(cdc *codec.Codec) {
cdc.RegisterInterface((*Content)(nil), nil)
cdc.RegisterConcrete(TextProposal{}, "cosmos-sdk/TextProposal", nil)
cdc.RegisterConcrete(SoftwareUpgradeProposal{}, "cosmos-sdk/SoftwareUpgradeProposal", nil)
}

View File

@ -47,6 +47,7 @@ func SimulateFromSeed(
appStateFn AppStateFn, seed int64, ops WeightedOperations,
invariants sdk.Invariants,
numBlocks, blockSize int, commit, lean, onOperation, allInvariants bool,
blackListedAccs map[string]bool,
) (stopEarly bool, simError error) {
// in case we have to end early, don't os.Exit so that we can run cleanup code.
@ -74,6 +75,16 @@ func SimulateFromSeed(
return true, fmt.Errorf("must have greater than zero genesis accounts")
}
// remove module account address if they exist in accs
var tmpAccs []Account
for _, acc := range accs {
if !blackListedAccs[acc.Address.String()] {
tmpAccs = append(tmpAccs, acc)
}
}
accs = tmpAccs
nextValidators := validators
header := abci.Header{

View File

@ -151,7 +151,7 @@ func (k Keeper) HandleValidatorSignature(ctx sdk.Context, addr crypto.Address, p
consAddr := sdk.ConsAddress(addr)
pubkey, err := k.getPubkey(ctx, addr)
if err != nil {
panic(fmt.Sprintf("Validator consensus-address %v not found", consAddr.String()))
panic(fmt.Sprintf("Validator consensus-address %s not found", consAddr))
}
// fetch signing info
@ -193,7 +193,8 @@ func (k Keeper) HandleValidatorSignature(ctx sdk.Context, addr crypto.Address, p
),
)
logger.Info(fmt.Sprintf("Absent validator %s (%s) at height %d, %d missed, threshold %d", addr, pubkey, height, signInfo.MissedBlocksCounter, k.MinSignedPerWindow(ctx)))
logger.Info(
fmt.Sprintf("Absent validator %s (%s) at height %d, %d missed, threshold %d", consAddr, pubkey, height, signInfo.MissedBlocksCounter, k.MinSignedPerWindow(ctx)))
}
minHeight := signInfo.StartHeight + k.SignedBlocksWindow(ctx)
@ -206,7 +207,7 @@ func (k Keeper) HandleValidatorSignature(ctx sdk.Context, addr crypto.Address, p
// Downtime confirmed: slash and jail the validator
logger.Info(fmt.Sprintf("Validator %s past min height of %d and below signed blocks threshold of %d",
sdk.ConsAddress(pubkey.Address()), minHeight, k.MinSignedPerWindow(ctx)))
consAddr, minHeight, k.MinSignedPerWindow(ctx)))
// We need to retrieve the stake distribution which signed the block, so we subtract ValidatorUpdateDelay from the evidence height,
// and subtract an additional 1 since this is the LastCommit.
@ -235,8 +236,9 @@ func (k Keeper) HandleValidatorSignature(ctx sdk.Context, addr crypto.Address, p
k.clearValidatorMissedBlockBitArray(ctx, consAddr)
} else {
// Validator was (a) not found or (b) already jailed, don't slash
logger.Info(fmt.Sprintf("Validator %s would have been slashed for downtime, but was either not found in store or already jailed",
sdk.ConsAddress(pubkey.Address())))
logger.Info(
fmt.Sprintf("Validator %s would have been slashed for downtime, but was either not found in store or already jailed", consAddr),
)
}
}

View File

@ -0,0 +1,177 @@
// DONTCOVER
// nolint
package v0_34
import (
"time"
"github.com/tendermint/tendermint/crypto"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
)
const (
ModuleName = "staking"
)
type (
Pool struct {
NotBondedTokens sdk.Int `json:"not_bonded_tokens"`
BondedTokens sdk.Int `json:"bonded_tokens"`
}
Params struct {
UnbondingTime time.Duration `json:"unbonding_time"`
MaxValidators uint16 `json:"max_validators"`
MaxEntries uint16 `json:"max_entries"`
BondDenom string `json:"bond_denom"`
}
LastValidatorPower struct {
Address sdk.ValAddress
Power int64
}
Description struct {
Moniker string `json:"moniker"`
Identity string `json:"identity"`
Website string `json:"website"`
Details string `json:"details"`
}
Commission struct {
CommissionRates CommissionRates `json:"commission_rates"`
UpdateTime time.Time `json:"update_time"`
}
CommissionRates struct {
Rate sdk.Dec `json:"rate"`
MaxRate sdk.Dec `json:"max_rate"`
MaxChangeRate sdk.Dec `json:"max_change_rate"`
}
bechValidator struct {
OperatorAddress sdk.ValAddress `json:"operator_address"` // the bech32 address of the validator's operator
ConsPubKey string `json:"consensus_pubkey"` // the bech32 consensus public key of the validator
Jailed bool `json:"jailed"` // has the validator been jailed from bonded status?
Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded)
Tokens sdk.Int `json:"tokens"` // delegated tokens (incl. self-delegation)
DelegatorShares sdk.Dec `json:"delegator_shares"` // total shares issued to a validator's delegators
Description Description `json:"description"` // description terms for the validator
UnbondingHeight int64 `json:"unbonding_height"` // if unbonding, height at which this validator has begun unbonding
UnbondingCompletionTime time.Time `json:"unbonding_time"` // if unbonding, min time for the validator to complete unbonding
Commission Commission `json:"commission"` // commission parameters
MinSelfDelegation sdk.Int `json:"min_self_delegation"` // minimum self delegation
}
Validator struct {
OperatorAddress sdk.ValAddress `json:"operator_address"`
ConsPubKey crypto.PubKey `json:"consensus_pubkey"`
Jailed bool `json:"jailed"`
Status sdk.BondStatus `json:"status"`
Tokens sdk.Int `json:"tokens"`
DelegatorShares sdk.Dec `json:"delegator_shares"`
Description Description `json:"description"`
UnbondingHeight int64 `json:"unbonding_height"`
UnbondingCompletionTime time.Time `json:"unbonding_time"`
Commission Commission `json:"commission"`
MinSelfDelegation sdk.Int `json:"min_self_delegation"`
}
Validators []Validator
Delegation struct {
DelegatorAddress sdk.AccAddress `json:"delegator_address"`
ValidatorAddress sdk.ValAddress `json:"validator_address"`
Shares sdk.Dec `json:"shares"`
}
Delegations []Delegation
UnbondingDelegationEntry struct {
CreationHeight int64 `json:"creation_height"`
CompletionTime time.Time `json:"completion_time"`
InitialBalance sdk.Int `json:"initial_balance"`
Balance sdk.Int `json:"balance"`
}
UnbondingDelegation struct {
DelegatorAddress sdk.AccAddress `json:"delegator_address"`
ValidatorAddress sdk.ValAddress `json:"validator_address"`
Entries []UnbondingDelegationEntry `json:"entries"`
}
RedelegationEntry struct {
CreationHeight int64 `json:"creation_height"`
CompletionTime time.Time `json:"completion_time"`
InitialBalance sdk.Int `json:"initial_balance"`
SharesDst sdk.Dec `json:"shares_dst"`
}
Redelegation struct {
DelegatorAddress sdk.AccAddress `json:"delegator_address"`
ValidatorSrcAddress sdk.ValAddress `json:"validator_src_address"`
ValidatorDstAddress sdk.ValAddress `json:"validator_dst_address"`
Entries []RedelegationEntry `json:"entries"`
}
GenesisState struct {
Pool Pool `json:"pool"`
Params Params `json:"params"`
LastTotalPower sdk.Int `json:"last_total_power"`
LastValidatorPowers []LastValidatorPower `json:"last_validator_powers"`
Validators Validators `json:"validators"`
Delegations Delegations `json:"delegations"`
UnbondingDelegations []UnbondingDelegation `json:"unbonding_delegations"`
Redelegations []Redelegation `json:"redelegations"`
Exported bool `json:"exported"`
}
)
func (v Validator) MarshalJSON() ([]byte, error) {
bechConsPubKey, err := sdk.Bech32ifyConsPub(v.ConsPubKey)
if err != nil {
return nil, err
}
return codec.Cdc.MarshalJSON(bechValidator{
OperatorAddress: v.OperatorAddress,
ConsPubKey: bechConsPubKey,
Jailed: v.Jailed,
Status: v.Status,
Tokens: v.Tokens,
DelegatorShares: v.DelegatorShares,
Description: v.Description,
UnbondingHeight: v.UnbondingHeight,
UnbondingCompletionTime: v.UnbondingCompletionTime,
MinSelfDelegation: v.MinSelfDelegation,
Commission: v.Commission,
})
}
// UnmarshalJSON unmarshals the validator from JSON using Bech32
func (v *Validator) UnmarshalJSON(data []byte) error {
bv := &bechValidator{}
if err := codec.Cdc.UnmarshalJSON(data, bv); err != nil {
return err
}
consPubKey, err := sdk.GetConsPubKeyBech32(bv.ConsPubKey)
if err != nil {
return err
}
*v = Validator{
OperatorAddress: bv.OperatorAddress,
ConsPubKey: consPubKey,
Jailed: bv.Jailed,
Tokens: bv.Tokens,
Status: bv.Status,
DelegatorShares: bv.DelegatorShares,
Description: bv.Description,
UnbondingHeight: bv.UnbondingHeight,
UnbondingCompletionTime: bv.UnbondingCompletionTime,
Commission: bv.Commission,
MinSelfDelegation: bv.MinSelfDelegation,
}
return nil
}

View File

@ -0,0 +1,23 @@
// DONTCOVER
// nolint
package v0_36
import (
v034staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_34"
)
// Migrate accepts exported genesis state from v0.34 and migrates it to v0.36
// genesis state. All entries are identical except for validator slashing events
// which now include the period.
func Migrate(oldGenState v034staking.GenesisState) GenesisState {
return NewGenesisState(
oldGenState.Params,
oldGenState.LastTotalPower,
oldGenState.LastValidatorPowers,
oldGenState.Validators,
oldGenState.Delegations,
oldGenState.UnbondingDelegations,
oldGenState.Redelegations,
oldGenState.Exported,
)
}

View File

@ -0,0 +1,44 @@
// DONTCOVER
// nolint
package v0_36
import (
v034staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_34"
sdk "github.com/cosmos/cosmos-sdk/types"
)
const (
ModuleName = "staking"
)
type (
GenesisState struct {
Params v034staking.Params `json:"params"`
LastTotalPower sdk.Int `json:"last_total_power"`
LastValidatorPowers []v034staking.LastValidatorPower `json:"last_validator_powers"`
Validators v034staking.Validators `json:"validators"`
Delegations v034staking.Delegations `json:"delegations"`
UnbondingDelegations []v034staking.UnbondingDelegation `json:"unbonding_delegations"`
Redelegations []v034staking.Redelegation `json:"redelegations"`
Exported bool `json:"exported"`
}
)
func NewGenesisState(
params v034staking.Params, lastTotalPower sdk.Int, lastValPowers []v034staking.LastValidatorPower,
validators v034staking.Validators, delegations v034staking.Delegations,
ubds []v034staking.UnbondingDelegation, reds []v034staking.Redelegation, exported bool,
) GenesisState {
return GenesisState{
Params: params,
LastTotalPower: lastTotalPower,
LastValidatorPowers: lastValPowers,
Validators: validators,
Delegations: delegations,
UnbondingDelegations: ubds,
Redelegations: reds,
Exported: exported,
}
}

View File

@ -159,7 +159,7 @@ func SimulateMsgUndelegate(m auth.AccountKeeper, k staking.Keeper) simulation.Op
return simulation.NoOpMsg(), nil, nil
}
msg := staking.NewMsgDelegate(
msg := staking.NewMsgUndelegate(
delegatorAddress, delegation.ValidatorAddress, sdk.NewCoin(k.GetParams(ctx).BondDenom, unbondAmt),
)
if msg.ValidateBasic() != nil {

View File

@ -8,12 +8,12 @@ import (
// names used as root for pool module accounts:
//
// - NotBondedPool -> "NotBondedTokensPool"
// - NotBondedPool -> "not_bonded_tokens_pool"
//
// - BondedPool -> "BondedTokensPool"
// - BondedPool -> "bonded_tokens_pool"
const (
NotBondedPoolName = "NotBondedTokensPool"
BondedPoolName = "BondedTokensPool"
NotBondedPoolName = "not_bonded_tokens_pool"
BondedPoolName = "bonded_tokens_pool"
)
// Pool - tracking bonded and not-bonded token supply of the bond denomination

View File

@ -7,6 +7,8 @@ import (
)
// InitGenesis sets supply information for genesis.
//
// CONTRACT: all types of accounts must have been already initialized/created
func InitGenesis(ctx sdk.Context, keeper Keeper, ak types.AccountKeeper, data GenesisState) {
// manually set the total supply based on accounts if not provided
if data.Supply.Total.Empty() {

View File

@ -73,8 +73,7 @@ func (k Keeper) UndelegateCoinsFromModuleToAccount(ctx sdk.Context, senderModule
recipientAddr sdk.AccAddress, amt sdk.Coins) sdk.Error {
acc := k.GetModuleAccount(ctx, senderModule)
senderAddr := acc.GetAddress()
if senderAddr == nil {
if acc == nil {
return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", senderModule))
}
@ -82,7 +81,7 @@ func (k Keeper) UndelegateCoinsFromModuleToAccount(ctx sdk.Context, senderModule
panic(fmt.Sprintf("module account %s does not have permissions to undelegate coins", senderModule))
}
return k.bk.UndelegateCoins(ctx, senderAddr, recipientAddr, amt)
return k.bk.UndelegateCoins(ctx, acc.GetAddress(), recipientAddr, amt)
}
// MintCoins creates new coins from thin air and adds it to the module account.
@ -95,13 +94,11 @@ func (k Keeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk
return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", moduleName))
}
addr := acc.GetAddress()
if !acc.HasPermission(types.Minter) {
panic(fmt.Sprintf("module account %s does not have permissions to mint tokens", moduleName))
}
_, err := k.bk.AddCoins(ctx, addr, amt)
_, err := k.bk.AddCoins(ctx, acc.GetAddress(), amt)
if err != nil {
panic(err)
}
@ -121,9 +118,9 @@ func (k Keeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk
// Panics if the name maps to a non-burner module account or if the amount is invalid.
func (k Keeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk.Error {
// create the account if it doesn't yet exist
acc := k.GetModuleAccount(ctx, moduleName)
addr := acc.GetAddress()
if addr == nil {
if acc == nil {
return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", moduleName))
}
@ -131,7 +128,7 @@ func (k Keeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk
panic(fmt.Sprintf("module account %s does not have permissions to burn tokens", moduleName))
}
_, err := k.bk.SubtractCoins(ctx, addr, amt)
_, err := k.bk.SubtractCoins(ctx, acc.GetAddress(), amt)
if err != nil {
panic(err)
}

View File

@ -118,7 +118,7 @@ func TestBurnCoins(t *testing.T) {
initialSupply.Inflate(initCoins)
keeper.SetSupply(ctx, initialSupply)
require.Panics(t, func() { keeper.BurnCoins(ctx, "", initCoins) }, "no module account")
require.Error(t, keeper.BurnCoins(ctx, "", initCoins), "no module account")
require.Panics(t, func() { keeper.BurnCoins(ctx, types.Minter, initCoins) }, "invalid permission")
require.Panics(t, func() { keeper.BurnCoins(ctx, randomPerm, initialSupply.Total) }, "random permission")
require.Panics(t, func() { keeper.BurnCoins(ctx, types.Burner, initialSupply.Total) }, "insufficient coins")

View File

@ -9,7 +9,7 @@ import (
// Supply represents a struct that passively keeps track of the total supply amounts in the network
type Supply struct {
Total sdk.Coins `json:"total_supply" yaml:"total_supply"` // total supply of tokens registered on the chain
Total sdk.Coins `json:"total" yaml:"total"` // total supply of tokens registered on the chain
}
// NewSupply creates a new Supply instance

View File

@ -21,7 +21,7 @@ func TestSupplyMarshalYAML(t *testing.T) {
bzCoins, err := yaml.Marshal(coins)
require.NoError(t, err)
want := fmt.Sprintf(`total_supply:
want := fmt.Sprintf(`total:
%s`, string(bzCoins))
require.Equal(t, want, string(bz))

View File

@ -0,0 +1,27 @@
// DONTCOVER
// nolint
package v0_36
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
const ModuleName = "supply"
type (
Supply struct {
Total sdk.Coins `json:"total"`
}
GenesisState struct {
Supply Supply `json:"supply"`
}
)
func EmptyGenesisState() GenesisState {
return GenesisState{
Supply: Supply{
Total: sdk.NewCoins(), // leave this empty as it's filled on initialization
},
}
}