Merge PR #4838: Sim refactor 2 - Move GenesisState generators to modules

This commit is contained in:
Federico Kunze 2019-08-28 16:58:25 +02:00 committed by Alexander Bezobchuk
parent a131570cdc
commit 45b25ceaae
58 changed files with 1778 additions and 1331 deletions

View File

@ -26,9 +26,9 @@ commands:
- go-src-v1-{{ .Revision }}
- checkout
- restore_cache:
name: "Restore go modules cache"
keys:
- go-mod-v2-{{ checksum "go.sum" }}
name: "Restore go modules cache"
keys:
- go-mod-v2-{{ checksum "go.sum" }}
- run:
name: << parameters.description >>
command: |
@ -40,7 +40,7 @@ jobs:
steps:
- checkout
- run:
Name : "Build docs"
name: "Build docs"
command: make build-docs
- run:
name: "Upload docs to S3"
@ -87,13 +87,6 @@ jobs:
- make:
target: test_sim_import_export
description: "Test application import/export simulation"
- run:
command: |
mkdir -p /tmp/errors
cp /tmp/**/app-simulation-seed* /tmp/errors/
when: on_fail
- store_artifacts:
path: /tmp/errors
test_sim_after_import:
executor: golang
@ -101,13 +94,6 @@ jobs:
- make:
target: test_sim_after_import
description: "Test simulation after import"
- run:
command: |
mkdir -p /tmp/errors
cp /tmp/**/app-simulation-seed* /tmp/errors/
when: on_fail
- store_artifacts:
path: /tmp/errors
test_sim_multi_seed_long:
executor: golang
@ -115,13 +101,6 @@ jobs:
- make:
target: test_sim_multi_seed_long
description: "Test multi-seed simulation (long)"
- run:
command: |
mkdir -p /tmp/errors
cp /tmp/**/app-simulation-seed* /tmp/errors/
when: on_fail
- store_artifacts:
path: /tmp/errors
test_sim_multi_seed_short:
executor: golang
@ -129,14 +108,6 @@ jobs:
- make:
target: test_sim_multi_seed_short
description: "Test multi-seed simulation (short)"
- run:
command: |
mkdir -p /tmp/errors
cp /tmp/**/app-simulation-seed* /tmp/errors/
when: on_fail
- store_artifacts:
path: /tmp/errors
test_cover:
executor: golang

View File

@ -61,9 +61,12 @@ longer panics if the store to load contains substores that we didn't explicitly
* (simulation) [\#4824](https://github.com/cosmos/cosmos-sdk/issues/4824) PrintAllInvariants flag will print all failed invariants
* (simulation) [\#4490](https://github.com/cosmos/cosmos-sdk/issues/4490) add `InitialBlockHeight` flag to resume a simulation from a given block
* Support exporting the simulation stats to a given JSON file
* (simulation) [\#4847](https://github.com/cosmos/cosmos-sdk/issues/4847) `SimApp` and simulation refactors
* (simulation) [\#4847](https://github.com/cosmos/cosmos-sdk/issues/4847), [\#4838](https://github.com/cosmos/cosmos-sdk/pull/4838) `SimApp` and simulation refactors
* Implement `SimulationManager` for executing modules' simulation functionalities in a modularized way
* Add `DecodeStore` to the `SimulationManager` for decoding each module's types
* Add `RegisterStoreDecoders` to the `SimulationManager` for decoding each module's types
* Add `GenerateGenesisStates` to the `SimulationManager` to generate a randomized `GenState` for each module
* Add `RandomizedParams` to the `SimulationManager` that registers each modules' parameters `Content` to simulate
`ParamChangeProposal`s
* (simulation) [\#4893](https://github.com/cosmos/cosmos-sdk/issues/4893) Change SimApp keepers to be public and add getter functions for keys and codec
* (simulation) [\#4906](https://github.com/cosmos/cosmos-sdk/issues/4906) Add simulation `Config` struct that wraps simulation flags
* (store) [\#4792](https://github.com/cosmos/cosmos-sdk/issues/4792) panic on non-registered store

View File

@ -105,7 +105,7 @@ test_race:
test_sim_nondeterminism:
@echo "Running non-determinism test..."
@go test -mod=readonly $(SIMAPP) -run TestAppStateDeterminism -Enabled=true \
-NumBlocks=100 -BlockSize=200 -Commit=true -v -timeout 24h
-NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h
test_sim_custom_genesis_fast:
@echo "Running custom genesis simulation..."

1
go.mod
View File

@ -6,7 +6,6 @@ require (
github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d
github.com/cosmos/go-bip39 v0.0.0-20180618194314-52158e4697b8
github.com/cosmos/ledger-cosmos-go v0.10.3
github.com/cosmos/tools v0.0.0-20190729191304-444fa9c55188 // indirect
github.com/fortytw2/leaktest v1.3.0 // indirect
github.com/gogo/protobuf v1.2.1
github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129

4
go.sum
View File

@ -33,10 +33,6 @@ github.com/cosmos/ledger-cosmos-go v0.10.3 h1:Qhi5yTR5Pg1CaTpd00pxlGwNl4sFRdtK1J
github.com/cosmos/ledger-cosmos-go v0.10.3/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY=
github.com/cosmos/ledger-go v0.9.2 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI=
github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI=
github.com/cosmos/tools v0.0.0-20190729191304-444fa9c55188 h1:KZsNQXLq7ZUURaBjVrztEqZX+d7qpjQkS4a0jbCMHIY=
github.com/cosmos/tools v0.0.0-20190729191304-444fa9c55188/go.mod h1:ycjJZ351OX/Y/DYgZqNn1WLCgpmVH7j29THN8vjbb9U=
github.com/cosmos/tools/cmd/clog v0.0.0-20190722180430-ea942c183cba h1:YhVnGzBkE2TvfBW5fAYBdNVK/3bwTPYVbMaOIGRHFRY=
github.com/cosmos/tools/cmd/clog v0.0.0-20190722180430-ea942c183cba/go.mod h1:TdPuAVaU2rc6K24ejr/AnGznt9Fd2qjtMoRrTO4uFrI=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=

View File

@ -184,9 +184,9 @@ func NewSimApp(
bank.NewAppModule(app.BankKeeper, app.AccountKeeper),
crisis.NewAppModule(&app.CrisisKeeper),
supply.NewAppModule(app.SupplyKeeper, app.AccountKeeper),
distr.NewAppModule(app.DistrKeeper, app.SupplyKeeper),
gov.NewAppModule(app.GovKeeper, app.SupplyKeeper),
mint.NewAppModule(app.MintKeeper),
distr.NewAppModule(app.DistrKeeper, app.SupplyKeeper),
slashing.NewAppModule(app.SlashingKeeper, app.StakingKeeper),
staking.NewAppModule(app.StakingKeeper, app.AccountKeeper, app.SupplyKeeper),
nft.NewAppModule(app.NFTKeeper),
@ -204,13 +204,30 @@ func NewSimApp(
app.mm.SetOrderInitGenesis(
genaccounts.ModuleName, distr.ModuleName, staking.ModuleName,
auth.ModuleName, bank.ModuleName, slashing.ModuleName, gov.ModuleName,
mint.ModuleName, supply.ModuleName, crisis.ModuleName, genutil.ModuleName,
mint.ModuleName, supply.ModuleName, crisis.ModuleName, nft.ModuleName,
genutil.ModuleName,
)
app.mm.RegisterInvariants(&app.CrisisKeeper)
app.mm.RegisterRoutes(app.Router(), app.QueryRouter())
app.sm = module.NewSimulationManager(app.mm.Modules)
// create the simulation manager and define the order of the modules for deterministic simulations
//
// NOTE: this is not required apps that don't use the simulator for fuzz testing
// transactions
app.sm = module.NewSimulationManager(
genaccounts.NewAppModule(app.AccountKeeper),
auth.NewAppModule(app.AccountKeeper),
bank.NewAppModule(app.BankKeeper, app.AccountKeeper),
supply.NewAppModule(app.SupplyKeeper, app.AccountKeeper),
gov.NewAppModule(app.GovKeeper, app.SupplyKeeper),
mint.NewAppModule(app.MintKeeper),
distr.NewAppModule(app.DistrKeeper, app.SupplyKeeper),
staking.NewAppModule(app.StakingKeeper, app.AccountKeeper, app.SupplyKeeper),
slashing.NewAppModule(app.SlashingKeeper, app.StakingKeeper),
// nft.NewAppModule(app.NFTKeeper),
)
app.sm.RegisterStoreDecoders()
// initialize stores

View File

@ -1,121 +0,0 @@
/*
Package simapp implements a full fledged Cosmos SDK application used for executing
simulation test suites.
Simulation App
The SimApp type defines an application used for running extensive simulation
testing suites. It contains all core modules, including governance, staking,
slashing, and distribution.
Simulation is executed with various inputs including the number of blocks to
simulate, the block size, whether the app should commit or not, the invariant
checking period, and a seed which is used as a source of pseudo-randomness.
In addition to the various inputs, simulation runs mainly in three modes:
1. Completely random where the initial state, module parameters and simulation
parameters are pseudo-randomly generated.
2. From a genesis file where the initial state and the module parameters are defined.
This mode is helpful for running simulations on a known state such as a live
network export where a new (mostly likely breaking) version of the application
needs to be tested.
3. From a params file where the initial state is pseudo-randomly generated but the
module and simulation parameters can be provided manually. This allows for a more
controlled and deterministic simulation setup while allowing the state space to
still be pseudo-randomly simulated.
The simulation test suite also supports testing determinism and import/export
functionality.
Randomness
Currently, simulation uses a single seed (integer) as a source for a PRNG by
which all random operations are executed from. Any call to the PRNG changes all
future operations as the internal state of the PRNG is modified. For example,
if a new message type is created and needs to be simulated, the new introduced
PRNG call will change all subsequent operations.
This may can often be problematic when testing fixes to simulation faults. One
current solution to this is to use a params file as mentioned above. In the future
the simulation suite is expected to support a series of PRNGs that can be used
uniquely per module and simulation component so that they will not effect each
others state execution outcome.
Usage
To execute a completely pseudo-random simulation:
$ go test -mod=readonly github.com/cosmos/cosmos-sdk/simapp \
-run=TestFullAppSimulation \
-Enabled=true \
-NumBlocks=100 \
-BlockSize=200 \
-Commit=true \
-Seed=99 \
-Period=5 \
-v -timeout 24h
To execute simulation from a genesis file:
$ go test -mod=readonly github.com/cosmos/cosmos-sdk/simapp \
-run=TestFullAppSimulation \
-Enabled=true \
-NumBlocks=100 \
-BlockSize=200 \
-Commit=true \
-Seed=99 \
-Period=5 \
-Genesis=/path/to/genesis.json \
-v -timeout 24h
To execute simulation from a simulation params file:
$ go test -mod=readonly github.com/cosmos/cosmos-sdk/simapp \
-run=TestFullAppSimulation \
-Enabled=true \
-NumBlocks=100 \
-BlockSize=200 \
-Commit=true \
-Seed=99 \
-Period=5 \
-Params=/path/to/params.json \
-v -timeout 24h
To export the simulation params to a file at a given block height:
$ go test -mod=readonly github.com/cosmos/cosmos-sdk/simapp \
-run=TestFullAppSimulation \
-Enabled=true \
-NumBlocks=100 \
-BlockSize=200 \
-Commit=true \
-Seed=99 \
-Period=5 \
-ExportParamsPath=/path/to/params.json \
-ExportParamsHeight=50 \
-v -timeout 24h
To export the simulation app state (i.e genesis) to a file:
$ go test -mod=readonly github.com/cosmos/cosmos-sdk/simapp \
-run=TestFullAppSimulation \
-Enabled=true \
-NumBlocks=100 \
-BlockSize=200 \
-Commit=true \
-Seed=99 \
-Period=5 \
-ExportStatePath=/path/to/genesis.json \
v -timeout 24h
Params
Params that are provided to simulation from a JSON file are used to used to set
both module parameters and simulation parameters. See sim_test.go for the full
set of parameters that can be provided.
*/
package simapp

View File

@ -24,7 +24,6 @@ import (
"github.com/cosmos/cosmos-sdk/x/gov"
govsimops "github.com/cosmos/cosmos-sdk/x/gov/simulation/operations"
"github.com/cosmos/cosmos-sdk/x/mint"
nftsimops "github.com/cosmos/cosmos-sdk/x/nft/simulation/operations"
"github.com/cosmos/cosmos-sdk/x/params"
paramsimops "github.com/cosmos/cosmos-sdk/x/params/simulation/operations"
"github.com/cosmos/cosmos-sdk/x/simulation"
@ -35,23 +34,24 @@ import (
"github.com/cosmos/cosmos-sdk/x/supply"
)
// Get flags every time the simulator is run
func init() {
GetSimulatorFlags()
}
// TODO: add description
func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedOperation {
cdc := MakeCodec()
ap := make(simulation.AppParams)
paramChanges := app.sm.GenerateParamChanges(config.Seed)
if config.ParamsFile != "" {
bz, err := ioutil.ReadFile(config.ParamsFile)
if err != nil {
panic(err)
}
cdc.MustUnmarshalJSON(bz, &ap)
app.cdc.MustUnmarshalJSON(bz, &ap)
}
// nolint: govet
@ -59,7 +59,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightDeductFee, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightDeductFee, &v, nil,
func(_ *rand.Rand) {
v = 5
})
@ -70,7 +70,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightMsgSend, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightMsgSend, &v, nil,
func(_ *rand.Rand) {
v = 100
})
@ -81,7 +81,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightSingleInputMsgMultiSend, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightSingleInputMsgMultiSend, &v, nil,
func(_ *rand.Rand) {
v = 10
})
@ -92,7 +92,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightMsgSetWithdrawAddress, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightMsgSetWithdrawAddress, &v, nil,
func(_ *rand.Rand) {
v = 50
})
@ -103,7 +103,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightMsgWithdrawDelegationReward, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightMsgWithdrawDelegationReward, &v, nil,
func(_ *rand.Rand) {
v = 50
})
@ -114,7 +114,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightMsgWithdrawValidatorCommission, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightMsgWithdrawValidatorCommission, &v, nil,
func(_ *rand.Rand) {
v = 50
})
@ -125,7 +125,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightSubmitVotingSlashingTextProposal, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightSubmitVotingSlashingTextProposal, &v, nil,
func(_ *rand.Rand) {
v = 5
})
@ -136,7 +136,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightSubmitVotingSlashingCommunitySpendProposal, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightSubmitVotingSlashingCommunitySpendProposal, &v, nil,
func(_ *rand.Rand) {
v = 5
})
@ -147,18 +147,18 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightSubmitVotingSlashingParamChangeProposal, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightSubmitVotingSlashingParamChangeProposal, &v, nil,
func(_ *rand.Rand) {
v = 5
})
return v
}(nil),
govsimops.SimulateSubmittingVotingAndSlashingForProposal(app.GovKeeper, paramsimops.SimulateParamChangeProposalContent),
govsimops.SimulateSubmittingVotingAndSlashingForProposal(app.GovKeeper, paramsimops.SimulateParamChangeProposalContent(paramChanges)),
},
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightMsgDeposit, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightMsgDeposit, &v, nil,
func(_ *rand.Rand) {
v = 100
})
@ -169,7 +169,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightMsgCreateValidator, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightMsgCreateValidator, &v, nil,
func(_ *rand.Rand) {
v = 100
})
@ -180,7 +180,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightMsgEditValidator, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightMsgEditValidator, &v, nil,
func(_ *rand.Rand) {
v = 5
})
@ -191,7 +191,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightMsgDelegate, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightMsgDelegate, &v, nil,
func(_ *rand.Rand) {
v = 100
})
@ -202,7 +202,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightMsgUndelegate, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightMsgUndelegate, &v, nil,
func(_ *rand.Rand) {
v = 100
})
@ -213,7 +213,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightMsgBeginRedelegate, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightMsgBeginRedelegate, &v, nil,
func(_ *rand.Rand) {
v = 100
})
@ -224,7 +224,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightMsgUnjail, &v, nil,
ap.GetOrGenerate(app.cdc, OpWeightMsgUnjail, &v, nil,
func(_ *rand.Rand) {
v = 100
})
@ -232,50 +232,50 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
}(nil),
slashingsimops.SimulateMsgUnjail(app.SlashingKeeper),
},
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightMsgTransferNFT, &v, nil,
func(_ *rand.Rand) {
v = 100
})
return v
}(nil),
nftsimops.SimulateMsgTransferNFT(app.NFTKeeper),
},
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightMsgEditNFTMetadata, &v, nil,
func(_ *rand.Rand) {
v = 100
})
return v
}(nil),
nftsimops.SimulateMsgEditNFTMetadata(app.NFTKeeper),
},
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightMsgMintNFT, &v, nil,
func(_ *rand.Rand) {
v = 100
})
return v
}(nil),
nftsimops.SimulateMsgMintNFT(app.NFTKeeper),
},
{
func(_ *rand.Rand) int {
var v int
ap.GetOrGenerate(cdc, OpWeightMsgBurnNFT, &v, nil,
func(_ *rand.Rand) {
v = 100
})
return v
}(nil),
nftsimops.SimulateMsgBurnNFT(app.NFTKeeper),
},
// {
// func(_ *rand.Rand) int {
// var v int
// ap.GetOrGenerate(app.cdc, OpWeightMsgTransferNFT, &v, nil,
// func(_ *rand.Rand) {
// v = 33
// })
// return v
// }(nil),
// nftsimops.SimulateMsgTransferNFT(app.NFTKeeper),
// },
// {
// func(_ *rand.Rand) int {
// var v int
// ap.GetOrGenerate(app.cdc, OpWeightMsgEditNFTMetadata, &v, nil,
// func(_ *rand.Rand) {
// v = 5
// })
// return v
// }(nil),
// nftsimops.SimulateMsgEditNFTMetadata(app.NFTKeeper),
// },
// {
// func(_ *rand.Rand) int {
// var v int
// ap.GetOrGenerate(app.cdc, OpWeightMsgMintNFT, &v, nil,
// func(_ *rand.Rand) {
// v = 10
// })
// return v
// }(nil),
// nftsimops.SimulateMsgMintNFT(app.NFTKeeper),
// },
// {
// func(_ *rand.Rand) int {
// var v int
// ap.GetOrGenerate(app.cdc, OpWeightMsgBurnNFT, &v, nil,
// func(_ *rand.Rand) {
// v = 5
// })
// return v
// }(nil),
// nftsimops.SimulateMsgBurnNFT(app.NFTKeeper),
// },
}
}
@ -310,37 +310,22 @@ func BenchmarkFullAppSimulation(b *testing.B) {
// Run randomized simulation
// TODO: parameterize numbers, save for a later PR
_, params, simErr := simulation.SimulateFromSeed(
b, os.Stdout, app.BaseApp, AppStateFn,
_, simParams, simErr := simulation.SimulateFromSeed(
b, os.Stdout, app.BaseApp, AppStateFn(app.Codec(), app.sm),
testAndRunTxs(app, config), invariants(app),
app.ModuleAccountAddrs(), config,
)
// export state and params before the simulation error is checked
if config.ExportStatePath != "" {
fmt.Println("Exporting app state...")
appState, _, err := app.ExportAppStateAndValidators(false, nil)
if err != nil {
fmt.Println(err)
b.Fail()
}
err = ioutil.WriteFile(config.ExportStatePath, []byte(appState), 0644)
if err != nil {
if err := ExportStateToJSON(app, config.ExportStatePath); err != nil {
fmt.Println(err)
b.Fail()
}
}
if config.ExportParamsPath != "" {
fmt.Println("Exporting simulation params...")
paramsBz, err := json.MarshalIndent(params, "", " ")
if err != nil {
fmt.Println(err)
b.Fail()
}
err = ioutil.WriteFile(config.ExportParamsPath, paramsBz, 0644)
if err != nil {
if err := ExportParamsToJSON(simParams, config.ExportParamsPath); err != nil {
fmt.Println(err)
b.Fail()
}
@ -360,71 +345,7 @@ func BenchmarkFullAppSimulation(b *testing.B) {
func TestFullAppSimulation(t *testing.T) {
if !flagEnabledValue {
t.Skip("Skipping application simulation")
}
var logger log.Logger
config := NewConfigFromFlags()
if flagVerboseValue {
logger = log.TestingLogger()
} else {
logger = log.NewNopLogger()
}
var db dbm.DB
dir, _ := ioutil.TempDir("", "goleveldb-app-sim")
db, _ = sdk.NewLevelDB("Simulation", dir)
defer func() {
db.Close()
os.RemoveAll(dir)
}()
app := NewSimApp(logger, db, nil, true, 0, fauxMerkleModeOpt)
require.Equal(t, "SimApp", app.Name())
// Run randomized simulation
_, params, simErr := simulation.SimulateFromSeed(
t, os.Stdout, app.BaseApp, AppStateFn,
testAndRunTxs(app, config), invariants(app),
app.ModuleAccountAddrs(), config,
)
// export state and params before the simulation error is checked
if config.ExportStatePath != "" {
fmt.Println("Exporting app state...")
appState, _, err := app.ExportAppStateAndValidators(false, nil)
require.NoError(t, err)
err = ioutil.WriteFile(config.ExportStatePath, []byte(appState), 0644)
require.NoError(t, err)
}
if config.ExportParamsPath != "" {
fmt.Println("Exporting simulation params...")
fmt.Println(params)
paramsBz, err := json.MarshalIndent(params, "", " ")
require.NoError(t, err)
err = ioutil.WriteFile(config.ExportParamsPath, paramsBz, 0644)
require.NoError(t, err)
}
require.NoError(t, simErr)
if config.Commit {
// for memdb:
// fmt.Println("Database Size", db.Stats()["database.size"])
fmt.Println("\nGoLevelDB Stats")
fmt.Println(db.Stats()["leveldb.stats"])
fmt.Println("GoLevelDB cached block size", db.Stats()["leveldb.cachedblock"])
}
}
func TestAppImportExport(t *testing.T) {
if !flagEnabledValue {
t.Skip("Skipping application import/export simulation")
t.Skip("skipping application simulation")
}
var logger log.Logger
@ -450,27 +371,74 @@ func TestAppImportExport(t *testing.T) {
// Run randomized simulation
_, simParams, simErr := simulation.SimulateFromSeed(
t, os.Stdout, app.BaseApp, AppStateFn,
t, os.Stdout, app.BaseApp, AppStateFn(app.Codec(), app.sm),
testAndRunTxs(app, config), invariants(app),
app.ModuleAccountAddrs(), config,
)
// export state and params before the simulation error is checked
if config.ExportStatePath != "" {
err := ExportStateToJSON(app, config.ExportStatePath)
require.NoError(t, err)
}
if config.ExportParamsPath != "" {
err := ExportParamsToJSON(simParams, config.ExportParamsPath)
require.NoError(t, err)
}
require.NoError(t, simErr)
if config.Commit {
// for memdb:
// fmt.Println("Database Size", db.Stats()["database.size"])
fmt.Println("\nGoLevelDB Stats")
fmt.Println(db.Stats()["leveldb.stats"])
fmt.Println("GoLevelDB cached block size", db.Stats()["leveldb.cachedblock"])
}
}
func TestAppImportExport(t *testing.T) {
if !flagEnabledValue {
t.Skip("skipping application import/export simulation")
}
var logger log.Logger
config := NewConfigFromFlags()
if flagVerboseValue {
logger = log.TestingLogger()
} else {
logger = log.NewNopLogger()
}
var db dbm.DB
dir, _ := ioutil.TempDir("", "goleveldb-app-sim")
db, _ = sdk.NewLevelDB("Simulation", dir)
defer func() {
db.Close()
os.RemoveAll(dir)
}()
app := NewSimApp(logger, db, nil, true, 0, fauxMerkleModeOpt)
require.Equal(t, "SimApp", app.Name())
// Run randomized simulation
_, simParams, simErr := simulation.SimulateFromSeed(
t, os.Stdout, app.BaseApp, AppStateFn(app.Codec(), app.sm),
testAndRunTxs(app, config), invariants(app),
app.ModuleAccountAddrs(), config,
)
// export state and simParams before the simulation error is checked
if config.ExportStatePath != "" {
fmt.Println("Exporting app state...")
appState, _, err := app.ExportAppStateAndValidators(false, nil)
require.NoError(t, err)
err = ioutil.WriteFile(config.ExportStatePath, []byte(appState), 0644)
err := ExportStateToJSON(app, config.ExportStatePath)
require.NoError(t, err)
}
if config.ExportParamsPath != "" {
fmt.Println("Exporting simulation params...")
simParamsBz, err := json.MarshalIndent(simParams, "", " ")
require.NoError(t, err)
err = ioutil.WriteFile(config.ExportParamsPath, simParamsBz, 0644)
err := ExportParamsToJSON(simParams, config.ExportParamsPath)
require.NoError(t, err)
}
@ -484,11 +452,11 @@ func TestAppImportExport(t *testing.T) {
fmt.Println("GoLevelDB cached block size", db.Stats()["leveldb.cachedblock"])
}
fmt.Printf("Exporting genesis...\n")
fmt.Printf("exporting genesis...\n")
appState, _, err := app.ExportAppStateAndValidators(false, []string{})
require.NoError(t, err)
fmt.Printf("Importing genesis...\n")
fmt.Printf("importing genesis...\n")
newDir, _ := ioutil.TempDir("", "goleveldb-app-sim-2")
newDB, _ := sdk.NewLevelDB("Simulation-2", dir)
@ -508,7 +476,7 @@ func TestAppImportExport(t *testing.T) {
ctxB := newApp.NewContext(true, abci.Header{Height: app.LastBlockHeight()})
newApp.mm.InitGenesis(ctxB, genesisState)
fmt.Printf("Comparing stores...\n")
fmt.Printf("comparing stores...\n")
ctxA := app.NewContext(true, abci.Header{Height: app.LastBlockHeight()})
type StoreKeysPrefixes struct {
@ -543,7 +511,7 @@ func TestAppImportExport(t *testing.T) {
failedKVAs, failedKVBs := sdk.DiffKVStores(storeA, storeB, prefixes)
require.Equal(t, len(failedKVAs), len(failedKVBs), "unequal sets of key-values to compare")
fmt.Printf("Compared %d key/value pairs between %s and %s\n", len(failedKVAs), storeKeyA, storeKeyB)
fmt.Printf("compared %d key/value pairs between %s and %s\n", len(failedKVAs), storeKeyA, storeKeyB)
require.Len(t, failedKVAs, 0, GetSimulationLog(storeKeyA.Name(), app.sm.StoreDecoders, app.cdc, failedKVAs, failedKVBs))
}
@ -551,7 +519,7 @@ func TestAppImportExport(t *testing.T) {
func TestAppSimulationAfterImport(t *testing.T) {
if !flagEnabledValue {
t.Skip("Skipping application simulation after import")
t.Skip("skipping application simulation after import")
}
var logger log.Logger
@ -575,28 +543,20 @@ func TestAppSimulationAfterImport(t *testing.T) {
require.Equal(t, "SimApp", app.Name())
// Run randomized simulation
stopEarly, params, simErr := simulation.SimulateFromSeed(
t, os.Stdout, app.BaseApp, AppStateFn,
stopEarly, simParams, simErr := simulation.SimulateFromSeed(
t, os.Stdout, app.BaseApp, AppStateFn(app.Codec(), app.sm),
testAndRunTxs(app, config), invariants(app),
app.ModuleAccountAddrs(), config,
)
// export state and params before the simulation error is checked
if config.ExportStatePath != "" {
fmt.Println("Exporting app state...")
appState, _, err := app.ExportAppStateAndValidators(false, nil)
require.NoError(t, err)
err = ioutil.WriteFile(config.ExportStatePath, []byte(appState), 0644)
err := ExportStateToJSON(app, config.ExportStatePath)
require.NoError(t, err)
}
if config.ExportParamsPath != "" {
fmt.Println("Exporting simulation params...")
paramsBz, err := json.MarshalIndent(params, "", " ")
require.NoError(t, err)
err = ioutil.WriteFile(config.ExportParamsPath, paramsBz, 0644)
err := ExportParamsToJSON(simParams, config.ExportParamsPath)
require.NoError(t, err)
}
@ -612,16 +572,16 @@ func TestAppSimulationAfterImport(t *testing.T) {
if stopEarly {
// we can't export or import a zero-validator genesis
fmt.Printf("We can't export or import a zero-validator genesis, exiting test...\n")
fmt.Printf("we can't export or import a zero-validator genesis, exiting test...\n")
return
}
fmt.Printf("Exporting genesis...\n")
fmt.Printf("exporting genesis...\n")
appState, _, err := app.ExportAppStateAndValidators(true, []string{})
require.NoError(t, err)
fmt.Printf("Importing genesis...\n")
fmt.Printf("importing genesis...\n")
newDir, _ := ioutil.TempDir("", "goleveldb-app-sim-2")
newDB, _ := sdk.NewLevelDB("Simulation-2", dir)
@ -639,7 +599,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
// Run randomized simulation on imported app
_, _, err = simulation.SimulateFromSeed(
t, os.Stdout, newApp.BaseApp, AppStateFn,
t, os.Stdout, newApp.BaseApp, AppStateFn(app.Codec(), app.sm),
testAndRunTxs(newApp, config), invariants(newApp),
newApp.ModuleAccountAddrs(), config,
)
@ -651,7 +611,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
// and doesn't depend on the application.
func TestAppStateDeterminism(t *testing.T) {
if !flagEnabledValue {
t.Skip("Skipping application simulation")
t.Skip("skipping application simulation")
}
config := NewConfigFromFlags()
@ -673,12 +633,12 @@ func TestAppStateDeterminism(t *testing.T) {
app := NewSimApp(logger, db, nil, true, 0)
fmt.Printf(
"Running non-determinism simulation; seed: %d/%d (%d), attempt: %d/%d\n",
i+1, numSeeds, config.Seed, j+1, numTimesToRunPerSeed,
"running non-determinism simulation; seed %d: %d/%d, attempt: %d/%d\n",
config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed,
)
_, _, err := simulation.SimulateFromSeed(
t, os.Stdout, app.BaseApp, AppStateFn,
t, os.Stdout, app.BaseApp, AppStateFn(app.Codec(), app.sm),
testAndRunTxs(app, config), []sdk.Invariant{},
app.ModuleAccountAddrs(), config,
)
@ -688,7 +648,10 @@ func TestAppStateDeterminism(t *testing.T) {
appHashList[j] = appHash
if j != 0 {
require.Equal(t, appHashList[0], appHashList[j], "appHash list: %v", appHashList)
require.Equal(
t, appHashList[0], appHashList[j],
"non-determinism in seed %d: %d/%d, attempt: %d/%d\n", config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed,
)
}
}
}
@ -696,7 +659,9 @@ func TestAppStateDeterminism(t *testing.T) {
func BenchmarkInvariants(b *testing.B) {
logger := log.NewNopLogger()
config := NewConfigFromFlags()
config.AllInvariants = false
dir, _ := ioutil.TempDir("", "goleveldb-app-invariant-bench")
db, _ := sdk.NewLevelDB("simulation", dir)
@ -709,37 +674,22 @@ func BenchmarkInvariants(b *testing.B) {
app := NewSimApp(logger, db, nil, true, 0)
// 2. Run parameterized simulation (w/o invariants)
_, params, simErr := simulation.SimulateFromSeed(
b, ioutil.Discard, app.BaseApp, AppStateFn,
_, simParams, simErr := simulation.SimulateFromSeed(
b, ioutil.Discard, app.BaseApp, AppStateFn(app.Codec(), app.sm),
testAndRunTxs(app, config), []sdk.Invariant{},
app.ModuleAccountAddrs(), config,
)
// export state and params before the simulation error is checked
if config.ExportStatePath != "" {
fmt.Println("Exporting app state...")
appState, _, err := app.ExportAppStateAndValidators(false, nil)
if err != nil {
fmt.Println(err)
b.Fail()
}
err = ioutil.WriteFile(config.ExportStatePath, []byte(appState), 0644)
if err != nil {
if err := ExportStateToJSON(app, config.ExportStatePath); err != nil {
fmt.Println(err)
b.Fail()
}
}
if config.ExportParamsPath != "" {
fmt.Println("Exporting simulation params...")
paramsBz, err := json.MarshalIndent(params, "", " ")
if err != nil {
fmt.Println(err)
b.Fail()
}
err = ioutil.WriteFile(config.ExportParamsPath, paramsBz, 0644)
if err != nil {
if err := ExportParamsToJSON(simParams, config.ExportParamsPath); err != nil {
fmt.Println(err)
b.Fail()
}

View File

@ -1,7 +1,5 @@
package simapp
// DONTCOVER
import (
"encoding/json"
"fmt"
@ -12,71 +10,72 @@ import (
"github.com/tendermint/tendermint/crypto/secp256k1"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/genaccounts"
nftsim "github.com/cosmos/cosmos-sdk/x/nft/simulation"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
// 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(
r *rand.Rand, accs []simulation.Account, config simulation.Config,
) (appState json.RawMessage, simAccs []simulation.Account, chainID string, genesisTimestamp time.Time) {
func AppStateFn(cdc *codec.Codec, simManager *module.SimulationManager) simulation.AppStateFn {
return func(r *rand.Rand, accs []simulation.Account, config simulation.Config,
) (appState json.RawMessage, simAccs []simulation.Account, chainID string, genesisTimestamp time.Time) {
cdc := MakeCodec()
if flagGenesisTimeValue == 0 {
genesisTimestamp = simulation.RandTimestamp(r)
} else {
genesisTimestamp = time.Unix(flagGenesisTimeValue, 0)
}
switch {
case config.ParamsFile != "" && config.GenesisFile != "":
panic("cannot provide both a genesis file and a params file")
case config.GenesisFile != "":
appState, simAccs, chainID = AppStateFromGenesisFileFn(r, config)
case config.ParamsFile != "":
appParams := make(simulation.AppParams)
bz, err := ioutil.ReadFile(config.ParamsFile)
if err != nil {
panic(err)
if flagGenesisTimeValue == 0 {
genesisTimestamp = simulation.RandTimestamp(r)
} else {
genesisTimestamp = time.Unix(flagGenesisTimeValue, 0)
}
cdc.MustUnmarshalJSON(bz, &appParams)
appState, simAccs, chainID = AppStateRandomizedFn(r, accs, genesisTimestamp, appParams)
switch {
case config.ParamsFile != "" && config.GenesisFile != "":
panic("cannot provide both a genesis file and a params file")
default:
appParams := make(simulation.AppParams)
appState, simAccs, chainID = AppStateRandomizedFn(r, accs, genesisTimestamp, appParams)
case config.GenesisFile != "":
appState, simAccs, chainID = AppStateFromGenesisFileFn(r, cdc, config.GenesisFile)
case config.ParamsFile != "":
appParams := make(simulation.AppParams)
bz, err := ioutil.ReadFile(config.ParamsFile)
if err != nil {
panic(err)
}
cdc.MustUnmarshalJSON(bz, &appParams)
appState, simAccs, chainID = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams)
default:
appParams := make(simulation.AppParams)
appState, simAccs, chainID = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams)
}
return appState, simAccs, chainID, genesisTimestamp
}
return appState, simAccs, chainID, genesisTimestamp
}
// AppStateRandomizedFn creates calls each module's GenesisState generator function
// and creates
// and creates the simulation params
func AppStateRandomizedFn(
r *rand.Rand, accs []simulation.Account, genesisTimestamp time.Time, appParams simulation.AppParams,
simManager *module.SimulationManager, r *rand.Rand, cdc *codec.Codec,
accs []simulation.Account, genesisTimestamp time.Time, appParams simulation.AppParams,
) (json.RawMessage, []simulation.Account, string) {
cdc := MakeCodec()
numAccs := int64(len(accs))
genesisState := NewDefaultGenesisState()
var (
amount int64
numInitiallyBonded int64
// generate a random amount of initial stake coins and a random initial
// number of bonded accounts
var initialStake, numInitiallyBonded int64
appParams.GetOrGenerate(
cdc, StakePerAccount, &initialStake, r,
func(r *rand.Rand) { initialStake = int64(r.Intn(1e12)) },
)
appParams.GetOrGenerate(
cdc, InitiallyBondedValidators, &numInitiallyBonded, r,
func(r *rand.Rand) { numInitiallyBonded = int64(r.Intn(250)) },
)
appParams.GetOrGenerate(cdc, StakePerAccount, &amount, r,
func(r *rand.Rand) { amount = int64(r.Intn(1e12)) })
appParams.GetOrGenerate(cdc, InitiallyBondedValidators, &amount, r,
func(r *rand.Rand) { numInitiallyBonded = int64(r.Intn(250)) })
numAccs := int64(len(accs))
if numInitiallyBonded > numAccs {
numInitiallyBonded = numAccs
}
@ -84,24 +83,26 @@ func AppStateRandomizedFn(
fmt.Printf(
`Selected randomly generated parameters for simulated genesis:
{
stake_per_account: "%v",
initially_bonded_validators: "%v"
stake_per_account: "%d",
initially_bonded_validators: "%d"
}
`, amount, numInitiallyBonded,
`, initialStake, numInitiallyBonded,
)
GenGenesisAccounts(cdc, r, accs, genesisTimestamp, amount, numInitiallyBonded, genesisState)
GenAuthGenesisState(cdc, r, appParams, genesisState)
GenBankGenesisState(cdc, r, appParams, genesisState)
GenSupplyGenesisState(cdc, amount, numInitiallyBonded, int64(len(accs)), genesisState)
GenGovGenesisState(cdc, r, appParams, genesisState)
GenMintGenesisState(cdc, r, appParams, genesisState)
nftsim.GenNFTGenesisState(cdc, r, accs, appParams, genesisState)
GenDistrGenesisState(cdc, r, appParams, genesisState)
stakingGen := GenStakingGenesisState(cdc, r, accs, amount, numAccs, numInitiallyBonded, appParams, genesisState)
GenSlashingGenesisState(cdc, r, stakingGen, appParams, genesisState)
simState := &module.SimulationState{
AppParams: appParams,
Cdc: cdc,
Rand: r,
GenState: genesisState,
Accounts: accs,
InitialStake: initialStake,
NumBonded: numInitiallyBonded,
GenTimestamp: genesisTimestamp,
}
appState, err := MakeCodec().MarshalJSON(genesisState)
simManager.GenerateGenesisStates(simState)
appState, err := cdc.MarshalJSON(genesisState)
if err != nil {
panic(err)
}
@ -111,16 +112,15 @@ func AppStateRandomizedFn(
// AppStateFromGenesisFileFn util function to generate the genesis AppState
// from a genesis.json file
func AppStateFromGenesisFileFn(r *rand.Rand, config simulation.Config) (json.RawMessage, []simulation.Account, string) {
func AppStateFromGenesisFileFn(r *rand.Rand, cdc *codec.Codec, genesisFile string) (
genState json.RawMessage, newAccs []simulation.Account, chainID string) {
var genesis tmtypes.GenesisDoc
cdc := MakeCodec()
bytes, err := ioutil.ReadFile(config.GenesisFile)
bytes, err := ioutil.ReadFile(genesisFile)
if err != nil {
panic(err)
}
var genesis tmtypes.GenesisDoc
cdc.MustUnmarshalJSON(bytes, &genesis)
var appState GenesisState
@ -128,16 +128,20 @@ func AppStateFromGenesisFileFn(r *rand.Rand, config simulation.Config) (json.Raw
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)
if _, err := r.Read(privkeySeed); err != nil {
panic(err)
}
privKey := secp256k1.GenPrivKeySecp256k1(privkeySeed)
newAccs = append(newAccs, simulation.Account{PrivKey: privKey, PubKey: privKey.PubKey(), Address: acc.Address})
// create simulator accounts
simAcc := simulation.Account{PrivKey: privKey, PubKey: privKey.PubKey(), Address: acc.Address}
newAccs = append(newAccs, simAcc)
}
return genesis.AppState, newAccs, genesis.ChainID

View File

@ -1,33 +1,22 @@
//nolint
package simapp
import (
"encoding/json"
"flag"
"fmt"
"math/rand"
"time"
"io/ioutil"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
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"
)
//---------------------------------------------------------------------
// Flags
// List of SimApp flags for the simulator
// List of available flags for the simulator
var (
flagGenesisFileValue string
flagParamsFileValue string
@ -96,405 +85,31 @@ func NewConfigFromFlags() simulation.Config {
}
}
// 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(
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
}
//---------------------------------------------------------------------
// Simulation Utils
// ExportStateToJSON util function to export the app state to JSON
func ExportStateToJSON(app *SimApp, path string) error {
fmt.Println("exporting app state...")
appState, _, err := app.ExportAppStateAndValidators(false, nil)
if err != nil {
return err
}
return ioutil.WriteFile(path, []byte(appState), 0644)
}
// ExportParamsToJSON util function to export the simulation parameters to JSON
func ExportParamsToJSON(params simulation.Params, path string) error {
fmt.Println("exporting simulation params...")
paramsBz, err := json.MarshalIndent(params, "", " ")
if err != nil {
return err
}
return ioutil.WriteFile(path, paramsBz, 0644)
}
// 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, sdr sdk.StoreDecoderRegistry, cdc *codec.Codec, kvAs, kvBs []cmn.KVPair) (log string) {

View File

@ -15,16 +15,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
func makeTestCodec() (cdc *codec.Codec) {
cdc = codec.New()
sdk.RegisterCodec(cdc)
codec.RegisterCrypto(cdc)
auth.RegisterCodec(cdc)
return
}
func TestGetSimulationLog(t *testing.T) {
cdc := makeTestCodec()
cdc := MakeCodec()
decoders := make(sdk.StoreDecoderRegistry)
decoders[auth.StoreKey] = func(cdc *codec.Codec, kvAs, kvBs cmn.KVPair) string { return "10" }

View File

@ -130,17 +130,9 @@ type AppModuleGenesis interface {
ExportGenesis(sdk.Context) json.RawMessage
}
// AppModuleSimulation defines the standard functions that every module should expose
// for the SDK blockchain simulator
type AppModuleSimulation interface {
// register a func to decode the each module's defined types from their corresponding store key
RegisterStoreDecoder(sdk.StoreDecoderRegistry)
}
// AppModule is the standard form for an application module
type AppModule interface {
AppModuleGenesis
AppModuleSimulation
// registers
RegisterInvariants(sdk.InvariantRegistry)
@ -173,9 +165,6 @@ func NewGenesisOnlyAppModule(amg AppModuleGenesis) AppModule {
// RegisterInvariants is a placeholder function register no invariants
func (GenesisOnlyAppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}
// RegisterStoreDecoder empty store decoder registry
func (GenesisOnlyAppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {}
// Route empty module message route
func (GenesisOnlyAppModule) Route() string { return "" }

View File

@ -1,20 +1,41 @@
package module
import (
"encoding/json"
"math/rand"
"time"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
// AppModuleSimulation defines the standard functions that every module should expose
// for the SDK blockchain simulator
type AppModuleSimulation interface {
// register a func to decode the each module's defined types from their corresponding store key
RegisterStoreDecoder(sdk.StoreDecoderRegistry)
// randomized genesis states
GenerateGenesisState(input *SimulationState)
// randomized module parameters for param change proposals
RandomizedParams(r *rand.Rand) []simulation.ParamChange
}
// SimulationManager defines a simulation manager that provides the high level utility
// for managing and executing simulation functionalities for a group of modules
type SimulationManager struct {
Modules map[string]AppModule
StoreDecoders sdk.StoreDecoderRegistry
Modules []AppModuleSimulation // array of app modules; we use an array for deterministic simulation tests
StoreDecoders sdk.StoreDecoderRegistry // functions to decode the key-value pairs from each module's store
}
// NewSimulationManager creates a new SimulationManager object
func NewSimulationManager(moduleMap map[string]AppModule) *SimulationManager {
//
// CONTRACT: All the modules provided must be also registered on the module Manager
func NewSimulationManager(modules ...AppModuleSimulation) *SimulationManager {
return &SimulationManager{
Modules: moduleMap,
Modules: modules,
StoreDecoders: make(sdk.StoreDecoderRegistry),
}
}
@ -25,3 +46,37 @@ func (sm *SimulationManager) RegisterStoreDecoders() {
module.RegisterStoreDecoder(sm.StoreDecoders)
}
}
// GenerateGenesisStates generates a randomized GenesisState for each of the
// registered modules
func (sm *SimulationManager) GenerateGenesisStates(input *SimulationState) {
for _, module := range sm.Modules {
module.GenerateGenesisState(input)
}
}
// GenerateParamChanges generates randomized contents for creating params change
// proposal transactions
func (sm *SimulationManager) GenerateParamChanges(seed int64) (paramChanges []simulation.ParamChange) {
r := rand.New(rand.NewSource(seed))
for _, module := range sm.Modules {
paramChanges = append(paramChanges, module.RandomizedParams(r)...)
}
return
}
// SimulationState is the input parameters used on each of the module's randomized
// GenesisState generator function
type SimulationState struct {
AppParams simulation.AppParams
Cdc *codec.Codec // application codec
Rand *rand.Rand // random number
GenState map[string]json.RawMessage // genesis state
Accounts []simulation.Account // simulation accounts
InitialStake int64 // initial coins per account
NumBonded int64 // number of initially bonded acconts
GenTimestamp time.Time // genesis timestamp
UnbondTime time.Duration // staking unbond time stored to use it as the slashing maximum evidence duration
}

View File

@ -2,6 +2,7 @@ package auth
import (
"encoding/json"
"math/rand"
"github.com/gorilla/mux"
"github.com/spf13/cobra"
@ -15,6 +16,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth/client/rest"
"github.com/cosmos/cosmos-sdk/x/auth/simulation"
"github.com/cosmos/cosmos-sdk/x/auth/types"
sim "github.com/cosmos/cosmos-sdk/x/simulation"
)
var (
@ -77,6 +79,16 @@ func (AppModuleSimulation) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.DecodeStore
}
// GenerateGenesisState creates a randomized GenState of the auth module
func (AppModuleSimulation) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// RandomizedParams creates randomized auth param changes for the simulator.
func (AppModuleSimulation) RandomizedParams(r *rand.Rand) []sim.ParamChange {
return simulation.ParamChanges(r)
}
//____________________________________________________________________________
// AppModule implements an application module for the auth module.

View File

@ -0,0 +1,88 @@
package simulation
// DONTCOVER
import (
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
// Simulation parameter constants
const (
MaxMemoChars = "max_memo_characters"
TxSigLimit = "tx_sig_limit"
TxSizeCostPerByte = "tx_size_cost_per_byte"
SigVerifyCostED25519 = "sig_verify_cost_ed25519"
SigVerifyCostSECP256K1 = "sig_verify_cost_secp256k1"
)
// GenMaxMemoChars randomized MaxMemoChars
func GenMaxMemoChars(r *rand.Rand) uint64 {
return uint64(simulation.RandIntBetween(r, 100, 200))
}
// GenTxSigLimit randomized TxSigLimit
func GenTxSigLimit(r *rand.Rand) uint64 {
return uint64(r.Intn(7) + 1)
}
// GenTxSizeCostPerByte randomized TxSizeCostPerByte
func GenTxSizeCostPerByte(r *rand.Rand) uint64 {
return uint64(simulation.RandIntBetween(r, 5, 15))
}
// GenSigVerifyCostED25519 randomized SigVerifyCostED25519
func GenSigVerifyCostED25519(r *rand.Rand) uint64 {
return uint64(simulation.RandIntBetween(r, 500, 1000))
}
// GenSigVerifyCostSECP256K1 randomized SigVerifyCostSECP256K1
func GenSigVerifyCostSECP256K1(r *rand.Rand) uint64 {
return uint64(simulation.RandIntBetween(r, 500, 1000))
}
// RandomizedGenState generates a random GenesisState for auth
func RandomizedGenState(simState *module.SimulationState) {
var maxMemoChars uint64
simState.AppParams.GetOrGenerate(
simState.Cdc, MaxMemoChars, &maxMemoChars, simState.Rand,
func(r *rand.Rand) { maxMemoChars = GenMaxMemoChars(r) },
)
var txSigLimit uint64
simState.AppParams.GetOrGenerate(
simState.Cdc, TxSigLimit, &txSigLimit, simState.Rand,
func(r *rand.Rand) { txSigLimit = GenTxSigLimit(r) },
)
var txSizeCostPerByte uint64
simState.AppParams.GetOrGenerate(
simState.Cdc, TxSizeCostPerByte, &txSizeCostPerByte, simState.Rand,
func(r *rand.Rand) { txSizeCostPerByte = GenTxSizeCostPerByte(r) },
)
var sigVerifyCostED25519 uint64
simState.AppParams.GetOrGenerate(
simState.Cdc, SigVerifyCostED25519, &sigVerifyCostED25519, simState.Rand,
func(r *rand.Rand) { sigVerifyCostED25519 = GenSigVerifyCostED25519(r) },
)
var sigVerifyCostSECP256K1 uint64
simState.AppParams.GetOrGenerate(
simState.Cdc, SigVerifyCostSECP256K1, &sigVerifyCostSECP256K1, simState.Rand,
func(r *rand.Rand) { sigVerifyCostED25519 = GenSigVerifyCostSECP256K1(r) },
)
authGenesis := types.NewGenesisState(
types.NewParams(maxMemoChars, txSigLimit, txSizeCostPerByte,
sigVerifyCostED25519, sigVerifyCostSECP256K1),
)
fmt.Printf("Selected randomly generated auth parameters:\n%s\n", codec.MustMarshalJSONIndent(simState.Cdc, authGenesis.Params))
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(authGenesis)
}

View File

@ -0,0 +1,39 @@
package simulation
// DONTCOVER
import (
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
const (
keyMaxMemoCharacters = "MaxMemoCharacters"
keyTxSigLimit = "TxSigLimit"
keyTxSizeCostPerByte = "TxSizeCostPerByte"
)
// ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation
func ParamChanges(r *rand.Rand) []simulation.ParamChange {
return []simulation.ParamChange{
simulation.NewSimParamChange(types.ModuleName, keyMaxMemoCharacters, "",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", GenMaxMemoChars(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyTxSigLimit, "",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", GenTxSigLimit(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyTxSizeCostPerByte, "",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", GenTxSizeCostPerByte(r))
},
),
}
}

View File

@ -1,7 +1,8 @@
// nolint
// autogenerated code using github.com/rigelrozanski/multitool
// aliases generated for the following subdirectories:
// ALIASGEN: github.com/cosmos/cosmos-sdk/x/bank/types
// ALIASGEN: github.com/cosmos/cosmos-sdk/x/bank/internal/keeper
// ALIASGEN: github.com/cosmos/cosmos-sdk/x/bank/internal/types
package bank
import (
@ -10,26 +11,40 @@ import (
)
const (
QueryBalance = keeper.QueryBalance
DefaultCodespace = types.DefaultCodespace
CodeSendDisabled = types.CodeSendDisabled
CodeInvalidInputsOutputs = types.CodeInvalidInputsOutputs
ModuleName = types.ModuleName
RouterKey = types.RouterKey
QuerierRoute = types.QuerierRoute
RouterKey = types.RouterKey
DefaultParamspace = types.DefaultParamspace
DefaultSendEnabled = types.DefaultSendEnabled
)
var (
// functions aliases
RegisterCodec = types.RegisterCodec
ErrNoInputs = types.ErrNoInputs
ErrNoOutputs = types.ErrNoOutputs
ErrInputOutputMismatch = types.ErrInputOutputMismatch
ErrSendDisabled = types.ErrSendDisabled
NewBaseKeeper = keeper.NewBaseKeeper
NewInput = types.NewInput
NewOutput = types.NewOutput
ParamKeyTable = types.ParamKeyTable
RegisterInvariants = keeper.RegisterInvariants
NonnegativeBalanceInvariant = keeper.NonnegativeBalanceInvariant
NewBaseKeeper = keeper.NewBaseKeeper
NewBaseSendKeeper = keeper.NewBaseSendKeeper
NewBaseViewKeeper = keeper.NewBaseViewKeeper
NewQuerier = keeper.NewQuerier
RegisterCodec = types.RegisterCodec
ErrNoInputs = types.ErrNoInputs
ErrNoOutputs = types.ErrNoOutputs
ErrInputOutputMismatch = types.ErrInputOutputMismatch
ErrSendDisabled = types.ErrSendDisabled
NewGenesisState = types.NewGenesisState
DefaultGenesisState = types.DefaultGenesisState
ValidateGenesis = types.ValidateGenesis
NewMsgSend = types.NewMsgSend
NewMsgMultiSend = types.NewMsgMultiSend
NewInput = types.NewInput
NewOutput = types.NewOutput
ValidateInputsOutputs = types.ValidateInputsOutputs
ParamKeyTable = types.ParamKeyTable
NewQueryBalanceParams = types.NewQueryBalanceParams
// variable aliases
ModuleCdc = types.ModuleCdc
@ -37,10 +52,16 @@ var (
)
type (
BaseKeeper = keeper.BaseKeeper // ibc module depends on this
Keeper = keeper.Keeper
MsgSend = types.MsgSend
MsgMultiSend = types.MsgMultiSend
Input = types.Input
Output = types.Output
Keeper = keeper.Keeper
BaseKeeper = keeper.BaseKeeper
SendKeeper = keeper.SendKeeper
BaseSendKeeper = keeper.BaseSendKeeper
ViewKeeper = keeper.ViewKeeper
BaseViewKeeper = keeper.BaseViewKeeper
GenesisState = types.GenesisState
MsgSend = types.MsgSend
MsgMultiSend = types.MsgMultiSend
Input = types.Input
Output = types.Output
QueryBalanceParams = types.QueryBalanceParams
)

View File

@ -4,19 +4,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// GenesisState is the bank state that must be provided at genesis.
type GenesisState struct {
SendEnabled bool `json:"send_enabled" yaml:"send_enabled"`
}
// NewGenesisState creates a new genesis state.
func NewGenesisState(sendEnabled bool) GenesisState {
return GenesisState{SendEnabled: sendEnabled}
}
// DefaultGenesisState returns a default genesis state
func DefaultGenesisState() GenesisState { return NewGenesisState(true) }
// InitGenesis sets distribution information for genesis.
func InitGenesis(ctx sdk.Context, keeper Keeper, data GenesisState) {
keeper.SetSendEnabled(ctx, data.SendEnabled)
@ -26,7 +13,3 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data GenesisState) {
func ExportGenesis(ctx sdk.Context, keeper Keeper) GenesisState {
return NewGenesisState(keeper.GetSendEnabled(ctx))
}
// ValidateGenesis performs basic validation of bank genesis data returning an
// error for any failed validation criteria.
func ValidateGenesis(data GenesisState) error { return nil }

View File

@ -0,0 +1,18 @@
package types
// GenesisState is the bank state that must be provided at genesis.
type GenesisState struct {
SendEnabled bool `json:"send_enabled" yaml:"send_enabled"`
}
// NewGenesisState creates a new genesis state.
func NewGenesisState(sendEnabled bool) GenesisState {
return GenesisState{SendEnabled: sendEnabled}
}
// DefaultGenesisState returns a default genesis state
func DefaultGenesisState() GenesisState { return NewGenesisState(true) }
// ValidateGenesis performs basic validation of bank genesis data returning an
// error for any failed validation criteria.
func ValidateGenesis(data GenesisState) error { return nil }

View File

@ -2,6 +2,7 @@ package bank
import (
"encoding/json"
"math/rand"
"github.com/gorilla/mux"
"github.com/spf13/cobra"
@ -16,6 +17,8 @@ import (
"github.com/cosmos/cosmos-sdk/x/bank/client/rest"
"github.com/cosmos/cosmos-sdk/x/bank/internal/keeper"
"github.com/cosmos/cosmos-sdk/x/bank/internal/types"
"github.com/cosmos/cosmos-sdk/x/bank/simulation"
sim "github.com/cosmos/cosmos-sdk/x/simulation"
)
var (
@ -70,6 +73,16 @@ type AppModuleSimulation struct{}
// RegisterStoreDecoder performs a no-op.
func (AppModuleSimulation) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {}
// GenerateGenesisState creates a randomized GenState of the bank module.
func (AppModuleSimulation) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// RandomizedParams creates randomized bank param changes for the simulator.
func (AppModuleSimulation) RandomizedParams(r *rand.Rand) []sim.ParamChange {
return simulation.ParamChanges(r)
}
//____________________________________________________________________________
// AppModule implements an application module for the bank module.

View File

@ -0,0 +1,36 @@
package simulation
// DONTCOVER
import (
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/bank/internal/types"
)
// Simulation parameter constants
const (
SendEnabled = "send_enabled"
)
// GenSendEnabled randomized SendEnabled
func GenSendEnabled(r *rand.Rand) bool {
return r.Int63n(2) == 0
}
// RandomizedGenState generates a random GenesisState for bank
func RandomizedGenState(simState *module.SimulationState) {
var sendEnabled bool
simState.AppParams.GetOrGenerate(
simState.Cdc, SendEnabled, &sendEnabled, simState.Rand,
func(r *rand.Rand) { sendEnabled = GenSendEnabled(r) },
)
bankGenesis := types.NewGenesisState(sendEnabled)
fmt.Printf("Selected randomly generated bank parameters:\n%s\n", codec.MustMarshalJSONIndent(simState.Cdc, bankGenesis))
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(bankGenesis)
}

View File

@ -0,0 +1,25 @@
package simulation
// DONTCOVER
import (
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/x/bank/internal/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
const keySendEnabled = "sendenabled"
// ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation
func ParamChanges(r *rand.Rand) []simulation.ParamChange {
return []simulation.ParamChange{
simulation.NewSimParamChange(types.ModuleName, keySendEnabled, "",
func(r *rand.Rand) string {
return fmt.Sprintf("%v", GenSendEnabled(r))
},
),
}
}

View File

@ -18,9 +18,8 @@ import (
)
var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleSimulation = AppModuleSimulation{}
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
)
// AppModuleBasic defines the basic application module used by the crisis module.
@ -64,18 +63,9 @@ func (AppModuleBasic) GetQueryCmd(_ *codec.Codec) *cobra.Command { return nil }
//____________________________________________________________________________
// AppModuleSimulation defines the module simulation functions used by the crisis module.
type AppModuleSimulation struct{}
// RegisterStoreDecoder performs a no-op.
func (AppModuleSimulation) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {}
//____________________________________________________________________________
// AppModule implements an application module for the crisis module.
type AppModule struct {
AppModuleBasic
AppModuleSimulation
// NOTE: We store a reference to the keeper here so that after a module
// manager is created, the invariants can be properly registered and
@ -86,9 +76,8 @@ type AppModule struct {
// NewAppModule creates a new AppModule object
func NewAppModule(keeper *keeper.Keeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{},
AppModuleSimulation: AppModuleSimulation{},
keeper: keeper,
AppModuleBasic: AppModuleBasic{},
keeper: keeper,
}
}

View File

@ -2,6 +2,7 @@ package distribution
import (
"encoding/json"
"math/rand"
"github.com/gorilla/mux"
"github.com/spf13/cobra"
@ -16,6 +17,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/distribution/client/rest"
"github.com/cosmos/cosmos-sdk/x/distribution/simulation"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
sim "github.com/cosmos/cosmos-sdk/x/simulation"
)
var (
@ -78,6 +80,16 @@ func (AppModuleSimulation) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.DecodeStore
}
// GenerateGenesisState creates a randomized GenState of the distribution module.
func (AppModuleSimulation) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// RandomizedParams creates randomized distribution param changes for the simulator.
func (AppModuleSimulation) RandomizedParams(r *rand.Rand) []sim.ParamChange {
return simulation.ParamChanges(r)
}
//____________________________________________________________________________
// AppModule implements an application module for the distribution module.

View File

@ -0,0 +1,67 @@
package simulation
// DONTCOVER
import (
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
)
// Simulation parameter constants
const (
CommunityTax = "community_tax"
BaseProposerReward = "base_proposer_reward"
BonusProposerReward = "bonus_proposer_reward"
)
// GenCommunityTax randomized CommunityTax
func GenCommunityTax(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2))
}
// GenBaseProposerReward randomized BaseProposerReward
func GenBaseProposerReward(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2))
}
// GenBonusProposerReward randomized BonusProposerReward
func GenBonusProposerReward(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2))
}
// RandomizedGenState generates a random GenesisState for distribution
func RandomizedGenState(simState *module.SimulationState) {
var communityTax sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, CommunityTax, &communityTax, simState.Rand,
func(r *rand.Rand) { communityTax = GenCommunityTax(r) },
)
var baseProposerReward sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, BaseProposerReward, &baseProposerReward, simState.Rand,
func(r *rand.Rand) { baseProposerReward = GenBaseProposerReward(r) },
)
var bonusProposerReward sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, BonusProposerReward, &bonusProposerReward, simState.Rand,
func(r *rand.Rand) { bonusProposerReward = GenBonusProposerReward(r) },
)
distrGenesis := types.GenesisState{
FeePool: types.InitialFeePool(),
CommunityTax: communityTax,
BaseProposerReward: baseProposerReward,
BonusProposerReward: bonusProposerReward,
}
fmt.Printf("Selected randomly generated distribution parameters:\n%s\n", codec.MustMarshalJSONIndent(simState.Cdc, distrGenesis))
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(distrGenesis)
}

View File

@ -7,8 +7,8 @@ import (
"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/distribution"
"github.com/cosmos/cosmos-sdk/x/gov"
govsimops "github.com/cosmos/cosmos-sdk/x/gov/simulation/operations"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
@ -88,18 +88,22 @@ func SimulateMsgWithdrawValidatorCommission(k distribution.Keeper) simulation.Op
// SimulateCommunityPoolSpendProposalContent generates random community-pool-spend proposal content
func SimulateCommunityPoolSpendProposalContent(k distribution.Keeper) govsimops.ContentSimulator {
return func(r *rand.Rand, _ *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account) gov.Content {
return func(r *rand.Rand, ctx sdk.Context, accs []simulation.Account) govtypes.Content {
var coins sdk.Coins
recipientAcc := simulation.RandomAcc(r, accs)
coins := sdk.Coins{}
balance := k.GetFeePool(ctx).CommunityPool
if len(balance) > 0 {
denomIndex := r.Intn(len(balance))
amount, goErr := simulation.RandPositiveInt(r, balance[denomIndex].Amount.TruncateInt())
if goErr == nil {
amount, err := simulation.RandPositiveInt(r, balance[denomIndex].Amount.TruncateInt())
if err == nil {
denom := balance[denomIndex].Denom
coins = sdk.NewCoins(sdk.NewCoin(denom, amount.Mul(sdk.NewInt(2))))
}
}
return distribution.NewCommunityPoolSpendProposal(
simulation.RandStringOfLength(r, 10),
simulation.RandStringOfLength(r, 100),

View File

@ -0,0 +1,39 @@
package simulation
// DONTCOVER
import (
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
const (
keyCommunityTax = "communitytax"
keyBaseProposerReward = "baseproposerreward"
keyBonusProposerReward = "bonusproposerreward"
)
// ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation
func ParamChanges(r *rand.Rand) []simulation.ParamChange {
return []simulation.ParamChange{
simulation.NewSimParamChange(types.ModuleName, keyCommunityTax, "",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenCommunityTax(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyBaseProposerReward, "",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenBaseProposerReward(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyBonusProposerReward, "",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenBonusProposerReward(r))
},
),
}
}

View File

@ -2,6 +2,7 @@ package genaccounts
import (
"encoding/json"
"math/rand"
"github.com/gorilla/mux"
"github.com/spf13/cobra"
@ -14,6 +15,8 @@ import (
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/auth/exported"
"github.com/cosmos/cosmos-sdk/x/genaccounts/internal/types"
"github.com/cosmos/cosmos-sdk/x/genaccounts/simulation"
sim "github.com/cosmos/cosmos-sdk/x/simulation"
)
var (
@ -82,6 +85,16 @@ type AppModuleSimulation struct{}
// RegisterStoreDecoder performs a no-op.
func (AppModuleSimulation) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {}
// GenerateGenesisState creates a randomized GenState of the genesis accounts module.
func (AppModuleSimulation) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// RandomizedParams doesn't create randomized genaccounts param changes for the simulator.
func (AppModuleSimulation) RandomizedParams(_ *rand.Rand) []sim.ParamChange {
return nil
}
//____________________________________________________________________________
// AppModule implements an application module for the genesis accounts module.
@ -93,15 +106,30 @@ type AppModule struct {
}
// NewAppModule creates a new AppModule object
func NewAppModule(accountKeeper types.AccountKeeper) module.AppModule {
func NewAppModule(accountKeeper types.AccountKeeper) AppModule {
return module.NewGenesisOnlyAppModule(AppModule{
return AppModule{
AppModuleBasic: AppModuleBasic{},
AppModuleSimulation: AppModuleSimulation{},
accountKeeper: accountKeeper,
})
}
}
// RegisterInvariants is a placeholder function register no invariants
func (AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}
// Route empty module message route
func (AppModule) Route() string { return "" }
// NewHandler returns an empty module handler
func (AppModule) NewHandler() sdk.Handler { return nil }
// QuerierRoute returns an empty module querier route
func (AppModule) QuerierRoute() string { return "" }
// NewQuerierHandler returns an empty module querier
func (AppModule) NewQuerierHandler() sdk.Querier { return nil }
// InitGenesis performs genesis initialization for the genesis accounts module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
@ -117,3 +145,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
gs := ExportGenesis(ctx, am.accountKeeper)
return ModuleCdc.MustMarshalJSON(gs)
}
// BeginBlock returns an empty module begin-block
func (AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {}
// EndBlock returns an empty module end-block
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}

View File

@ -0,0 +1,68 @@
package simulation
// DONTCOVER
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/genaccounts/internal/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
// RandomizedGenState generates a random GenesisState for the genesis accounts
func RandomizedGenState(simState *module.SimulationState) {
var genesisAccounts []types.GenesisAccount
// randomly generate some genesis accounts
for i, acc := range simState.Accounts {
coins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(simState.InitialStake))}
bacc := authtypes.NewBaseAccountWithAddress(acc.Address)
if err := bacc.SetCoins(coins); err != nil {
panic(err)
}
var gacc types.GenesisAccount
// Only consider making a vesting account once the initial bonded validator
// set is exhausted due to needing to track DelegatedVesting.
if int64(i) > simState.NumBonded && simState.Rand.Intn(100) < 50 {
var (
vacc authexported.VestingAccount
endTime int64
)
startTime := simState.GenTimestamp.Unix()
// Allow for some vesting accounts to vest very quickly while others very slowly.
if simState.Rand.Intn(100) < 50 {
endTime = int64(simulation.RandIntBetween(simState.Rand, int(startTime), int(startTime+(60*60*24*30))))
} else {
endTime = int64(simulation.RandIntBetween(simState.Rand, int(startTime), int(startTime+(60*60*12))))
}
if startTime == endTime {
endTime++
}
if simState.Rand.Intn(100) < 50 {
vacc = authtypes.NewContinuousVestingAccount(&bacc, startTime, endTime)
} else {
vacc = authtypes.NewDelayedVestingAccount(&bacc, endTime)
}
var err error
gacc, err = types.NewGenesisAccountI(vacc)
if err != nil {
panic(err)
}
} else {
gacc = types.NewGenesisAccount(&bacc)
}
genesisAccounts = append(genesisAccounts, gacc)
}
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(genesisAccounts)
}

View File

@ -16,9 +16,8 @@ import (
)
var (
_ module.AppModuleGenesis = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleSimulation = AppModuleSimulation{}
_ module.AppModuleGenesis = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
)
// AppModuleBasic defines the basic application module used by the genutil module.
@ -59,18 +58,9 @@ func (AppModuleBasic) GetQueryCmd(_ *codec.Codec) *cobra.Command { return nil }
//____________________________________________________________________________
// AppModuleSimulation defines the module simulation functions used by the auth module.
type AppModuleSimulation struct{}
// RegisterStoreDecoder registers a decoder for genutil module's types
func (AppModuleSimulation) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {}
//____________________________________________________________________________
// AppModule implements an application module for the genutil module.
type AppModule struct {
AppModuleBasic
AppModuleSimulation
accountKeeper types.AccountKeeper
stakingKeeper types.StakingKeeper
@ -82,11 +72,10 @@ func NewAppModule(accountKeeper types.AccountKeeper,
stakingKeeper types.StakingKeeper, deliverTx deliverTxfn) module.AppModule {
return module.NewGenesisOnlyAppModule(AppModule{
AppModuleBasic: AppModuleBasic{},
AppModuleSimulation: AppModuleSimulation{},
accountKeeper: accountKeeper,
stakingKeeper: stakingKeeper,
deliverTx: deliverTx,
AppModuleBasic: AppModuleBasic{},
accountKeeper: accountKeeper,
stakingKeeper: stakingKeeper,
deliverTx: deliverTx,
})
}

View File

@ -4,6 +4,7 @@ package gov
import (
"encoding/json"
"math/rand"
"github.com/gorilla/mux"
"github.com/spf13/cobra"
@ -19,6 +20,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/gov/client/rest"
"github.com/cosmos/cosmos-sdk/x/gov/simulation"
"github.com/cosmos/cosmos-sdk/x/gov/types"
sim "github.com/cosmos/cosmos-sdk/x/simulation"
)
var (
@ -96,11 +98,21 @@ func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command {
// AppModuleSimulation defines the module simulation functions used by the gov module.
type AppModuleSimulation struct{}
// RegisterStoreDecoder performs a no-op.
// RegisterStoreDecoder registers a decoder for gov module's types
func (AppModuleSimulation) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.DecodeStore
}
// GenerateGenesisState creates a randomized GenState of the gov module.
func (AppModuleSimulation) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// RandomizedParams creates randomized gov param changes for the simulator.
func (AppModuleSimulation) RandomizedParams(r *rand.Rand) []sim.ParamChange {
return simulation.ParamChanges(r)
}
//____________________________________________________________________________
// AppModule implements an application module for the gov module.

107
x/gov/simulation/genesis.go Normal file
View File

@ -0,0 +1,107 @@
package simulation
// DONTCOVER
import (
"fmt"
"math/rand"
"time"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
// Simulation parameter constants
const (
DepositParamsMinDeposit = "deposit_params_min_deposit"
DepositParamsDepositPeriod = "deposit_params_deposit_period"
VotingParamsVotingPeriod = "voting_params_voting_period"
TallyParamsQuorum = "tally_params_quorum"
TallyParamsThreshold = "tally_params_threshold"
TallyParamsVeto = "tally_params_veto"
)
// GenDepositParamsDepositPeriod randomized DepositParamsDepositPeriod
func GenDepositParamsDepositPeriod(r *rand.Rand) time.Duration {
return time.Duration(simulation.RandIntBetween(r, 1, 2*60*60*24*2)) * time.Second
}
// GenDepositParamsMinDeposit randomized DepositParamsMinDeposit
func GenDepositParamsMinDeposit(r *rand.Rand) sdk.Coins {
return sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, int64(simulation.RandIntBetween(r, 1, 1e3))))
}
// GenVotingParamsVotingPeriod randomized VotingParamsVotingPeriod
func GenVotingParamsVotingPeriod(r *rand.Rand) time.Duration {
return time.Duration(simulation.RandIntBetween(r, 1, 2*60*60*24*2)) * time.Second
}
// GenTallyParamsQuorum randomized TallyParamsQuorum
func GenTallyParamsQuorum(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(int64(simulation.RandIntBetween(r, 334, 500)), 3)
}
// GenTallyParamsThreshold randomized TallyParamsThreshold
func GenTallyParamsThreshold(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(int64(simulation.RandIntBetween(r, 450, 550)), 3)
}
// GenTallyParamsVeto randomized TallyParamsVeto
func GenTallyParamsVeto(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(int64(simulation.RandIntBetween(r, 250, 334)), 3)
}
// RandomizedGenState generates a random GenesisState for gov
func RandomizedGenState(simState *module.SimulationState) {
startingProposalID := uint64(simState.Rand.Intn(100))
var minDeposit sdk.Coins
simState.AppParams.GetOrGenerate(
simState.Cdc, DepositParamsMinDeposit, &minDeposit, simState.Rand,
func(r *rand.Rand) { minDeposit = GenDepositParamsMinDeposit(r) },
)
var depositPeriod time.Duration
simState.AppParams.GetOrGenerate(
simState.Cdc, DepositParamsDepositPeriod, &depositPeriod, simState.Rand,
func(r *rand.Rand) { depositPeriod = GenDepositParamsDepositPeriod(r) },
)
var votingPeriod time.Duration
simState.AppParams.GetOrGenerate(
simState.Cdc, VotingParamsVotingPeriod, &votingPeriod, simState.Rand,
func(r *rand.Rand) { votingPeriod = GenVotingParamsVotingPeriod(r) },
)
var quorum sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, TallyParamsQuorum, &quorum, simState.Rand,
func(r *rand.Rand) { quorum = GenTallyParamsQuorum(r) },
)
var threshold sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, TallyParamsThreshold, &threshold, simState.Rand,
func(r *rand.Rand) { threshold = GenTallyParamsThreshold(r) },
)
var veto sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, TallyParamsVeto, &veto, simState.Rand,
func(r *rand.Rand) { veto = GenTallyParamsVeto(r) },
)
govGenesis := types.NewGenesisState(
startingProposalID,
types.NewDepositParams(minDeposit, depositPeriod),
types.NewVotingParams(votingPeriod),
types.NewTallyParams(quorum, threshold, veto),
)
fmt.Printf("Selected randomly generated governance parameters:\n%s\n", codec.MustMarshalJSONIndent(simState.Cdc, govGenesis))
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(govGenesis)
}

View File

@ -14,7 +14,7 @@ import (
// ContentSimulator defines a function type alias for generating random proposal
// content.
type ContentSimulator func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account) gov.Content
type ContentSimulator func(r *rand.Rand, ctx sdk.Context, accs []simulation.Account) gov.Content
// SimulateSubmittingVotingAndSlashingForProposal simulates creating a msg Submit Proposal
// voting on the proposal, and subsequently slashing the proposal. It is implemented using
@ -51,7 +51,7 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, contentSim Con
// 1) submit proposal now
sender := simulation.RandomAcc(r, accs)
content := contentSim(r, app, ctx, accs)
content := contentSim(r, ctx, accs)
msg, err := simulationCreateMsgSubmitProposal(r, content, sender)
if err != nil {
return simulation.NoOpMsg(gov.ModuleName), nil, err
@ -107,7 +107,7 @@ func simulateHandleMsgSubmitProposal(msg gov.MsgSubmitProposal, handler sdk.Hand
}
// SimulateTextProposalContent returns random text proposal content.
func SimulateTextProposalContent(r *rand.Rand, _ *baseapp.BaseApp, _ sdk.Context, _ []simulation.Account) gov.Content {
func SimulateTextProposalContent(r *rand.Rand, _ sdk.Context, _ []simulation.Account) gov.Content {
return gov.NewTextProposal(
simulation.RandStringOfLength(r, 140),
simulation.RandStringOfLength(r, 5000),

View File

@ -0,0 +1,68 @@
package simulation
// DONTCOVER
import (
"encoding/json"
"fmt"
"math/rand"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
const (
keyVotingParams = "votingparams"
keyDepositParams = "depositparams"
keyTallyParams = "tallyparams"
subkeyQuorum = "quorum"
subkeyThreshold = "threshold"
subkeyVeto = "veto"
)
// ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation
func ParamChanges(r *rand.Rand) []simulation.ParamChange {
return []simulation.ParamChange{
simulation.NewSimParamChange(types.ModuleName, keyVotingParams, "",
func(r *rand.Rand) string {
return fmt.Sprintf(`{"voting_period": "%d"}`, GenVotingParamsVotingPeriod(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyDepositParams, "",
func(r *rand.Rand) string {
return fmt.Sprintf(`{"max_deposit_period": "%d"}`, GenDepositParamsDepositPeriod(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyTallyParams, "",
func(r *rand.Rand) string {
changes := []struct {
key string
value sdk.Dec
}{
{subkeyQuorum, GenTallyParamsQuorum(r)},
{subkeyThreshold, GenTallyParamsThreshold(r)},
{subkeyVeto, GenTallyParamsVeto(r)},
}
pc := make(map[string]string)
numChanges := simulation.RandIntBetween(r, 1, len(changes))
for i := 0; i < numChanges; i++ {
c := changes[r.Intn(len(changes))]
_, ok := pc[c.key]
for ok {
c := changes[r.Intn(len(changes))]
_, ok = pc[c.key]
}
pc[c.key] = c.value.String()
}
bz, _ := json.Marshal(pc)
return string(bz)
},
),
}
}

View File

@ -24,6 +24,9 @@ var (
// functions aliases
NewKeeper = keeper.NewKeeper
NewQuerier = keeper.NewQuerier
NewGenesisState = types.NewGenesisState
DefaultGenesisState = types.DefaultGenesisState
ValidateGenesis = types.ValidateGenesis
NewMinter = types.NewMinter
InitialMinter = types.InitialMinter
DefaultInitialMinter = types.DefaultInitialMinter
@ -45,7 +48,8 @@ var (
)
type (
Keeper = keeper.Keeper
Minter = types.Minter
Params = types.Params
Keeper = keeper.Keeper
GenesisState = types.GenesisState
Minter = types.Minter
Params = types.Params
)

View File

@ -4,28 +4,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// GenesisState - minter state
type GenesisState struct {
Minter Minter `json:"minter" yaml:"minter"` // minter object
Params Params `json:"params" yaml:"params"` // inflation params
}
// NewGenesisState creates a new GenesisState object
func NewGenesisState(minter Minter, params Params) GenesisState {
return GenesisState{
Minter: minter,
Params: params,
}
}
// DefaultGenesisState creates a default GenesisState object
func DefaultGenesisState() GenesisState {
return GenesisState{
Minter: DefaultInitialMinter(),
Params: DefaultParams(),
}
}
// InitGenesis new mint genesis
func InitGenesis(ctx sdk.Context, keeper Keeper, data GenesisState) {
keeper.SetMinter(ctx, data.Minter)
@ -38,19 +16,3 @@ func ExportGenesis(ctx sdk.Context, keeper Keeper) GenesisState {
params := keeper.GetParams(ctx)
return NewGenesisState(minter, params)
}
// ValidateGenesis validates the provided genesis state to ensure the
// expected invariants holds.
func ValidateGenesis(data GenesisState) error {
err := ValidateParams(data.Params)
if err != nil {
return err
}
err = ValidateMinter(data.Minter)
if err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,34 @@
package types
// GenesisState - minter state
type GenesisState struct {
Minter Minter `json:"minter" yaml:"minter"` // minter object
Params Params `json:"params" yaml:"params"` // inflation params
}
// NewGenesisState creates a new GenesisState object
func NewGenesisState(minter Minter, params Params) GenesisState {
return GenesisState{
Minter: minter,
Params: params,
}
}
// DefaultGenesisState creates a default GenesisState object
func DefaultGenesisState() GenesisState {
return GenesisState{
Minter: DefaultInitialMinter(),
Params: DefaultParams(),
}
}
// ValidateGenesis validates the provided genesis state to ensure the
// expected invariants holds.
func ValidateGenesis(data GenesisState) error {
err := ValidateParams(data.Params)
if err != nil {
return err
}
return ValidateMinter(data.Minter)
}

View File

@ -2,6 +2,7 @@ package mint
import (
"encoding/json"
"math/rand"
"github.com/gorilla/mux"
"github.com/spf13/cobra"
@ -15,6 +16,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/mint/client/cli"
"github.com/cosmos/cosmos-sdk/x/mint/client/rest"
"github.com/cosmos/cosmos-sdk/x/mint/simulation"
sim "github.com/cosmos/cosmos-sdk/x/simulation"
)
var (
@ -75,6 +77,16 @@ func (AppModuleSimulation) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.DecodeStore
}
// GenerateGenesisState creates a randomized GenState of the mint module.
func (AppModuleSimulation) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// RandomizedParams creates randomized mint param changes for the simulator.
func (AppModuleSimulation) RandomizedParams(r *rand.Rand) []sim.ParamChange {
return simulation.ParamChanges(r)
}
//____________________________________________________________________________
// AppModule implements an application module for the mint module.

View File

@ -0,0 +1,92 @@
package simulation
// DONTCOVER
import (
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/mint/internal/types"
)
// Simulation parameter constants
const (
Inflation = "inflation"
InflationRateChange = "inflation_rate_change"
InflationMax = "inflation_max"
InflationMin = "inflation_min"
GoalBonded = "goal_bonded"
)
// GenInflation randomized Inflation
func GenInflation(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(int64(r.Intn(99)), 2)
}
// GenInflationRateChange randomized InflationRateChange
func GenInflationRateChange(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(int64(r.Intn(99)), 2)
}
// GenInflationMax randomized InflationMax
func GenInflationMax(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(20, 2)
}
// GenInflationMin randomized InflationMin
func GenInflationMin(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(7, 2)
}
// GenGoalBonded randomized GoalBonded
func GenGoalBonded(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(67, 2)
}
// RandomizedGenState generates a random GenesisState for mint
func RandomizedGenState(simState *module.SimulationState) {
// minter
var inflation sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, Inflation, &inflation, simState.Rand,
func(r *rand.Rand) { inflation = GenInflation(r) },
)
// params
var inflationRateChange sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, InflationRateChange, &inflationRateChange, simState.Rand,
func(r *rand.Rand) { inflationRateChange = GenInflationRateChange(r) },
)
var inflationMax sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, InflationMax, &inflationMax, simState.Rand,
func(r *rand.Rand) { inflationMax = GenInflationMax(r) },
)
var inflationMin sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, InflationMin, &inflationMin, simState.Rand,
func(r *rand.Rand) { inflationMin = GenInflationMin(r) },
)
var goalBonded sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, GoalBonded, &goalBonded, simState.Rand,
func(r *rand.Rand) { goalBonded = GenGoalBonded(r) },
)
mintDenom := sdk.DefaultBondDenom
blocksPerYear := uint64(60 * 60 * 8766 / 5)
params := types.NewParams(mintDenom, inflationRateChange, inflationMax, inflationMin, goalBonded, blocksPerYear)
mintGenesis := types.NewGenesisState(types.InitialMinter(inflation), params)
fmt.Printf("Selected randomly generated minting parameters:\n%s\n", codec.MustMarshalJSONIndent(simState.Cdc, mintGenesis))
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(mintGenesis)
}

View File

@ -0,0 +1,45 @@
package simulation
// DONTCOVER
import (
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/x/mint/internal/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
const (
keyInflationRateChange = "InflationRateChange"
keyInflationMax = "InflationMax"
keyInflationMin = "InflationMin"
keyGoalBonded = "GoalBonded"
)
// ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation
func ParamChanges(r *rand.Rand) []simulation.ParamChange {
return []simulation.ParamChange{
simulation.NewSimParamChange(types.ModuleName, keyInflationRateChange, "",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenInflationRateChange(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyInflationMax, "",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenInflationMax(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyInflationMin, "",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenInflationMin(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyGoalBonded, "",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenGoalBonded(r))
},
),
}
}

View File

@ -13,7 +13,7 @@ import (
// nolint: deadcode unused
var (
denom1 = "test-denom"
denom1 = "test-denom"
denom2 = "test-denom2"
denom3 = "test-denom3"
id = "1"
@ -22,7 +22,7 @@ var (
address = types.CreateTestAddrs(1)[0]
address2 = types.CreateTestAddrs(2)[1]
address3 = types.CreateTestAddrs(3)[2]
tokenURI1 = "https://google.com/token-1.json"
tokenURI1 = "https://google.com/token-1.json"
tokenURI2 = "https://google.com/token-2.json"
)

View File

@ -4,6 +4,7 @@ package nft
import (
"encoding/json"
"math/rand"
"github.com/gorilla/mux"
"github.com/spf13/cobra"
@ -17,6 +18,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/nft/client/cli"
"github.com/cosmos/cosmos-sdk/x/nft/client/rest"
"github.com/cosmos/cosmos-sdk/x/nft/simulation"
sim "github.com/cosmos/cosmos-sdk/x/simulation"
)
var (
@ -76,11 +78,21 @@ func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command {
// AppModuleSimulation defines the module simulation functions used by the gov module.
type AppModuleSimulation struct{}
// RegisterStoreDecoder performs a no-op.
// RegisterStoreDecoder registers a decoder for nft module's types
func (AppModuleSimulation) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.DecodeStore
}
// GenerateGenesisState creates a randomized GenState of the nft module.
func (AppModuleSimulation) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// RandomizedParams doesn't create randomized nft param changes for the simulator.
func (AppModuleSimulation) RandomizedParams(_ *rand.Rand) []sim.ParamChange {
return nil
}
//____________________________________________________________________________
// AppModule supply app module

View File

@ -1,48 +1,53 @@
package simulation
import (
"encoding/json"
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/nft/internal/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
// GenNFTGenesisState generates a random GenesisState for nft
func GenNFTGenesisState(cdc *codec.Codec, r *rand.Rand, accs []simulation.Account, ap simulation.AppParams, genesisState map[string]json.RawMessage) {
const (
Kitties = "crypto-kitties"
Doggos = "crypto-doggos"
)
const (
kities = "crypto-kities"
doggos = "crypto-doggos"
)
collections := types.NewCollections(types.NewCollection(Kitties, types.NFTs{}), types.NewCollection(Doggos, types.NFTs{}))
// RandomizedGenState generates a random GenesisState for nft
func RandomizedGenState(simState *module.SimulationState) {
collections := types.NewCollections(types.NewCollection(kities, types.NFTs{}), types.NewCollection(doggos, types.NFTs{}))
var ownerships []types.Owner
for _, acc := range accs {
if r.Intn(100) < 50 {
for _, acc := range simState.Accounts {
// 10% of accounts own an NFT
if simState.Rand.Intn(100) < 10 {
baseNFT := types.NewBaseNFT(
simulation.RandStringOfLength(r, 10), // id
simulation.RandStringOfLength(simState.Rand, 10), // id
acc.Address,
simulation.RandStringOfLength(r, 45), // tokenURI
simulation.RandStringOfLength(simState.Rand, 45), // tokenURI
)
var idCollection types.IDCollection
var err error
if r.Intn(100) < 50 {
var (
idCollection types.IDCollection
err error
)
// 50% doggos and 50% kitties
if simState.Rand.Intn(100) < 50 {
collections[0], err = collections[0].AddNFT(&baseNFT)
if err != nil {
panic(err)
}
idCollection = types.NewIDCollection(Kitties, []string{baseNFT.ID})
idCollection = types.NewIDCollection(kities, []string{baseNFT.ID})
} else {
collections[1], err = collections[1].AddNFT(&baseNFT)
if err != nil {
panic(err)
}
idCollection = types.NewIDCollection(Doggos, []string{baseNFT.ID})
idCollection = types.NewIDCollection(doggos, []string{baseNFT.ID})
}
ownership := types.NewOwner(acc.Address, idCollection)
ownerships = append(ownerships, ownership)
}
@ -50,6 +55,6 @@ func GenNFTGenesisState(cdc *codec.Codec, r *rand.Rand, accs []simulation.Accoun
nftGenesis := types.NewGenesisState(ownerships, collections)
fmt.Printf("Selected randomly generated NFT parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, nftGenesis))
genesisState[types.ModuleName] = cdc.MustMarshalJSON(nftGenesis)
fmt.Printf("Selected randomly generated NFT genesis state:\n%s\n", codec.MustMarshalJSONIndent(simState.Cdc, nftGenesis))
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(nftGenesis)
}

View File

@ -1,185 +1,53 @@
package operations
import (
"encoding/json"
"fmt"
"math/rand"
"time"
"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
govsimops "github.com/cosmos/cosmos-sdk/x/gov/simulation/operations"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
type simParamChange struct {
subspace string
key string
subkey string
simValue func(r *rand.Rand) string
}
func (spc simParamChange) compKey() string {
return fmt.Sprintf("%s/%s/%s", spc.subkey, spc.key, spc.subkey)
}
// paramChangePool defines a static slice of possible simulated parameter changes
// where each simParamChange corresponds to a ParamChange with a simValue
// function to generate a simulated new value.
var paramChangePool = []simParamChange{
// staking parameters
{
"staking",
"MaxValidators",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("%d", simulation.ModuleParamSimulator[simulation.MaxValidators](r).(uint16))
},
},
{
"staking",
"UnbondingTime",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator[simulation.UnbondingTime](r).(time.Duration))
},
},
// slashing parameters
{
"slashing",
"SignedBlocksWindow",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator[simulation.SignedBlocksWindow](r).(int64))
},
},
{
"slashing",
"MinSignedPerWindow",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", simulation.ModuleParamSimulator[simulation.MinSignedPerWindow](r).(sdk.Dec))
},
},
{
"slashing",
"SlashFractionDowntime",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", simulation.ModuleParamSimulator[simulation.SlashFractionDowntime](r).(sdk.Dec))
},
},
// minting parameters
{
"mint",
"InflationRateChange",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", simulation.ModuleParamSimulator[simulation.InflationRateChange](r).(sdk.Dec))
},
},
// gov parameters
{
"gov",
"votingparams",
"",
func(r *rand.Rand) string {
return fmt.Sprintf(`{"voting_period": "%d"}`, simulation.ModuleParamSimulator[simulation.VotingParamsVotingPeriod](r).(time.Duration))
},
},
{
"gov",
"depositparams",
"",
func(r *rand.Rand) string {
return fmt.Sprintf(`{"max_deposit_period": "%d"}`, simulation.ModuleParamSimulator[simulation.VotingParamsVotingPeriod](r).(time.Duration))
},
},
{
"gov",
"tallyparams",
"",
func(r *rand.Rand) string {
changes := []struct {
key string
value sdk.Dec
}{
{"quorum", simulation.ModuleParamSimulator[simulation.TallyParamsQuorum](r).(sdk.Dec)},
{"threshold", simulation.ModuleParamSimulator[simulation.TallyParamsThreshold](r).(sdk.Dec)},
{"veto", simulation.ModuleParamSimulator[simulation.TallyParamsVeto](r).(sdk.Dec)},
}
pc := make(map[string]string)
numChanges := simulation.RandIntBetween(r, 1, len(changes))
for i := 0; i < numChanges; i++ {
c := changes[r.Intn(len(changes))]
_, ok := pc[c.key]
for ok {
c := changes[r.Intn(len(changes))]
_, ok = pc[c.key]
}
pc[c.key] = c.value.String()
}
bz, _ := json.Marshal(pc)
return string(bz)
},
},
// auth parameters
{
"auth",
"MaxMemoCharacters",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator[simulation.MaxMemoChars](r).(uint64))
},
},
{
"auth",
"TxSigLimit",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator[simulation.TxSigLimit](r).(uint64))
},
},
{
"auth",
"TxSizeCostPerByte",
"",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator[simulation.TxSizeCostPerByte](r).(uint64))
},
},
}
// SimulateParamChangeProposalContent returns random parameter change content.
// It will generate a ParameterChangeProposal object with anywhere between 1 and
// 3 parameter changes all of which have random, but valid values.
func SimulateParamChangeProposalContent(r *rand.Rand, _ *baseapp.BaseApp, _ sdk.Context, _ []simulation.Account) govtypes.Content {
numChanges := simulation.RandIntBetween(r, 1, len(paramChangePool)/2)
paramChanges := make([]params.ParamChange, numChanges, numChanges)
paramChangesKeys := make(map[string]struct{})
// the total amount of defined parameters changes, all of which have random valid values.
func SimulateParamChangeProposalContent(paramChangePool []simulation.ParamChange) govsimops.ContentSimulator {
return func(r *rand.Rand, _ sdk.Context, _ []simulation.Account) govtypes.Content {
for i := 0; i < numChanges; i++ {
spc := paramChangePool[r.Intn(len(paramChangePool))]
// do not include duplicate parameter changes for a given subspace/key
_, ok := paramChangesKeys[spc.compKey()]
for ok {
spc = paramChangePool[r.Intn(len(paramChangePool))]
_, ok = paramChangesKeys[spc.compKey()]
lenParamChange := len(paramChangePool)
if lenParamChange == 0 {
panic("param changes array is empty")
}
paramChangesKeys[spc.compKey()] = struct{}{}
paramChanges[i] = params.NewParamChangeWithSubkey(spc.subspace, spc.key, spc.subkey, spc.simValue(r))
}
numChanges := simulation.RandIntBetween(r, 1, lenParamChange)
paramChanges := make([]params.ParamChange, numChanges, numChanges)
return params.NewParameterChangeProposal(
simulation.RandStringOfLength(r, 140),
simulation.RandStringOfLength(r, 5000),
paramChanges,
)
// map from key to empty struct; used only for look-up of the keys of the
// parameters that are already in the random set of changes.
paramChangesKeys := make(map[string]struct{})
for i := 0; i < numChanges; i++ {
spc := paramChangePool[r.Intn(len(paramChangePool))]
// do not include duplicate parameter changes for a given subspace/key
_, ok := paramChangesKeys[spc.ComposedKey()]
for ok {
spc = paramChangePool[r.Intn(len(paramChangePool))]
_, ok = paramChangesKeys[spc.ComposedKey()]
}
// add a new distinct parameter to the set of changes and register the key
// to avoid further duplicates
paramChangesKeys[spc.ComposedKey()] = struct{}{}
paramChanges[i] = params.NewParamChangeWithSubkey(spc.Subspace, spc.Key, spc.Subkey, spc.SimValue(r))
}
return params.NewParameterChangeProposal(
simulation.RandStringOfLength(r, 140), // title
simulation.RandStringOfLength(r, 5000), // description
paramChanges, // set of changes
)
}
}

View File

@ -1,7 +1,7 @@
package subspace
import (
"errors"
"fmt"
"reflect"
"github.com/cosmos/cosmos-sdk/codec"
@ -145,7 +145,7 @@ func (s Subspace) Modified(ctx sdk.Context, key []byte) bool {
func (s Subspace) checkType(store sdk.KVStore, key []byte, param interface{}) {
attr, ok := s.table.m[string(key)]
if !ok {
panic("Parameter not registered")
panic(fmt.Sprintf("parameter %s not registered", string(key)))
}
ty := attr.ty
@ -183,7 +183,7 @@ func (s Subspace) Set(ctx sdk.Context, key []byte, param interface{}) {
func (s Subspace) Update(ctx sdk.Context, key []byte, param []byte) error {
attr, ok := s.table.m[string(key)]
if !ok {
panic("Parameter not registered")
panic(fmt.Sprintf("parameter %s not registered", string(key)))
}
ty := attr.ty
@ -227,7 +227,7 @@ func (s Subspace) UpdateWithSubkey(ctx sdk.Context, key []byte, subkey []byte, p
attr, ok := s.table.m[string(concatkey)]
if !ok {
return errors.New("parameter not registered")
return fmt.Errorf("parameter %s not registered", string(key))
}
ty := attr.ty

View File

@ -1,25 +1,121 @@
/*
Package simulation implements a simulation framework for any state machine
built on the SDK which utilizes auth.
Package simulation implements a full fledged Cosmos SDK application used for executing
simulation test suites.
It is primarily intended for fuzz testing the integration of modules. It will
test that the provided operations are interoperable, and that the desired
invariants hold. It can additionally be used to detect what the performance
benchmarks in the system are, by using benchmarking mode and cpu / mem
profiling. If it detects a failure, it provides the entire log of what was ran.
Simulation App
The simulator takes as input: a random seed, the set of operations to run, the
invariants to test, and additional parameters to configure how long to run, and
misc. parameters that affect simulation speed.
The SimApp type defines an application used for running extensive simulation
testing suites. It contains all core modules, including governance, staking,
slashing, and distribution.
It is intended that every module provides a list of Operations which will
randomly create and run a message / tx in a manner that is interesting to fuzz,
and verify that the state transition was executed as exported. Each module
should additionally provide methods to assert that the desired invariants hold.
Simulation is executed with various inputs including the number of blocks to
simulate, the block size, whether the app should commit or not, the invariant
checking period, and a seed which is used as a source of pseudo-randomness.
Then to perform a randomized simulation, select the set of desired operations,
the weightings for each, the invariants you want to test, and how long to run
it for. Then run simulation.Simulate! The simulator will handle things like
ensuring that validators periodically double signing, or go offline.
In addition to the various inputs, simulation runs mainly in three modes:
1. Completely random where the initial state, module parameters and simulation
parameters are pseudo-randomly generated.
2. From a genesis file where the initial state and the module parameters are defined.
This mode is helpful for running simulations on a known state such as a live
network export where a new (mostly likely breaking) version of the application
needs to be tested.
3. From a params file where the initial state is pseudo-randomly generated but the
module and simulation parameters can be provided manually. This allows for a more
controlled and deterministic simulation setup while allowing the state space to
still be pseudo-randomly simulated.
The simulation test suite also supports testing determinism and import/export
functionality.
Randomness
Currently, simulation uses a single seed (integer) as a source for a PRNG by
which all random operations are executed from. Any call to the PRNG changes all
future operations as the internal state of the PRNG is modified. For example,
if a new message type is created and needs to be simulated, the new introduced
PRNG call will change all subsequent operations.
This may can often be problematic when testing fixes to simulation faults. One
current solution to this is to use a params file as mentioned above. In the future
the simulation suite is expected to support a series of PRNGs that can be used
uniquely per module and simulation component so that they will not effect each
others state execution outcome.
Usage
To execute a completely pseudo-random simulation:
$ go test -mod=readonly github.com/cosmos/cosmos-sdk/simapp \
-run=TestFullAppSimulation \
-Enabled=true \
-NumBlocks=100 \
-BlockSize=200 \
-Commit=true \
-Seed=99 \
-Period=5 \
-v -timeout 24h
To execute simulation from a genesis file:
$ go test -mod=readonly github.com/cosmos/cosmos-sdk/simapp \
-run=TestFullAppSimulation \
-Enabled=true \
-NumBlocks=100 \
-BlockSize=200 \
-Commit=true \
-Seed=99 \
-Period=5 \
-Genesis=/path/to/genesis.json \
-v -timeout 24h
To execute simulation from a simulation params file:
$ go test -mod=readonly github.com/cosmos/cosmos-sdk/simapp \
-run=TestFullAppSimulation \
-Enabled=true \
-NumBlocks=100 \
-BlockSize=200 \
-Commit=true \
-Seed=99 \
-Period=5 \
-Params=/path/to/params.json \
-v -timeout 24h
To export the simulation params to a file at a given block height:
$ go test -mod=readonly github.com/cosmos/cosmos-sdk/simapp \
-run=TestFullAppSimulation \
-Enabled=true \
-NumBlocks=100 \
-BlockSize=200 \
-Commit=true \
-Seed=99 \
-Period=5 \
-ExportParamsPath=/path/to/params.json \
-ExportParamsHeight=50 \
-v -timeout 24h
To export the simulation app state (i.e genesis) to a file:
$ go test -mod=readonly github.com/cosmos/cosmos-sdk/simapp \
-run=TestFullAppSimulation \
-Enabled=true \
-NumBlocks=100 \
-BlockSize=200 \
-Commit=true \
-Seed=99 \
-Period=5 \
-ExportStatePath=/path/to/genesis.json \
v -timeout 24h
Params
Params that are provided to simulation from a JSON file are used to used to set
both module parameters and simulation parameters. See sim_test.go for the full
set of parameters that can be provided.
*/
package simulation

View File

@ -2,51 +2,21 @@ package simulation
import (
"encoding/json"
"fmt"
"math/rand"
"time"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// nolint
const (
// Minimum time per block
minTimePerBlock int64 = 10000 / 2
// Maximum time per block
maxTimePerBlock int64 = 10000
// Simulation parameter constants
SendEnabled = "send_enabled"
MaxMemoChars = "max_memo_characters"
TxSigLimit = "tx_sig_limit"
TxSizeCostPerByte = "tx_size_cost_per_byte"
SigVerifyCostED25519 = "sig_verify_cost_ed25519"
SigVerifyCostSECP256K1 = "sig_verify_cost_secp256k1"
DepositParamsMinDeposit = "deposit_params_min_deposit"
VotingParamsVotingPeriod = "voting_params_voting_period"
TallyParamsQuorum = "tally_params_quorum"
TallyParamsThreshold = "tally_params_threshold"
TallyParamsVeto = "tally_params_veto"
UnbondingTime = "unbonding_time"
MaxValidators = "max_validators"
SignedBlocksWindow = "signed_blocks_window"
MinSignedPerWindow = "min_signed_per_window"
DowntimeJailDuration = "downtime_jail_duration"
SlashFractionDoubleSign = "slash_fraction_double_sign"
SlashFractionDowntime = "slash_fraction_downtime"
InflationRateChange = "inflation_rate_change"
Inflation = "inflation"
InflationMax = "inflation_max"
InflationMin = "inflation_min"
GoalBonded = "goal_bonded"
CommunityTax = "community_tax"
BaseProposerReward = "base_proposer_reward"
BonusProposerReward = "bonus_proposer_reward"
)
// TODO explain transitional matrix usage
// TODO: explain transitional matrix usage
var (
// Currently there are 3 different liveness types,
// fully online, spotty connection, offline.
@ -63,97 +33,15 @@ var (
{15, 92, 1},
{0, 3, 99},
})
// ModuleParamSimulator defines module parameter value simulators. All
// values simulated should be within valid acceptable range for the given
// parameter.
ModuleParamSimulator = map[string]func(r *rand.Rand) interface{}{
SendEnabled: func(r *rand.Rand) interface{} {
return r.Int63n(2) == 0
},
MaxMemoChars: func(r *rand.Rand) interface{} {
return uint64(RandIntBetween(r, 100, 200))
},
TxSigLimit: func(r *rand.Rand) interface{} {
return uint64(r.Intn(7) + 1)
},
TxSizeCostPerByte: func(r *rand.Rand) interface{} {
return uint64(RandIntBetween(r, 5, 15))
},
SigVerifyCostED25519: func(r *rand.Rand) interface{} {
return uint64(RandIntBetween(r, 500, 1000))
},
SigVerifyCostSECP256K1: func(r *rand.Rand) interface{} {
return uint64(RandIntBetween(r, 500, 1000))
},
DepositParamsMinDeposit: func(r *rand.Rand) interface{} {
return sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, int64(RandIntBetween(r, 1, 1e3)))}
},
VotingParamsVotingPeriod: func(r *rand.Rand) interface{} {
return time.Duration(RandIntBetween(r, 1, 2*60*60*24*2)) * time.Second
},
TallyParamsQuorum: func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(int64(RandIntBetween(r, 334, 500)), 3)
},
TallyParamsThreshold: func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(int64(RandIntBetween(r, 450, 550)), 3)
},
TallyParamsVeto: func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(int64(RandIntBetween(r, 250, 334)), 3)
},
UnbondingTime: func(r *rand.Rand) interface{} {
return time.Duration(RandIntBetween(r, 60, 60*60*24*3*2)) * time.Second
},
MaxValidators: func(r *rand.Rand) interface{} {
return uint16(r.Intn(250) + 1)
},
SignedBlocksWindow: func(r *rand.Rand) interface{} {
return int64(RandIntBetween(r, 10, 1000))
},
MinSignedPerWindow: func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(int64(r.Intn(10)), 1)
},
DowntimeJailDuration: func(r *rand.Rand) interface{} {
return time.Duration(RandIntBetween(r, 60, 60*60*24)) * time.Second
},
SlashFractionDoubleSign: func(r *rand.Rand) interface{} {
return sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(50) + 1)))
},
SlashFractionDowntime: func(r *rand.Rand) interface{} {
return sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(200) + 1)))
},
InflationRateChange: func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(int64(r.Intn(99)), 2)
},
Inflation: func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(int64(r.Intn(99)), 2)
},
InflationMax: func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(20, 2)
},
InflationMin: func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(7, 2)
},
GoalBonded: func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(67, 2)
},
CommunityTax: func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2))
},
BaseProposerReward: func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2))
},
BonusProposerReward: func(r *rand.Rand) interface{} {
return sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2))
},
}
)
// TODO add description
type (
AppParams map[string]json.RawMessage
ParamSimulator func(r *rand.Rand)
)
// AppParams defines a flat JSON of key/values for all possible configurable
// simulation parameters. It might contain: operation weights, simulation parameters
// and flattened module state parameters (i.e not stored under it's respective module name).
type AppParams map[string]json.RawMessage
// ParamSimulator creates a parameter value from a source of random number
type ParamSimulator func(r *rand.Rand)
// GetOrGenerate attempts to get a given parameter by key from the AppParams
// object. If it exists, it'll be decoded and returned. Otherwise, the provided
@ -167,7 +55,7 @@ func (sp AppParams) GetOrGenerate(cdc *codec.Codec, key string, ptr interface{},
ps(r)
}
// Simulation parameters
// Params define the parameters necessary for running the simulations
type Params struct {
PastEvidenceFraction float64
NumKeys int
@ -177,7 +65,7 @@ type Params struct {
BlockSizeTransitionMatrix TransitionMatrix
}
// Return random simulation parameters
// RandomParams for simulation
func RandomParams(r *rand.Rand) Params {
return Params{
PastEvidenceFraction: r.Float64(),
@ -188,3 +76,32 @@ func RandomParams(r *rand.Rand) Params {
BlockSizeTransitionMatrix: defaultBlockSizeTransitionMatrix,
}
}
//-----------------------------------------------------------------------------
// Param change proposals
// SimValFn function to generate the randomized parameter change value
type SimValFn func(r *rand.Rand) string
// ParamChange defines the object used for simulating parameter change proposals
type ParamChange struct {
Subspace string
Key string
Subkey string
SimValue SimValFn
}
// NewSimParamChange creates a new ParamChange instance
func NewSimParamChange(subspace, key, subkey string, simVal SimValFn) ParamChange {
return ParamChange{
Subspace: subspace,
Key: key,
Subkey: subkey,
SimValue: simVal,
}
}
// ComposedKey creates a new composed key for the param change proposal
func (spc ParamChange) ComposedKey() string {
return fmt.Sprintf("%s/%s/%s", spc.Subspace, spc.Key, spc.Subkey)
}

View File

@ -18,7 +18,8 @@ const (
// shamelessly copied from
// https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-golang#31832326
// Generate a random string of a particular length
// RandStringOfLength generates a random string of a particular length
func RandStringOfLength(r *rand.Rand, n int) string {
b := make([]byte, n)
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
@ -36,7 +37,7 @@ func RandStringOfLength(r *rand.Rand, n int) string {
return string(b)
}
// get a rand positive sdk.Int
// RandPositiveInt get a rand positive sdk.Int
func RandPositiveInt(r *rand.Rand, max sdk.Int) (sdk.Int, error) {
if !max.GT(sdk.OneInt()) {
return sdk.Int{}, errors.New("max too small")
@ -45,7 +46,7 @@ func RandPositiveInt(r *rand.Rand, max sdk.Int) (sdk.Int, error) {
return sdk.NewIntFromBigInt(new(big.Int).Rand(r, max.BigInt())).Add(sdk.OneInt()), nil
}
// Generate a random amount
// RandomAmount generates a random amount
// Note: The range of RandomAmount includes max, and is, in fact, biased to return max as well as 0.
func RandomAmount(r *rand.Rand, max sdk.Int) sdk.Int {
var randInt = big.NewInt(0)
@ -87,9 +88,10 @@ func RandIntBetween(r *rand.Rand, min, max int) int {
return r.Intn(max-min) + min
}
// Derive a new rand deterministically from a rand.
// DeriveRand derives a new Rand deterministically from another random source.
// Unlike rand.New(rand.NewSource(seed)), the result is "more random"
// depending on the source and state of r.
//
// NOTE: not crypto safe.
func DeriveRand(r *rand.Rand) *rand.Rand {
const num = 8 // TODO what's a good number? Too large is too slow.

View File

@ -52,7 +52,7 @@ type Params struct {
// NewParams creates a new Params object
func NewParams(maxEvidenceAge time.Duration, signedBlocksWindow int64,
minSignedPerWindow sdk.Dec, downtimeJailDuration time.Duration,
slashFractionDoubleSign sdk.Dec, slashFractionDowntime sdk.Dec) Params {
slashFractionDoubleSign, slashFractionDowntime sdk.Dec) Params {
return Params{
MaxEvidenceAge: maxEvidenceAge,

View File

@ -2,6 +2,7 @@ package slashing
import (
"encoding/json"
"math/rand"
"github.com/gorilla/mux"
"github.com/spf13/cobra"
@ -12,6 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
sim "github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/slashing/client/cli"
"github.com/cosmos/cosmos-sdk/x/slashing/client/rest"
"github.com/cosmos/cosmos-sdk/x/slashing/internal/types"
@ -80,6 +82,16 @@ func (AppModuleSimulation) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.DecodeStore
}
// GenerateGenesisState creates a randomized GenState of the slashing module.
func (AppModuleSimulation) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// RandomizedParams creates randomized slashing param changes for the simulator.
func (AppModuleSimulation) RandomizedParams(r *rand.Rand) []sim.ParamChange {
return simulation.ParamChanges(r)
}
//____________________________________________________________________________
// AppModule implements an application module for the slashing module.

View File

@ -0,0 +1,93 @@
package simulation
// DONTCOVER
import (
"fmt"
"math/rand"
"time"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/slashing/internal/types"
)
// Simulation parameter constants
const (
SignedBlocksWindow = "signed_blocks_window"
MinSignedPerWindow = "min_signed_per_window"
DowntimeJailDuration = "downtime_jail_duration"
SlashFractionDoubleSign = "slash_fraction_double_sign"
SlashFractionDowntime = "slash_fraction_downtime"
)
// GenSignedBlocksWindow randomized SignedBlocksWindow
func GenSignedBlocksWindow(r *rand.Rand) int64 {
return int64(simulation.RandIntBetween(r, 10, 1000))
}
// GenMinSignedPerWindow randomized MinSignedPerWindow
func GenMinSignedPerWindow(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(int64(r.Intn(10)), 1)
}
// GenDowntimeJailDuration randomized DowntimeJailDuration
func GenDowntimeJailDuration(r *rand.Rand) time.Duration {
return time.Duration(simulation.RandIntBetween(r, 60, 60*60*24)) * time.Second
}
// GenSlashFractionDoubleSign randomized SlashFractionDoubleSign
func GenSlashFractionDoubleSign(r *rand.Rand) sdk.Dec {
return sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(50) + 1)))
}
// GenSlashFractionDowntime randomized SlashFractionDowntime
func GenSlashFractionDowntime(r *rand.Rand) sdk.Dec {
return sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(200) + 1)))
}
// RandomizedGenState generates a random GenesisState for slashing
func RandomizedGenState(simState *module.SimulationState) {
var signedBlocksWindow int64
simState.AppParams.GetOrGenerate(
simState.Cdc, SignedBlocksWindow, &signedBlocksWindow, simState.Rand,
func(r *rand.Rand) { signedBlocksWindow = GenSignedBlocksWindow(r) },
)
var minSignedPerWindow sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, MinSignedPerWindow, &minSignedPerWindow, simState.Rand,
func(r *rand.Rand) { minSignedPerWindow = GenMinSignedPerWindow(r) },
)
var downtimeJailDuration time.Duration
simState.AppParams.GetOrGenerate(
simState.Cdc, DowntimeJailDuration, &downtimeJailDuration, simState.Rand,
func(r *rand.Rand) { downtimeJailDuration = GenDowntimeJailDuration(r) },
)
var slashFractionDoubleSign sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, SlashFractionDoubleSign, &slashFractionDoubleSign, simState.Rand,
func(r *rand.Rand) { slashFractionDoubleSign = GenSlashFractionDoubleSign(r) },
)
var slashFractionDowntime sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, SlashFractionDowntime, &slashFractionDowntime, simState.Rand,
func(r *rand.Rand) { slashFractionDowntime = GenSlashFractionDowntime(r) },
)
params := types.NewParams(
simState.UnbondTime, signedBlocksWindow, minSignedPerWindow,
downtimeJailDuration, slashFractionDoubleSign, slashFractionDowntime,
)
slashingGenesis := types.NewGenesisState(params, nil, nil)
fmt.Printf("Selected randomly generated slashing parameters:\n%s\n", codec.MustMarshalJSONIndent(simState.Cdc, slashingGenesis.Params))
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(slashingGenesis)
}

View File

@ -0,0 +1,39 @@
package simulation
// DONTCOVER
import (
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/slashing/internal/types"
)
const (
keySignedBlocksWindow = "SignedBlocksWindow"
keyMinSignedPerWindow = "MinSignedPerWindow"
keySlashFractionDowntime = "SlashFractionDowntime"
)
// ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation
func ParamChanges(r *rand.Rand) []simulation.ParamChange {
return []simulation.ParamChange{
simulation.NewSimParamChange(types.ModuleName, keySignedBlocksWindow, "",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", GenSignedBlocksWindow(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyMinSignedPerWindow, "",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenMinSignedPerWindow(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keySlashFractionDowntime, "",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenSlashFractionDowntime(r))
},
),
}
}

View File

@ -2,6 +2,7 @@ package staking
import (
"encoding/json"
"math/rand"
"github.com/gorilla/mux"
"github.com/spf13/cobra"
@ -16,6 +17,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
sim "github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/staking/client/cli"
"github.com/cosmos/cosmos-sdk/x/staking/client/rest"
"github.com/cosmos/cosmos-sdk/x/staking/simulation"
@ -105,6 +107,16 @@ func (AppModuleSimulation) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.DecodeStore
}
// GenerateGenesisState creates a randomized GenState of the staking module.
func (AppModuleSimulation) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// RandomizedParams creates randomized staking param changes for the simulator.
func (AppModuleSimulation) RandomizedParams(r *rand.Rand) []sim.ParamChange {
return simulation.ParamChanges(r)
}
//____________________________________________________________________________
// AppModule implements an application module for the staking module.

View File

@ -0,0 +1,78 @@
package simulation
// DONTCOVER
import (
"fmt"
"math/rand"
"time"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
// Simulation parameter constants
const (
UnbondingTime = "unbonding_time"
MaxValidators = "max_validators"
)
// GenUnbondingTime randomized UnbondingTime
func GenUnbondingTime(r *rand.Rand) (ubdTime time.Duration) {
return time.Duration(simulation.RandIntBetween(r, 60, 60*60*24*3*2)) * time.Second
}
// GenMaxValidators randomized MaxValidators
func GenMaxValidators(r *rand.Rand) (maxValidators uint16) {
return uint16(r.Intn(250) + 1)
}
// RandomizedGenState generates a random GenesisState for staking
func RandomizedGenState(simState *module.SimulationState) {
// params
var unbondTime time.Duration
simState.AppParams.GetOrGenerate(
simState.Cdc, UnbondingTime, &unbondTime, simState.Rand,
func(r *rand.Rand) { unbondTime = GenUnbondingTime(r) },
)
var maxValidators uint16
simState.AppParams.GetOrGenerate(
simState.Cdc, MaxValidators, &maxValidators, simState.Rand,
func(r *rand.Rand) { maxValidators = GenMaxValidators(r) },
)
// NOTE: the slashing module need to be defined after the staking module on the
// NewSimulationManager constructor for this to work
simState.UnbondTime = unbondTime
params := types.NewParams(simState.UnbondTime, maxValidators, 7, sdk.DefaultBondDenom)
// validators & delegations
var (
validators []types.Validator
delegations []types.Delegation
)
valAddrs := make([]sdk.ValAddress, simState.NumBonded)
for i := 0; i < int(simState.NumBonded); i++ {
valAddr := sdk.ValAddress(simState.Accounts[i].Address)
valAddrs[i] = valAddr
validator := types.NewValidator(valAddr, simState.Accounts[i].PubKey, types.Description{})
validator.Tokens = sdk.NewInt(simState.InitialStake)
validator.DelegatorShares = sdk.NewDec(simState.InitialStake)
delegation := types.NewDelegation(simState.Accounts[i].Address, valAddr, sdk.NewDec(simState.InitialStake))
validators = append(validators, validator)
delegations = append(delegations, delegation)
}
stakingGenesis := types.NewGenesisState(params, validators, delegations)
fmt.Printf("Selected randomly generated staking parameters:\n%s\n", codec.MustMarshalJSONIndent(simState.Cdc, stakingGenesis.Params))
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(stakingGenesis)
}

View File

@ -0,0 +1,33 @@
package simulation
// DONTCOVER
import (
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
const (
keyMaxValidators = "MaxValidators"
keyUnbondingTime = "UnbondingTime"
)
// ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation
func ParamChanges(r *rand.Rand) []simulation.ParamChange {
return []simulation.ParamChange{
simulation.NewSimParamChange(types.ModuleName, keyMaxValidators, "",
func(r *rand.Rand) string {
return fmt.Sprintf("%d", GenMaxValidators(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyUnbondingTime, "",
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", GenUnbondingTime(r))
},
),
}
}

View File

@ -2,6 +2,7 @@ package supply
import (
"encoding/json"
"math/rand"
"github.com/gorilla/mux"
"github.com/spf13/cobra"
@ -12,6 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
sim "github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/supply/client/cli"
"github.com/cosmos/cosmos-sdk/x/supply/client/rest"
"github.com/cosmos/cosmos-sdk/x/supply/internal/types"
@ -21,7 +23,7 @@ import (
var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleSimulation = AppModuleSimulation{}
_ module.AppModuleSimulation = AppModule{}
)
// AppModuleBasic defines the basic application module used by the supply module.
@ -76,6 +78,16 @@ func (AppModuleSimulation) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.DecodeStore
}
// GenerateGenesisState creates a randomized GenState of the supply module.
func (AppModuleSimulation) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// RandomizedParams doesn't create any randomized supply param changes for the simulator.
func (AppModuleSimulation) RandomizedParams(_ *rand.Rand) []sim.ParamChange {
return nil
}
//____________________________________________________________________________
// AppModule implements an application module for the supply module.

View File

@ -0,0 +1,23 @@
package simulation
// DONTCOVER
import (
"fmt"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/supply/internal/types"
)
// RandomizedGenState generates a random GenesisState for supply
func RandomizedGenState(simState *module.SimulationState) {
numAccs := int64(len(simState.Accounts))
totalSupply := sdk.NewInt(simState.InitialStake * (numAccs + simState.NumBonded))
supplyGenesis := types.NewGenesisState(sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, totalSupply)))
fmt.Printf("Generated supply parameters:\n%s\n", codec.MustMarshalJSONIndent(simState.Cdc, supplyGenesis))
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(supplyGenesis)
}