diff --git a/simapp/sim_test.go b/simapp/sim_test.go index d85645beae..ef95a105d7 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -14,44 +14,20 @@ import ( "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto/secp256k1" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" - tmtypes "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth" authsim "github.com/cosmos/cosmos-sdk/x/auth/simulation" "github.com/cosmos/cosmos-sdk/x/bank" - distr "github.com/cosmos/cosmos-sdk/x/distribution" distrsim "github.com/cosmos/cosmos-sdk/x/distribution/simulation" - "github.com/cosmos/cosmos-sdk/x/genaccounts" - "github.com/cosmos/cosmos-sdk/x/gov" govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation" - "github.com/cosmos/cosmos-sdk/x/mint" paramsim "github.com/cosmos/cosmos-sdk/x/params/simulation" "github.com/cosmos/cosmos-sdk/x/simulation" - "github.com/cosmos/cosmos-sdk/x/slashing" slashingsim "github.com/cosmos/cosmos-sdk/x/slashing/simulation" "github.com/cosmos/cosmos-sdk/x/staking" stakingsim "github.com/cosmos/cosmos-sdk/x/staking/simulation" - "github.com/cosmos/cosmos-sdk/x/supply" -) - -var ( - genesisFile string - paramsFile string - seed int64 - numBlocks int - blockSize int - enabled bool - verbose bool - lean bool - commit bool - period int - onOperation bool // TODO Remove in favor of binary search for invariant violation ) func init() { @@ -73,42 +49,39 @@ 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) { - return tb, w, app.BaseApp, AppStateFn, seed, + return tb, w, app.BaseApp, appStateFn, seed, testAndRunTxs(app), invariants(app), numBlocks, blockSize, commit, lean, onOperation } -func AppStateFromGenesisFileFn( - r *rand.Rand, _ []simulation.Account, _ time.Time, -) (json.RawMessage, []simulation.Account, string) { +func appStateFn( + r *rand.Rand, accs []simulation.Account, genesisTimestamp time.Time, +) (appState json.RawMessage, simAccs []simulation.Account, chainID string) { - var genesis tmtypes.GenesisDoc cdc := MakeCodec() - bytes, err := ioutil.ReadFile(genesisFile) - if err != nil { - panic(err) + switch { + case paramsFile != "" && genesisFile != "": + panic("cannot provide both a genesis file and a params file") + + case genesisFile != "": + appState, simAccs, chainID = AppStateFromGenesisFileFn(r, accs, genesisTimestamp) + + case paramsFile != "": + appParams := make(simulation.AppParams) + bz, err := ioutil.ReadFile(paramsFile) + if err != nil { + panic(err) + } + + cdc.MustUnmarshalJSON(bz, &appParams) + appState, simAccs, chainID = appStateRandomizedFn(r, accs, genesisTimestamp, appParams) + + default: + appParams := make(simulation.AppParams) + appState, simAccs, chainID = appStateRandomizedFn(r, accs, genesisTimestamp, appParams) } - cdc.MustUnmarshalJSON(bytes, &genesis) - - var appState GenesisState - cdc.MustUnmarshalJSON(genesis.AppState, &appState) - - accounts := genaccounts.GetGenesisStateFromAppState(cdc, appState) - - var newAccs []simulation.Account - for _, acc := range accounts { - // Pick a random private key, since we don't know the actual key - // This should be fine as it's only used for mock Tendermint validators - // and these keys are never actually used to sign by mock Tendermint. - privkeySeed := make([]byte, 15) - r.Read(privkeySeed) - - privKey := secp256k1.GenPrivKeySecp256k1(privkeySeed) - newAccs = append(newAccs, simulation.Account{privKey, privKey.PubKey(), acc.Address}) - } - - return genesis.AppState, newAccs, genesis.ChainID + return appState, simAccs, chainID } // TODO refactor out random initialization code to the modules @@ -161,424 +134,6 @@ func appStateRandomizedFn( return appState, accs, "simulation" } -func AppStateFn( - r *rand.Rand, accs []simulation.Account, genesisTimestamp time.Time, -) (appState json.RawMessage, simAccs []simulation.Account, chainID string) { - - cdc := MakeCodec() - - switch { - case paramsFile != "" && genesisFile != "": - panic("cannot provide both a genesis file and a params file") - - case genesisFile != "": - appState, simAccs, chainID = AppStateFromGenesisFileFn(r, accs, genesisTimestamp) - - case paramsFile != "": - appParams := make(simulation.AppParams) - bz, err := ioutil.ReadFile(paramsFile) - if err != nil { - panic(err) - } - - cdc.MustUnmarshalJSON(bz, &appParams) - appState, simAccs, chainID = appStateRandomizedFn(r, accs, genesisTimestamp, appParams) - - default: - appParams := make(simulation.AppParams) - appState, simAccs, chainID = appStateRandomizedFn(r, accs, genesisTimestamp, appParams) - } - - return appState, simAccs, chainID -} - -func GenAuthGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, genesisState map[string]json.RawMessage) { - authGenesis := auth.NewGenesisState( - auth.NewParams( - func(r *rand.Rand) uint64 { - var v uint64 - ap.GetOrGenerate(cdc, simulation.MaxMemoChars, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.MaxMemoChars](r).(uint64) - }) - return v - }(r), - func(r *rand.Rand) uint64 { - var v uint64 - ap.GetOrGenerate(cdc, simulation.TxSigLimit, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.TxSigLimit](r).(uint64) - }) - return v - }(r), - func(r *rand.Rand) uint64 { - var v uint64 - ap.GetOrGenerate(cdc, simulation.TxSizeCostPerByte, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.TxSizeCostPerByte](r).(uint64) - }) - return v - }(r), - func(r *rand.Rand) uint64 { - var v uint64 - ap.GetOrGenerate(cdc, simulation.SigVerifyCostED25519, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.SigVerifyCostED25519](r).(uint64) - }) - return v - }(r), - func(r *rand.Rand) uint64 { - var v uint64 - ap.GetOrGenerate(cdc, simulation.SigVerifyCostSECP256K1, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.SigVerifyCostSECP256K1](r).(uint64) - }) - return v - }(r), - ), - ) - - fmt.Printf("Selected randomly generated auth parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, authGenesis.Params)) - genesisState[auth.ModuleName] = cdc.MustMarshalJSON(authGenesis) -} - -func GenBankGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, genesisState map[string]json.RawMessage) { - bankGenesis := bank.NewGenesisState( - func(r *rand.Rand) bool { - var v bool - ap.GetOrGenerate(cdc, simulation.SendEnabled, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.SendEnabled](r).(bool) - }) - return v - }(r), - ) - - fmt.Printf("Selected randomly generated bank parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, bankGenesis)) - genesisState[bank.ModuleName] = cdc.MustMarshalJSON(bankGenesis) -} - -func GenSupplyGenesisState(cdc *codec.Codec, amount, numInitiallyBonded, numAccs int64, genesisState map[string]json.RawMessage) { - totalSupply := sdk.NewInt(amount * (numAccs + numInitiallyBonded)) - supplyGenesis := supply.NewGenesisState( - supply.NewSupply(sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, totalSupply))), - ) - - fmt.Printf("Generated supply parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, supplyGenesis)) - genesisState[supply.ModuleName] = cdc.MustMarshalJSON(supplyGenesis) -} - -func GenGenesisAccounts( - cdc *codec.Codec, r *rand.Rand, accs []simulation.Account, - genesisTimestamp time.Time, amount, numInitiallyBonded int64, - genesisState map[string]json.RawMessage, -) { - - var genesisAccounts []genaccounts.GenesisAccount - - // randomly generate some genesis accounts - for i, acc := range accs { - coins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(amount))} - bacc := auth.NewBaseAccountWithAddress(acc.Address) - bacc.SetCoins(coins) - - var gacc genaccounts.GenesisAccount - - // Only consider making a vesting account once the initial bonded validator - // set is exhausted due to needing to track DelegatedVesting. - if int64(i) > numInitiallyBonded && r.Intn(100) < 50 { - var ( - vacc auth.VestingAccount - endTime int64 - ) - - startTime := genesisTimestamp.Unix() - - // Allow for some vesting accounts to vest very quickly while others very slowly. - if r.Intn(100) < 50 { - endTime = int64(simulation.RandIntBetween(r, int(startTime), int(startTime+(60*60*24*30)))) - } else { - endTime = int64(simulation.RandIntBetween(r, int(startTime), int(startTime+(60*60*12)))) - } - - if startTime == endTime { - endTime++ - } - - if r.Intn(100) < 50 { - vacc = auth.NewContinuousVestingAccount(&bacc, startTime, endTime) - } else { - vacc = auth.NewDelayedVestingAccount(&bacc, endTime) - } - - var err error - gacc, err = genaccounts.NewGenesisAccountI(vacc) - if err != nil { - panic(err) - } - } else { - gacc = genaccounts.NewGenesisAccount(&bacc) - } - - genesisAccounts = append(genesisAccounts, gacc) - } - - genesisState[genaccounts.ModuleName] = cdc.MustMarshalJSON(genesisAccounts) -} - -func GenGovGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, genesisState map[string]json.RawMessage) { - var vp time.Duration - ap.GetOrGenerate(cdc, simulation.VotingParamsVotingPeriod, &vp, r, - func(r *rand.Rand) { - vp = simulation.ModuleParamSimulator[simulation.VotingParamsVotingPeriod](r).(time.Duration) - }) - - govGenesis := gov.NewGenesisState( - uint64(r.Intn(100)), - gov.NewDepositParams( - func(r *rand.Rand) sdk.Coins { - var v sdk.Coins - ap.GetOrGenerate(cdc, simulation.DepositParamsMinDeposit, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.DepositParamsMinDeposit](r).(sdk.Coins) - }) - return v - }(r), - vp, - ), - gov.NewVotingParams(vp), - gov.NewTallyParams( - func(r *rand.Rand) sdk.Dec { - var v sdk.Dec - ap.GetOrGenerate(cdc, simulation.TallyParamsQuorum, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.TallyParamsQuorum](r).(sdk.Dec) - }) - return v - }(r), - func(r *rand.Rand) sdk.Dec { - var v sdk.Dec - ap.GetOrGenerate(cdc, simulation.TallyParamsThreshold, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.TallyParamsThreshold](r).(sdk.Dec) - }) - return v - }(r), - func(r *rand.Rand) sdk.Dec { - var v sdk.Dec - ap.GetOrGenerate(cdc, simulation.TallyParamsVeto, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.TallyParamsVeto](r).(sdk.Dec) - }) - return v - }(r), - ), - ) - - fmt.Printf("Selected randomly generated governance parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, govGenesis)) - genesisState[gov.ModuleName] = cdc.MustMarshalJSON(govGenesis) -} - -func GenMintGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, genesisState map[string]json.RawMessage) { - mintGenesis := mint.NewGenesisState( - mint.InitialMinter( - func(r *rand.Rand) sdk.Dec { - var v sdk.Dec - ap.GetOrGenerate(cdc, simulation.Inflation, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.Inflation](r).(sdk.Dec) - }) - return v - }(r), - ), - mint.NewParams( - sdk.DefaultBondDenom, - func(r *rand.Rand) sdk.Dec { - var v sdk.Dec - ap.GetOrGenerate(cdc, simulation.InflationRateChange, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.InflationRateChange](r).(sdk.Dec) - }) - return v - }(r), - func(r *rand.Rand) sdk.Dec { - var v sdk.Dec - ap.GetOrGenerate(cdc, simulation.InflationMax, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.InflationMax](r).(sdk.Dec) - }) - return v - }(r), - func(r *rand.Rand) sdk.Dec { - var v sdk.Dec - ap.GetOrGenerate(cdc, simulation.InflationMin, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.InflationMin](r).(sdk.Dec) - }) - return v - }(r), - func(r *rand.Rand) sdk.Dec { - var v sdk.Dec - ap.GetOrGenerate(cdc, simulation.GoalBonded, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.GoalBonded](r).(sdk.Dec) - }) - return v - }(r), - uint64(60*60*8766/5), - ), - ) - - fmt.Printf("Selected randomly generated minting parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, mintGenesis.Params)) - genesisState[mint.ModuleName] = cdc.MustMarshalJSON(mintGenesis) -} - -func GenDistrGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, genesisState map[string]json.RawMessage) { - distrGenesis := distr.GenesisState{ - FeePool: distr.InitialFeePool(), - CommunityTax: func(r *rand.Rand) sdk.Dec { - var v sdk.Dec - ap.GetOrGenerate(cdc, simulation.CommunityTax, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.CommunityTax](r).(sdk.Dec) - }) - return v - }(r), - BaseProposerReward: func(r *rand.Rand) sdk.Dec { - var v sdk.Dec - ap.GetOrGenerate(cdc, simulation.BaseProposerReward, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.BaseProposerReward](r).(sdk.Dec) - }) - return v - }(r), - BonusProposerReward: func(r *rand.Rand) sdk.Dec { - var v sdk.Dec - ap.GetOrGenerate(cdc, simulation.BonusProposerReward, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.BonusProposerReward](r).(sdk.Dec) - }) - return v - }(r), - } - - fmt.Printf("Selected randomly generated distribution parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, distrGenesis)) - genesisState[distr.ModuleName] = cdc.MustMarshalJSON(distrGenesis) -} - -func GenSlashingGenesisState( - cdc *codec.Codec, r *rand.Rand, stakingGen staking.GenesisState, - ap simulation.AppParams, genesisState map[string]json.RawMessage, -) { - slashingGenesis := slashing.NewGenesisState( - slashing.NewParams( - stakingGen.Params.UnbondingTime, - func(r *rand.Rand) int64 { - var v int64 - ap.GetOrGenerate(cdc, simulation.SignedBlocksWindow, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.SignedBlocksWindow](r).(int64) - }) - return v - }(r), - func(r *rand.Rand) sdk.Dec { - var v sdk.Dec - ap.GetOrGenerate(cdc, simulation.MinSignedPerWindow, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.MinSignedPerWindow](r).(sdk.Dec) - }) - return v - }(r), - func(r *rand.Rand) time.Duration { - var v time.Duration - ap.GetOrGenerate(cdc, simulation.DowntimeJailDuration, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.DowntimeJailDuration](r).(time.Duration) - }) - return v - }(r), - func(r *rand.Rand) sdk.Dec { - var v sdk.Dec - ap.GetOrGenerate(cdc, simulation.SlashFractionDoubleSign, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.SlashFractionDoubleSign](r).(sdk.Dec) - }) - return v - }(r), - func(r *rand.Rand) sdk.Dec { - var v sdk.Dec - ap.GetOrGenerate(cdc, simulation.SlashFractionDowntime, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.SlashFractionDowntime](r).(sdk.Dec) - }) - return v - }(r), - ), - nil, - nil, - ) - - fmt.Printf("Selected randomly generated slashing parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, slashingGenesis.Params)) - genesisState[slashing.ModuleName] = cdc.MustMarshalJSON(slashingGenesis) -} - -func GenStakingGenesisState( - cdc *codec.Codec, r *rand.Rand, accs []simulation.Account, amount, numAccs, numInitiallyBonded int64, - ap simulation.AppParams, genesisState map[string]json.RawMessage, -) staking.GenesisState { - - stakingGenesis := staking.NewGenesisState( - staking.NewParams( - func(r *rand.Rand) time.Duration { - var v time.Duration - ap.GetOrGenerate(cdc, simulation.UnbondingTime, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.UnbondingTime](r).(time.Duration) - }) - return v - }(r), - func(r *rand.Rand) uint16 { - var v uint16 - ap.GetOrGenerate(cdc, simulation.MaxValidators, &v, r, - func(r *rand.Rand) { - v = simulation.ModuleParamSimulator[simulation.MaxValidators](r).(uint16) - }) - return v - }(r), - 7, - sdk.DefaultBondDenom, - ), - nil, - nil, - ) - - var ( - validators []staking.Validator - delegations []staking.Delegation - ) - - valAddrs := make([]sdk.ValAddress, numInitiallyBonded) - for i := 0; i < int(numInitiallyBonded); i++ { - valAddr := sdk.ValAddress(accs[i].Address) - valAddrs[i] = valAddr - - validator := staking.NewValidator(valAddr, accs[i].PubKey, staking.Description{}) - validator.Tokens = sdk.NewInt(amount) - validator.DelegatorShares = sdk.NewDec(amount) - delegation := staking.NewDelegation(accs[i].Address, valAddr, sdk.NewDec(amount)) - validators = append(validators, validator) - delegations = append(delegations, delegation) - } - - stakingGenesis.Validators = validators - stakingGenesis.Delegations = delegations - - fmt.Printf("Selected randomly generated staking parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, stakingGenesis.Params)) - genesisState[staking.ModuleName] = cdc.MustMarshalJSON(stakingGenesis) - - return stakingGenesis -} - func testAndRunTxs(app *SimApp) []simulation.WeightedOperation { cdc := MakeCodec() ap := make(simulation.AppParams) @@ -1039,7 +594,7 @@ func TestAppStateDeterminism(t *testing.T) { // Run randomized simulation simulation.SimulateFromSeed( - t, os.Stdout, app.BaseApp, AppStateFn, seed, + t, os.Stdout, app.BaseApp, appStateFn, seed, testAndRunTxs(app), []sdk.Invariant{}, 50, @@ -1071,7 +626,7 @@ func BenchmarkInvariants(b *testing.B) { // 2. Run parameterized simulation (w/o invariants) _, err := simulation.SimulateFromSeed( - b, ioutil.Discard, app.BaseApp, AppStateFn, seed, testAndRunTxs(app), + b, ioutil.Discard, app.BaseApp, appStateFn, seed, testAndRunTxs(app), []sdk.Invariant{}, numBlocks, blockSize, commit, lean, onOperation, ) if err != nil { diff --git a/simapp/utils.go b/simapp/utils.go index a3397f8186..5b23452292 100644 --- a/simapp/utils.go +++ b/simapp/utils.go @@ -4,8 +4,12 @@ package simapp import ( "bytes" "encoding/binary" + "encoding/json" "fmt" "io" + "io/ioutil" + "math/rand" + "time" "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tendermint/libs/common" @@ -14,28 +18,481 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" - bam "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/tendermint/tendermint/crypto/secp256k1" + tmtypes "github.com/tendermint/tendermint/types" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/distribution" + "github.com/cosmos/cosmos-sdk/x/genaccounts" "github.com/cosmos/cosmos-sdk/x/gov" "github.com/cosmos/cosmos-sdk/x/mint" + "github.com/cosmos/cosmos-sdk/x/simulation" "github.com/cosmos/cosmos-sdk/x/slashing" "github.com/cosmos/cosmos-sdk/x/staking" "github.com/cosmos/cosmos-sdk/x/supply" ) +var ( + genesisFile string + paramsFile string + seed int64 + numBlocks int + blockSize int + enabled bool + verbose bool + lean bool + commit bool + period int + onOperation bool // TODO Remove in favor of binary search for invariant violation +) + // NewSimAppUNSAFE is used for debugging purposes only. // // NOTE: to not use this function with non-test code func NewSimAppUNSAFE(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, - invCheckPeriod uint, baseAppOptions ...func(*bam.BaseApp), + invCheckPeriod uint, baseAppOptions ...func(*baseapp.BaseApp), ) (gapp *SimApp, keyMain, keyStaking *sdk.KVStoreKey, stakingKeeper staking.Keeper) { gapp = NewSimApp(logger, db, traceStore, loadLatest, invCheckPeriod, baseAppOptions...) return gapp, gapp.keyMain, gapp.keyStaking, gapp.stakingKeeper } +// AppStateFromGenesisFileFn util function to generate the genesis AppState +// from a genesis.json file +func AppStateFromGenesisFileFn( + r *rand.Rand, _ []simulation.Account, _ time.Time, +) (json.RawMessage, []simulation.Account, string) { + + var genesis tmtypes.GenesisDoc + cdc := MakeCodec() + + bytes, err := ioutil.ReadFile(genesisFile) + if err != nil { + panic(err) + } + + cdc.MustUnmarshalJSON(bytes, &genesis) + + var appState GenesisState + cdc.MustUnmarshalJSON(genesis.AppState, &appState) + + accounts := genaccounts.GetGenesisStateFromAppState(cdc, appState) + + var newAccs []simulation.Account + for _, acc := range accounts { + // Pick a random private key, since we don't know the actual key + // This should be fine as it's only used for mock Tendermint validators + // and these keys are never actually used to sign by mock Tendermint. + privkeySeed := make([]byte, 15) + r.Read(privkeySeed) + + privKey := secp256k1.GenPrivKeySecp256k1(privkeySeed) + newAccs = append(newAccs, simulation.Account{privKey, privKey.PubKey(), acc.Address}) + } + + return genesis.AppState, newAccs, genesis.ChainID +} + +// GenAuthGenesisState generates a random GenesisState for auth +func GenAuthGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, genesisState map[string]json.RawMessage) { + authGenesis := auth.NewGenesisState( + auth.NewParams( + func(r *rand.Rand) uint64 { + var v uint64 + ap.GetOrGenerate(cdc, simulation.MaxMemoChars, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.MaxMemoChars](r).(uint64) + }) + return v + }(r), + func(r *rand.Rand) uint64 { + var v uint64 + ap.GetOrGenerate(cdc, simulation.TxSigLimit, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.TxSigLimit](r).(uint64) + }) + return v + }(r), + func(r *rand.Rand) uint64 { + var v uint64 + ap.GetOrGenerate(cdc, simulation.TxSizeCostPerByte, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.TxSizeCostPerByte](r).(uint64) + }) + return v + }(r), + func(r *rand.Rand) uint64 { + var v uint64 + ap.GetOrGenerate(cdc, simulation.SigVerifyCostED25519, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.SigVerifyCostED25519](r).(uint64) + }) + return v + }(r), + func(r *rand.Rand) uint64 { + var v uint64 + ap.GetOrGenerate(cdc, simulation.SigVerifyCostSECP256K1, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.SigVerifyCostSECP256K1](r).(uint64) + }) + return v + }(r), + ), + ) + + fmt.Printf("Selected randomly generated auth parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, authGenesis.Params)) + genesisState[auth.ModuleName] = cdc.MustMarshalJSON(authGenesis) +} + +// GenBankGenesisState generates a random GenesisState for bank +func GenBankGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, genesisState map[string]json.RawMessage) { + bankGenesis := bank.NewGenesisState( + func(r *rand.Rand) bool { + var v bool + ap.GetOrGenerate(cdc, simulation.SendEnabled, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.SendEnabled](r).(bool) + }) + return v + }(r), + ) + + fmt.Printf("Selected randomly generated bank parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, bankGenesis)) + genesisState[bank.ModuleName] = cdc.MustMarshalJSON(bankGenesis) +} + +// GenSupplyGenesisState generates a random GenesisState for supply +func GenSupplyGenesisState(cdc *codec.Codec, amount, numInitiallyBonded, numAccs int64, genesisState map[string]json.RawMessage) { + totalSupply := sdk.NewInt(amount * (numAccs + numInitiallyBonded)) + supplyGenesis := supply.NewGenesisState( + supply.NewSupply(sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, totalSupply))), + ) + + fmt.Printf("Generated supply parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, supplyGenesis)) + genesisState[supply.ModuleName] = cdc.MustMarshalJSON(supplyGenesis) +} + +// GenGenesisAccounts generates a random GenesisState for the genesis accounts +func GenGenesisAccounts( + cdc *codec.Codec, r *rand.Rand, accs []simulation.Account, + genesisTimestamp time.Time, amount, numInitiallyBonded int64, + genesisState map[string]json.RawMessage, +) { + + var genesisAccounts []genaccounts.GenesisAccount + + // randomly generate some genesis accounts + for i, acc := range accs { + coins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(amount))} + bacc := auth.NewBaseAccountWithAddress(acc.Address) + bacc.SetCoins(coins) + + var gacc genaccounts.GenesisAccount + + // Only consider making a vesting account once the initial bonded validator + // set is exhausted due to needing to track DelegatedVesting. + if int64(i) > numInitiallyBonded && r.Intn(100) < 50 { + var ( + vacc auth.VestingAccount + endTime int64 + ) + + startTime := genesisTimestamp.Unix() + + // Allow for some vesting accounts to vest very quickly while others very slowly. + if r.Intn(100) < 50 { + endTime = int64(simulation.RandIntBetween(r, int(startTime), int(startTime+(60*60*24*30)))) + } else { + endTime = int64(simulation.RandIntBetween(r, int(startTime), int(startTime+(60*60*12)))) + } + + if startTime == endTime { + endTime++ + } + + if r.Intn(100) < 50 { + vacc = auth.NewContinuousVestingAccount(&bacc, startTime, endTime) + } else { + vacc = auth.NewDelayedVestingAccount(&bacc, endTime) + } + + var err error + gacc, err = genaccounts.NewGenesisAccountI(vacc) + if err != nil { + panic(err) + } + } else { + gacc = genaccounts.NewGenesisAccount(&bacc) + } + + genesisAccounts = append(genesisAccounts, gacc) + } + + genesisState[genaccounts.ModuleName] = cdc.MustMarshalJSON(genesisAccounts) +} + +// GenGovGenesisState generates a random GenesisState for gov +func GenGovGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, genesisState map[string]json.RawMessage) { + var vp time.Duration + ap.GetOrGenerate(cdc, simulation.VotingParamsVotingPeriod, &vp, r, + func(r *rand.Rand) { + vp = simulation.ModuleParamSimulator[simulation.VotingParamsVotingPeriod](r).(time.Duration) + }) + + govGenesis := gov.NewGenesisState( + uint64(r.Intn(100)), + gov.NewDepositParams( + func(r *rand.Rand) sdk.Coins { + var v sdk.Coins + ap.GetOrGenerate(cdc, simulation.DepositParamsMinDeposit, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.DepositParamsMinDeposit](r).(sdk.Coins) + }) + return v + }(r), + vp, + ), + gov.NewVotingParams(vp), + gov.NewTallyParams( + func(r *rand.Rand) sdk.Dec { + var v sdk.Dec + ap.GetOrGenerate(cdc, simulation.TallyParamsQuorum, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.TallyParamsQuorum](r).(sdk.Dec) + }) + return v + }(r), + func(r *rand.Rand) sdk.Dec { + var v sdk.Dec + ap.GetOrGenerate(cdc, simulation.TallyParamsThreshold, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.TallyParamsThreshold](r).(sdk.Dec) + }) + return v + }(r), + func(r *rand.Rand) sdk.Dec { + var v sdk.Dec + ap.GetOrGenerate(cdc, simulation.TallyParamsVeto, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.TallyParamsVeto](r).(sdk.Dec) + }) + return v + }(r), + ), + ) + + fmt.Printf("Selected randomly generated governance parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, govGenesis)) + genesisState[gov.ModuleName] = cdc.MustMarshalJSON(govGenesis) +} + +// GenMintGenesisState generates a random GenesisState for mint +func GenMintGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, genesisState map[string]json.RawMessage) { + mintGenesis := mint.NewGenesisState( + mint.InitialMinter( + func(r *rand.Rand) sdk.Dec { + var v sdk.Dec + ap.GetOrGenerate(cdc, simulation.Inflation, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.Inflation](r).(sdk.Dec) + }) + return v + }(r), + ), + mint.NewParams( + sdk.DefaultBondDenom, + func(r *rand.Rand) sdk.Dec { + var v sdk.Dec + ap.GetOrGenerate(cdc, simulation.InflationRateChange, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.InflationRateChange](r).(sdk.Dec) + }) + return v + }(r), + func(r *rand.Rand) sdk.Dec { + var v sdk.Dec + ap.GetOrGenerate(cdc, simulation.InflationMax, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.InflationMax](r).(sdk.Dec) + }) + return v + }(r), + func(r *rand.Rand) sdk.Dec { + var v sdk.Dec + ap.GetOrGenerate(cdc, simulation.InflationMin, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.InflationMin](r).(sdk.Dec) + }) + return v + }(r), + func(r *rand.Rand) sdk.Dec { + var v sdk.Dec + ap.GetOrGenerate(cdc, simulation.GoalBonded, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.GoalBonded](r).(sdk.Dec) + }) + return v + }(r), + uint64(60*60*8766/5), + ), + ) + + fmt.Printf("Selected randomly generated minting parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, mintGenesis.Params)) + genesisState[mint.ModuleName] = cdc.MustMarshalJSON(mintGenesis) +} + +// GenDistrGenesisState generates a random GenesisState for distribution +func GenDistrGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, genesisState map[string]json.RawMessage) { + distrGenesis := distribution.GenesisState{ + FeePool: distribution.InitialFeePool(), + CommunityTax: func(r *rand.Rand) sdk.Dec { + var v sdk.Dec + ap.GetOrGenerate(cdc, simulation.CommunityTax, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.CommunityTax](r).(sdk.Dec) + }) + return v + }(r), + BaseProposerReward: func(r *rand.Rand) sdk.Dec { + var v sdk.Dec + ap.GetOrGenerate(cdc, simulation.BaseProposerReward, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.BaseProposerReward](r).(sdk.Dec) + }) + return v + }(r), + BonusProposerReward: func(r *rand.Rand) sdk.Dec { + var v sdk.Dec + ap.GetOrGenerate(cdc, simulation.BonusProposerReward, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.BonusProposerReward](r).(sdk.Dec) + }) + return v + }(r), + } + + fmt.Printf("Selected randomly generated distribution parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, distrGenesis)) + genesisState[distribution.ModuleName] = cdc.MustMarshalJSON(distrGenesis) +} + +// GenSlashingGenesisState generates a random GenesisState for slashing +func GenSlashingGenesisState( + cdc *codec.Codec, r *rand.Rand, stakingGen staking.GenesisState, + ap simulation.AppParams, genesisState map[string]json.RawMessage, +) { + slashingGenesis := slashing.NewGenesisState( + slashing.NewParams( + stakingGen.Params.UnbondingTime, + func(r *rand.Rand) int64 { + var v int64 + ap.GetOrGenerate(cdc, simulation.SignedBlocksWindow, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.SignedBlocksWindow](r).(int64) + }) + return v + }(r), + func(r *rand.Rand) sdk.Dec { + var v sdk.Dec + ap.GetOrGenerate(cdc, simulation.MinSignedPerWindow, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.MinSignedPerWindow](r).(sdk.Dec) + }) + return v + }(r), + func(r *rand.Rand) time.Duration { + var v time.Duration + ap.GetOrGenerate(cdc, simulation.DowntimeJailDuration, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.DowntimeJailDuration](r).(time.Duration) + }) + return v + }(r), + func(r *rand.Rand) sdk.Dec { + var v sdk.Dec + ap.GetOrGenerate(cdc, simulation.SlashFractionDoubleSign, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.SlashFractionDoubleSign](r).(sdk.Dec) + }) + return v + }(r), + func(r *rand.Rand) sdk.Dec { + var v sdk.Dec + ap.GetOrGenerate(cdc, simulation.SlashFractionDowntime, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.SlashFractionDowntime](r).(sdk.Dec) + }) + return v + }(r), + ), + nil, + nil, + ) + + fmt.Printf("Selected randomly generated slashing parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, slashingGenesis.Params)) + genesisState[slashing.ModuleName] = cdc.MustMarshalJSON(slashingGenesis) +} + +// GenStakingGenesisState generates a random GenesisState for staking +func GenStakingGenesisState( + cdc *codec.Codec, r *rand.Rand, accs []simulation.Account, amount, numAccs, numInitiallyBonded int64, + ap simulation.AppParams, genesisState map[string]json.RawMessage, +) staking.GenesisState { + + stakingGenesis := staking.NewGenesisState( + staking.NewParams( + func(r *rand.Rand) time.Duration { + var v time.Duration + ap.GetOrGenerate(cdc, simulation.UnbondingTime, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.UnbondingTime](r).(time.Duration) + }) + return v + }(r), + func(r *rand.Rand) uint16 { + var v uint16 + ap.GetOrGenerate(cdc, simulation.MaxValidators, &v, r, + func(r *rand.Rand) { + v = simulation.ModuleParamSimulator[simulation.MaxValidators](r).(uint16) + }) + return v + }(r), + 7, + sdk.DefaultBondDenom, + ), + nil, + nil, + ) + + var ( + validators []staking.Validator + delegations []staking.Delegation + ) + + valAddrs := make([]sdk.ValAddress, numInitiallyBonded) + for i := 0; i < int(numInitiallyBonded); i++ { + valAddr := sdk.ValAddress(accs[i].Address) + valAddrs[i] = valAddr + + validator := staking.NewValidator(valAddr, accs[i].PubKey, staking.Description{}) + validator.Tokens = sdk.NewInt(amount) + validator.DelegatorShares = sdk.NewDec(amount) + delegation := staking.NewDelegation(accs[i].Address, valAddr, sdk.NewDec(amount)) + validators = append(validators, validator) + delegations = append(delegations, delegation) + } + + stakingGenesis.Validators = validators + stakingGenesis.Delegations = delegations + + fmt.Printf("Selected randomly generated staking parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, stakingGenesis.Params)) + genesisState[staking.ModuleName] = cdc.MustMarshalJSON(stakingGenesis) + + return stakingGenesis +} + // GetSimulationLog unmarshals the KVPair's Value to the corresponding type based on the // each's module store key and the prefix bytes of the KVPair's key. func GetSimulationLog(storeName string, cdcA, cdcB *codec.Codec, kvA, kvB cmn.KVPair) (log string) { @@ -155,12 +612,6 @@ func DecodeDistributionStore(cdcA, cdcB *codec.Codec, kvA, kvB cmn.KVPair) strin // DecodeStakingStore unmarshals the KVPair's Value to the corresponding staking type func DecodeStakingStore(cdcA, cdcB *codec.Codec, kvA, kvB cmn.KVPair) string { switch { - case bytes.Equal(kvA.Key[:1], staking.PoolKey): - var poolA, poolB staking.Pool - cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &poolA) - cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &poolB) - return fmt.Sprintf("%v\n%v", poolA, poolB) - case bytes.Equal(kvA.Key[:1], staking.LastTotalPowerKey): var powerA, powerB sdk.Int cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &powerA) diff --git a/simapp/utils_test.go b/simapp/utils_test.go index 8f806760c0..b76189728e 100644 --- a/simapp/utils_test.go +++ b/simapp/utils_test.go @@ -40,6 +40,7 @@ func makeTestCodec() (cdc *codec.Codec) { distr.RegisterCodec(cdc) gov.RegisterCodec(cdc) staking.RegisterCodec(cdc) + supply.RegisterCodec(cdc) return } diff --git a/x/staking/alias.go b/x/staking/alias.go index 84515957a1..019fa02985 100644 --- a/x/staking/alias.go +++ b/x/staking/alias.go @@ -182,7 +182,6 @@ var ( // variable aliases ModuleCdc = types.ModuleCdc - PoolKey = types.PoolKey LastValidatorPowerKey = types.LastValidatorPowerKey LastTotalPowerKey = types.LastTotalPowerKey ValidatorsKey = types.ValidatorsKey diff --git a/x/staking/types/keys.go b/x/staking/types/keys.go index 233daa22b3..ce23e4fb85 100644 --- a/x/staking/types/keys.go +++ b/x/staking/types/keys.go @@ -27,8 +27,6 @@ const ( //nolint var ( // Keys for store prefixes - PoolKey = []byte{0x00} // key for the staking pools - // Last* values are constant during a block. LastValidatorPowerKey = []byte{0x11} // prefix for each key to a validator index, for bonded validators LastTotalPowerKey = []byte{0x12} // prefix for the total power