refactor!: extract `AppStateFn` out of simapp (backport #14977) (#14978)

Co-authored-by: Julien Robert <julien@rbrt.fr>
This commit is contained in:
mergify[bot] 2023-02-09 15:03:57 +00:00 committed by GitHub
parent a393336729
commit 6d2087ccf1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 40 deletions

View File

@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Improvements ### Improvements
* (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.
* (cli) [#14953](https://github.com/cosmos/cosmos-sdk/pull/14953) Enable profiling block replay during abci handshake with `--cpu-profile`. * (cli) [#14953](https://github.com/cosmos/cosmos-sdk/pull/14953) Enable profiling block replay during abci handshake with `--cpu-profile`.
* (store) [#14410](https://github.com/cosmos/cosmos-sdk/pull/14410) `rootmulti.Store.loadVersion` has validation to check if all the module stores' height is correct, it will error if any module store has incorrect height. * (store) [#14410](https://github.com/cosmos/cosmos-sdk/pull/14410) `rootmulti.Store.loadVersion` has validation to check if all the module stores' height is correct, it will error if any module store has incorrect height.
* (store) [#14189](https://github.com/cosmos/cosmos-sdk/pull/14189) Add config `iavl-lazy-loading` to enable lazy loading of iavl store, to improve start up time of archive nodes, add method `SetLazyLoading` to `CommitMultiStore` interface. * (store) [#14189](https://github.com/cosmos/cosmos-sdk/pull/14189) Add config `iavl-lazy-loading` to enable lazy loading of iavl store, to improve start up time of archive nodes, add method `SetLazyLoading` to `CommitMultiStore` interface.

View File

@ -1,7 +0,0 @@
package params
// Simulation parameter constants
const (
StakePerAccount = "stake_per_account"
InitiallyBondedValidators = "initially_bonded_validators"
)

View File

@ -49,7 +49,7 @@ func BenchmarkFullAppSimulation(b *testing.B) {
b, b,
os.Stdout, os.Stdout,
app.BaseApp, 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 simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config), simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(), BlockedAddresses(),
@ -104,7 +104,7 @@ func BenchmarkInvariants(b *testing.B) {
b, b,
os.Stdout, os.Stdout,
app.BaseApp, 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 simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config), simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(), BlockedAddresses(),

View File

@ -92,7 +92,7 @@ func TestFullAppSimulation(t *testing.T) {
t, t,
os.Stdout, os.Stdout,
app.BaseApp, 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 simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config), simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(), BlockedAddresses(),
@ -137,7 +137,7 @@ func TestAppImportExport(t *testing.T) {
t, t,
os.Stdout, os.Stdout,
app.BaseApp, 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 simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config), simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(), BlockedAddresses(),
@ -253,7 +253,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
t, t,
os.Stdout, os.Stdout,
app.BaseApp, 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 simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config), simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(), BlockedAddresses(),
@ -301,7 +301,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
t, t,
os.Stdout, os.Stdout,
newApp.BaseApp, 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 simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(newApp, newApp.AppCodec(), config), simtestutil.SimulationOperations(newApp, newApp.AppCodec(), config),
BlockedAddresses(), BlockedAddresses(),
@ -356,7 +356,7 @@ func TestAppStateDeterminism(t *testing.T) {
t, t,
os.Stdout, os.Stdout,
app.BaseApp, 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 simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config), simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(), BlockedAddresses(),

View File

@ -1,4 +1,4 @@
package simapp package sims
import ( import (
"encoding/json" "encoding/json"
@ -8,11 +8,10 @@ import (
"os" "os"
"time" "time"
"cosmossdk.io/math"
tmjson "github.com/tendermint/tendermint/libs/json" tmjson "github.com/tendermint/tendermint/libs/json"
tmtypes "github.com/tendermint/tendermint/types" tmtypes "github.com/tendermint/tendermint/types"
"cosmossdk.io/math"
simappparams "cosmossdk.io/simapp/params"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
@ -24,11 +23,21 @@ import (
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 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. // AppStateFn returns the initial application state using a genesis or the simulation parameters.
// It panics if the user provides files for both of them. // 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. // 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 { // genesisState is the default genesis state of the whole app.
return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config, 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) { ) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) {
if simcli.FlagGenesisTimeValue == 0 { if simcli.FlagGenesisTimeValue == 0 {
genesisTimestamp = simtypes.RandTimestamp(r) genesisTimestamp = simtypes.RandTimestamp(r)
@ -43,7 +52,10 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty
case config.GenesisFile != "": case config.GenesisFile != "":
// override the default chain-id from simapp to set it later to the config // 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 { if simcli.FlagGenesisTimeValue == 0 {
// use genesis timestamp if no custom timestamp is provided (i.e no random timestamp) // use genesis timestamp if no custom timestamp is provided (i.e no random timestamp)
@ -65,11 +77,11 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty
if err != nil { if err != nil {
panic(err) panic(err)
} }
appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams) appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState)
default: default:
appParams := make(simtypes.AppParams) 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) rawState := make(map[string]json.RawMessage)
@ -84,8 +96,7 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty
} }
stakingState := new(stakingtypes.GenesisState) stakingState := new(stakingtypes.GenesisState)
err = cdc.UnmarshalJSON(stakingStateBz, stakingState) if err = cdc.UnmarshalJSON(stakingStateBz, stakingState); err != nil {
if err != nil {
panic(err) panic(err)
} }
// compute not bonded balance // compute not bonded balance
@ -104,8 +115,7 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty
panic("bank genesis state is missing") panic("bank genesis state is missing")
} }
bankState := new(banktypes.GenesisState) bankState := new(banktypes.GenesisState)
err = cdc.UnmarshalJSON(bankStateBz, bankState) if err = cdc.UnmarshalJSON(bankStateBz, bankState); err != nil {
if err != nil {
panic(err) panic(err)
} }
@ -140,12 +150,15 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty
// AppStateRandomizedFn creates calls each module's GenesisState generator function // AppStateRandomizedFn creates calls each module's GenesisState generator function
// and creates the simulation params // and creates the simulation params
func AppStateRandomizedFn( func AppStateRandomizedFn(
simManager *module.SimulationManager, r *rand.Rand, cdc codec.JSONCodec, simManager *module.SimulationManager,
accs []simtypes.Account, genesisTimestamp time.Time, appParams simtypes.AppParams, r *rand.Rand,
cdc codec.JSONCodec,
accs []simtypes.Account,
genesisTimestamp time.Time,
appParams simtypes.AppParams,
genesisState map[string]json.RawMessage,
) (json.RawMessage, []simtypes.Account) { ) (json.RawMessage, []simtypes.Account) {
numAccs := int64(len(accs)) numAccs := int64(len(accs))
genesisState := ModuleBasics.DefaultGenesis(cdc)
// generate a random amount of initial stake coins and a random initial // generate a random amount of initial stake coins and a random initial
// number of bonded accounts // number of bonded accounts
var ( var (
@ -153,11 +166,11 @@ func AppStateRandomizedFn(
initialStake math.Int initialStake math.Int
) )
appParams.GetOrGenerate( appParams.GetOrGenerate(
cdc, simappparams.StakePerAccount, &initialStake, r, cdc, StakePerAccount, &initialStake, r,
func(r *rand.Rand) { initialStake = math.NewInt(r.Int63n(1e12)) }, func(r *rand.Rand) { initialStake = math.NewInt(r.Int63n(1e12)) },
) )
appParams.GetOrGenerate( appParams.GetOrGenerate(
cdc, simappparams.InitiallyBondedValidators, &numInitiallyBonded, r, cdc, InitiallyBondedValidators, &numInitiallyBonded, r,
func(r *rand.Rand) { numInitiallyBonded = int64(r.Intn(300)) }, func(r *rand.Rand) { numInitiallyBonded = int64(r.Intn(300)) },
) )
@ -197,7 +210,7 @@ func AppStateRandomizedFn(
// AppStateFromGenesisFileFn util function to generate the genesis AppState // AppStateFromGenesisFileFn util function to generate the genesis AppState
// from a genesis.json file. // from a genesis.json file.
func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile string) (tmtypes.GenesisDoc, []simtypes.Account) { func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile string) (tmtypes.GenesisDoc, []simtypes.Account, error) {
bytes, err := os.ReadFile(genesisFile) bytes, err := os.ReadFile(genesisFile)
if err != nil { if err != nil {
panic(err) panic(err)
@ -207,13 +220,12 @@ func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile str
// NOTE: Tendermint uses a custom JSON decoder for GenesisDoc // NOTE: Tendermint uses a custom JSON decoder for GenesisDoc
err = tmjson.Unmarshal(bytes, &genesis) err = tmjson.Unmarshal(bytes, &genesis)
if err != nil { if err != nil {
panic(err) return genesis, nil, err
} }
var appState GenesisState var appState map[string]json.RawMessage
err = json.Unmarshal(genesis.AppState, &appState) if err = json.Unmarshal(genesis.AppState, &appState); err != nil {
if err != nil { return genesis, nil, err
panic(err)
} }
var authGenesis authtypes.GenesisState var authGenesis authtypes.GenesisState
@ -235,7 +247,7 @@ func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile str
a, ok := acc.GetCachedValue().(authtypes.AccountI) a, ok := acc.GetCachedValue().(authtypes.AccountI)
if !ok { if !ok {
panic("expected account") return genesis, nil, fmt.Errorf("expected account")
} }
// create simulator accounts // create simulator accounts
@ -243,5 +255,5 @@ func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile str
newAccs[i] = simAcc newAccs[i] = simAcc
} }
return genesis, newAccs return genesis, newAccs, nil
} }