Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor!: extract AppStateFn out of simapp #14977

Merged
merged 7 commits into from
Feb 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### API Breaking Changes

* (simapp) [#14977](https://github.com/cosmos/cosmos-sdk/pull/14977) Move simulation helpers functions (`AppStateFn` and `AppStateRandomizedFn`) to `testutil/sims`. These takes an extra genesisState argument which is the default state of the app.
* (x/gov) [#14720](https://github.com/cosmos/cosmos-sdk/pull/14720) Add an expedited field in the gov v1 proposal and `MsgNewMsgProposal`.
* [#14847](https://github.com/cosmos/cosmos-sdk/pull/14847) App and ModuleManager methods `InitGenesis`, `ExportGenesis`, `BeginBlock` and `EndBlock` now also return an error.
* (simulation) [#14728](https://github.com/cosmos/cosmos-sdk/pull/14728) Rename the `ParamChanges` field to `LegacyParamChange` and `Contents` to `LegacyProposalContents` in `simulation.SimulationState`. Additionally it adds a `ProposalMsgs` field to `simulation.SimulationState`.
Expand Down
2 changes: 1 addition & 1 deletion crypto/keys/secp256k1/secp256k1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ Here are the specific versions used to generate the vectors.
github.com/cosmos/btcutil v1.0.5
github.com/cosmos/cosmos-sdk v0.46.8
*/
func generateKeyForCheckingConsistency() keyData {
var _ = func() keyData {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes golangci-lint happy.

priv := secp256k1.GenPrivKey()
encPriv := make([]byte, len(priv.Key)*2)
hex.Encode(encPriv, priv.Key)
Expand Down
2 changes: 1 addition & 1 deletion simapp/app_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func NewSimApp(
// For providing a custom a base account type add it below.
// By default the auth module uses authtypes.ProtoBaseAccount().
//
// func() authtypes.AccountI { return authtypes.ProtoBaseAccount() },
// func() sdk.AccountI { return authtypes.ProtoBaseAccount() },

//
// MINT
Expand Down
7 changes: 0 additions & 7 deletions simapp/params/params.go

This file was deleted.

4 changes: 2 additions & 2 deletions simapp/sim_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func BenchmarkFullAppSimulation(b *testing.B) {
b,
os.Stdout,
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(),
Expand Down Expand Up @@ -104,7 +104,7 @@ func BenchmarkInvariants(b *testing.B) {
b,
os.Stdout,
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(),
Expand Down
10 changes: 5 additions & 5 deletions simapp/sim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func TestFullAppSimulation(t *testing.T) {
t,
os.Stdout,
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(),
Expand Down Expand Up @@ -136,7 +136,7 @@ func TestAppImportExport(t *testing.T) {
t,
os.Stdout,
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(),
Expand Down Expand Up @@ -253,7 +253,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
t,
os.Stdout,
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(),
Expand Down Expand Up @@ -301,7 +301,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
t,
os.Stdout,
newApp.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(newApp, newApp.AppCodec(), config),
BlockedAddresses(),
Expand Down Expand Up @@ -356,7 +356,7 @@ func TestAppStateDeterminism(t *testing.T) {
t,
os.Stdout,
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(),
Expand Down
70 changes: 40 additions & 30 deletions simapp/state.go → testutil/sims/state_helpers.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package simapp
package sims

import (
"encoding/json"
Expand All @@ -8,12 +8,10 @@ import (
"os"
"time"

"cosmossdk.io/math"
cmtjson "github.com/cometbft/cometbft/libs/json"
cmttypes "github.com/cometbft/cometbft/types"

"cosmossdk.io/math"
simappparams "cosmossdk.io/simapp/params"

"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -25,11 +23,21 @@ import (
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

// Simulation parameter constants
const (
StakePerAccount = "stake_per_account"
InitiallyBondedValidators = "initially_bonded_validators"
)

// AppStateFn returns the initial application state using a genesis or the simulation parameters.
// It panics if the user provides files for both of them.
// If a file is not given for the genesis or the sim params, it creates a randomized one.
func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simtypes.AppStateFn {
return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config,
// genesisState is the default genesis state of the whole app.
func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager, genesisState map[string]json.RawMessage) simtypes.AppStateFn {
return func(
r *rand.Rand,
accs []simtypes.Account,
config simtypes.Config,
) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) {
if simcli.FlagGenesisTimeValue == 0 {
genesisTimestamp = simtypes.RandTimestamp(r)
Expand All @@ -44,7 +52,10 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty

case config.GenesisFile != "":
// override the default chain-id from simapp to set it later to the config
genesisDoc, accounts := AppStateFromGenesisFileFn(r, cdc, config.GenesisFile)
genesisDoc, accounts, err := AppStateFromGenesisFileFn(r, cdc, config.GenesisFile)
if err != nil {
panic(err)
}

if simcli.FlagGenesisTimeValue == 0 {
// use genesis timestamp if no custom timestamp is provided (i.e no random timestamp)
Expand All @@ -66,11 +77,11 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty
if err != nil {
panic(err)
}
appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams)
appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState)

default:
appParams := make(simtypes.AppParams)
appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams)
appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState)
}

rawState := make(map[string]json.RawMessage)
Expand All @@ -85,8 +96,7 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty
}

stakingState := new(stakingtypes.GenesisState)
err = cdc.UnmarshalJSON(stakingStateBz, stakingState)
if err != nil {
if err = cdc.UnmarshalJSON(stakingStateBz, stakingState); err != nil {
panic(err)
}
// compute not bonded balance
Expand All @@ -105,8 +115,7 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty
panic("bank genesis state is missing")
}
bankState := new(banktypes.GenesisState)
err = cdc.UnmarshalJSON(bankStateBz, bankState)
if err != nil {
if err = cdc.UnmarshalJSON(bankStateBz, bankState); err != nil {
panic(err)
}

Expand Down Expand Up @@ -141,24 +150,27 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty
// AppStateRandomizedFn creates calls each module's GenesisState generator function
// and creates the simulation params
func AppStateRandomizedFn(
simManager *module.SimulationManager, r *rand.Rand, cdc codec.JSONCodec,
accs []simtypes.Account, genesisTimestamp time.Time, appParams simtypes.AppParams,
simManager *module.SimulationManager,
r *rand.Rand,
cdc codec.JSONCodec,
accs []simtypes.Account,
genesisTimestamp time.Time,
appParams simtypes.AppParams,
genesisState map[string]json.RawMessage,
) (json.RawMessage, []simtypes.Account) {
numAccs := int64(len(accs))
genesisState := ModuleBasics.DefaultGenesis(cdc)

// generate a random amount of initial stake coins and a random initial
// number of bonded accounts
var (
numInitiallyBonded int64
initialStake math.Int
)
appParams.GetOrGenerate(
cdc, simappparams.StakePerAccount, &initialStake, r,
cdc, StakePerAccount, &initialStake, r,
func(r *rand.Rand) { initialStake = math.NewInt(r.Int63n(1e12)) },
)
appParams.GetOrGenerate(
cdc, simappparams.InitiallyBondedValidators, &numInitiallyBonded, r,
cdc, InitiallyBondedValidators, &numInitiallyBonded, r,
func(r *rand.Rand) { numInitiallyBonded = int64(r.Intn(300)) },
)

Expand Down Expand Up @@ -199,23 +211,21 @@ func AppStateRandomizedFn(

// AppStateFromGenesisFileFn util function to generate the genesis AppState
// from a genesis.json file.
func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile string) (cmttypes.GenesisDoc, []simtypes.Account) {
func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile string) (cmttypes.GenesisDoc, []simtypes.Account, error) {
bytes, err := os.ReadFile(genesisFile)
if err != nil {
panic(err)
}

var genesis cmttypes.GenesisDoc
// NOTE: CometBFT uses a custom JSON decoder for GenesisDoc
err = cmtjson.Unmarshal(bytes, &genesis)
if err != nil {
panic(err)
if err = cmtjson.Unmarshal(bytes, &genesis); err != nil {
return genesis, nil, err
}

var appState GenesisState
err = json.Unmarshal(genesis.AppState, &appState)
if err != nil {
panic(err)
var appState map[string]json.RawMessage
if err = json.Unmarshal(genesis.AppState, &appState); err != nil {
return genesis, nil, err
}

var authGenesis authtypes.GenesisState
Expand All @@ -235,15 +245,15 @@ func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile str

privKey := secp256k1.GenPrivKeyFromSecret(privkeySeed)

a, ok := acc.GetCachedValue().(authtypes.AccountI)
a, ok := acc.GetCachedValue().(sdk.AccountI)
if !ok {
panic("expected account")
return genesis, nil, fmt.Errorf("expected account")
}

// create simulator accounts
simAcc := simtypes.Account{PrivKey: privKey, PubKey: privKey.PubKey(), Address: a.GetAddress()}
newAccs[i] = simAcc
}

return genesis, newAccs
return genesis, newAccs, nil
}