Merge PR #4435: Simulation: Params from File
* Move distr params to simulation param generator * Cleanup sim params output * Print params when possible instead of entire genesis struct * Update module param simulator keys * Rename module params simulator keys * Add/fix missing module params and implement SimParams * UPdate sim test to accept params file * Allow weights to be provided from file * Create doc.go * Remove TODO * Implement MustMarshalJSONIndent * Use mustMarshalJSONIndent for non-codec * Remove TODO * Fix doc.go * Update points * Update simapp/doc.go Co-Authored-By: Alessio Treglia <quadrispro@ubuntu.com> * Update simapp/doc.go Co-Authored-By: Alessio Treglia <quadrispro@ubuntu.com> * Cleanup appStateFn * Use constants for simulation parameter keys * Update msgs.go * minor formatting
This commit is contained in:
parent
b4eb4a9e64
commit
6606007297
|
@ -3,6 +3,7 @@ package codec
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
amino "github.com/tendermint/go-amino"
|
||||
cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino"
|
||||
|
@ -35,6 +36,16 @@ func MarshalJSONIndent(cdc *Codec, obj interface{}) ([]byte, error) {
|
|||
return out.Bytes(), nil
|
||||
}
|
||||
|
||||
// MustMarshalJSONIndent executes MarshalJSONIndent except it panics upon failure.
|
||||
func MustMarshalJSONIndent(cdc *Codec, obj interface{}) []byte {
|
||||
bz, err := MarshalJSONIndent(cdc, obj)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to marshal JSON: %s", err))
|
||||
}
|
||||
|
||||
return bz
|
||||
}
|
||||
|
||||
//__________________________________________________________________
|
||||
|
||||
// generic sealed codec to be used throughout sdk
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
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 \
|
||||
-SimulationEnabled=true \
|
||||
-SimulationNumBlocks=100 \
|
||||
-SimulationBlockSize=200 \
|
||||
-SimulationCommit=true \
|
||||
-SimulationSeed=99 \
|
||||
-SimulationPeriod=5 \
|
||||
-v -timeout 24h
|
||||
|
||||
To execute simulation from a genesis file:
|
||||
|
||||
$ go test -mod=readonly github.com/cosmos/cosmos-sdk/simapp \
|
||||
-run=TestFullAppSimulation \
|
||||
-SimulationEnabled=true \
|
||||
-SimulationNumBlocks=100 \
|
||||
-SimulationBlockSize=200 \
|
||||
-SimulationCommit=true \
|
||||
-SimulationSeed=99 \
|
||||
-SimulationPeriod=5 \
|
||||
-SimulationGenesis=/path/to/genesis.json \
|
||||
-v -timeout 24h
|
||||
|
||||
To execute simulation from a params file:
|
||||
|
||||
$ go test -mod=readonly github.com/cosmos/cosmos-sdk/simapp \
|
||||
-run=TestFullAppSimulation \
|
||||
-SimulationEnabled=true \
|
||||
-SimulationNumBlocks=100 \
|
||||
-SimulationBlockSize=200 \
|
||||
-SimulationCommit=true \
|
||||
-SimulationSeed=99 \
|
||||
-SimulationPeriod=5 \
|
||||
-SimulationParams=/path/to/params.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
|
|
@ -0,0 +1,23 @@
|
|||
package simapp
|
||||
|
||||
// Simulation parameter constants
|
||||
const (
|
||||
StakePerAccount = "stake_per_account"
|
||||
InitiallyBondedValidators = "initially_bonded_validators"
|
||||
OpWeightDeductFee = "op_weight_deduct_fee"
|
||||
OpWeightMsgSend = "op_weight_msg_send"
|
||||
OpWeightSingleInputMsgMultiSend = "op_weight_single_input_msg_multisend"
|
||||
OpWeightMsgSetWithdrawAddress = "op_weight_msg_set_withdraw_address"
|
||||
OpWeightMsgWithdrawDelegationReward = "op_weight_msg_withdraw_delegation_reward"
|
||||
OpWeightMsgWithdrawValidatorCommission = "op_weight_msg_withdraw_validator_commission"
|
||||
OpWeightSubmitVotingSlashingTextProposal = "op_weight_submit_voting_slashing_text_proposal"
|
||||
OpWeightSubmitVotingSlashingCommunitySpendProposal = "op_weight_submit_voting_slashing_community_spend_proposal"
|
||||
OpWeightSubmitVotingSlashingParamChangeProposal = "op_weight_submit_voting_slashing_param_change_proposal"
|
||||
OpWeightMsgDeposit = "op_weight_msg_deposit"
|
||||
OpWeightMsgCreateValidator = "op_weight_msg_create_validator"
|
||||
OpWeightMsgEditValidator = "op_weight_msg_edit_validator"
|
||||
OpWeightMsgDelegate = "op_weight_msg_delegate"
|
||||
OpWeightMsgUndelegate = "op_weight_msg_undelegate"
|
||||
OpWeightMsgBeginRedelegate = "op_weight_msg_begin_redelegate"
|
||||
OpWeightMsgUnjail = "op_weight_msg_unjail"
|
||||
)
|
|
@ -20,6 +20,7 @@ import (
|
|||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/genaccounts"
|
||||
|
@ -41,6 +42,7 @@ import (
|
|||
|
||||
var (
|
||||
genesisFile string
|
||||
paramsFile string
|
||||
seed int64
|
||||
numBlocks int
|
||||
blockSize int
|
||||
|
@ -53,7 +55,8 @@ var (
|
|||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&genesisFile, "SimulationGenesis", "", "custom simulation genesis file")
|
||||
flag.StringVar(&genesisFile, "SimulationGenesis", "", "custom simulation genesis file; cannot be used with params file")
|
||||
flag.StringVar(¶msFile, "SimulationParams", "", "custom simulation params file which overrides any random params; cannot be used with genesis")
|
||||
flag.Int64Var(&seed, "SimulationSeed", 42, "simulation random seed")
|
||||
flag.IntVar(&numBlocks, "SimulationNumBlocks", 500, "number of blocks")
|
||||
flag.IntVar(&blockSize, "SimulationBlockSize", 200, "operations per block")
|
||||
|
@ -74,18 +77,23 @@ func getSimulateFromSeedInput(tb testing.TB, w io.Writer, app *SimApp) (
|
|||
testAndRunTxs(app), invariants(app), numBlocks, blockSize, commit, lean, onOperation
|
||||
}
|
||||
|
||||
func appStateFromGenesisFileFn(r *rand.Rand, accs []simulation.Account, genesisTimestamp time.Time,
|
||||
func appStateFromGenesisFileFn(
|
||||
r *rand.Rand, _ []simulation.Account, _ time.Time,
|
||||
) (json.RawMessage, []simulation.Account, string) {
|
||||
|
||||
var genesis tmtypes.GenesisDoc
|
||||
cdc := MakeCodec()
|
||||
|
||||
bytes, err := ioutil.ReadFile(genesisFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cdc.MustUnmarshalJSON(bytes, &genesis)
|
||||
|
||||
var appState GenesisState
|
||||
cdc.MustUnmarshalJSON(genesis.AppState, &appState)
|
||||
|
||||
accounts := genaccounts.GetGenesisStateFromAppState(cdc, appState)
|
||||
|
||||
var newAccs []simulation.Account
|
||||
|
@ -95,29 +103,168 @@ func appStateFromGenesisFileFn(r *rand.Rand, accs []simulation.Account, genesisT
|
|||
// and these keys are never actually used to sign by mock Tendermint.
|
||||
privkeySeed := make([]byte, 15)
|
||||
r.Read(privkeySeed)
|
||||
|
||||
privKey := secp256k1.GenPrivKeySecp256k1(privkeySeed)
|
||||
newAccs = append(newAccs, simulation.Account{privKey, privKey.PubKey(), acc.Address})
|
||||
}
|
||||
|
||||
return genesis.AppState, newAccs, genesis.ChainID
|
||||
}
|
||||
|
||||
// TODO refactor out random initialization code to the modules
|
||||
func appStateRandomizedFn(r *rand.Rand, accs []simulation.Account, genesisTimestamp time.Time,
|
||||
func appStateRandomizedFn(
|
||||
r *rand.Rand, accs []simulation.Account, genesisTimestamp time.Time, appParams simulation.AppParams,
|
||||
) (json.RawMessage, []simulation.Account, string) {
|
||||
|
||||
var genesisAccounts []genaccounts.GenesisAccount
|
||||
genesisState := NewDefaultGenesisState()
|
||||
cdc := MakeCodec()
|
||||
genesisState := NewDefaultGenesisState()
|
||||
|
||||
var (
|
||||
amount int64
|
||||
numInitiallyBonded int64
|
||||
)
|
||||
|
||||
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)) })
|
||||
|
||||
amount := int64(r.Intn(1e12))
|
||||
numInitiallyBonded := int64(r.Intn(250))
|
||||
numAccs := int64(len(accs))
|
||||
if numInitiallyBonded > numAccs {
|
||||
numInitiallyBonded = numAccs
|
||||
}
|
||||
fmt.Printf("Selected randomly generated parameters for simulated genesis:\n"+
|
||||
"\t{amount of stake per account: %v, initially bonded validators: %v}\n",
|
||||
amount, numInitiallyBonded)
|
||||
|
||||
fmt.Printf(
|
||||
`Selected randomly generated parameters for simulated genesis:
|
||||
{
|
||||
stake_per_account: "%v",
|
||||
initially_bonded_validators: "%v"
|
||||
}
|
||||
`, amount, numInitiallyBonded,
|
||||
)
|
||||
|
||||
genGenesisAccounts(cdc, r, accs, genesisTimestamp, amount, numInitiallyBonded, genesisState)
|
||||
genAuthGenesisState(cdc, r, appParams, genesisState)
|
||||
genBankGenesisState(cdc, r, appParams, genesisState)
|
||||
genGovGenesisState(cdc, r, appParams, genesisState)
|
||||
genMintGenesisState(cdc, r, appParams, genesisState)
|
||||
genDistrGenesisState(cdc, r, appParams, genesisState)
|
||||
stakingGen := genStakingGenesisState(cdc, r, accs, amount, numAccs, numInitiallyBonded, appParams, genesisState)
|
||||
genSlashingGenesisState(cdc, r, stakingGen, appParams, genesisState)
|
||||
|
||||
appState, err := MakeCodec().MarshalJSON(genesisState)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return appState, accs, "simulation"
|
||||
}
|
||||
|
||||
func appStateFn(
|
||||
r *rand.Rand, accs []simulation.Account, genesisTimestamp time.Time,
|
||||
) (appState json.RawMessage, simAccs []simulation.Account, chainID string) {
|
||||
|
||||
cdc := MakeCodec()
|
||||
|
||||
switch {
|
||||
case paramsFile != "" && genesisFile != "":
|
||||
panic("cannot provide both a genesis file and a params file")
|
||||
|
||||
case genesisFile != "":
|
||||
appState, simAccs, chainID = appStateFromGenesisFileFn(r, accs, genesisTimestamp)
|
||||
|
||||
case paramsFile != "":
|
||||
appParams := make(simulation.AppParams)
|
||||
bz, err := ioutil.ReadFile(paramsFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cdc.MustUnmarshalJSON(bz, &appParams)
|
||||
appState, simAccs, chainID = appStateRandomizedFn(r, accs, genesisTimestamp, appParams)
|
||||
|
||||
default:
|
||||
appParams := make(simulation.AppParams)
|
||||
appState, simAccs, chainID = appStateRandomizedFn(r, accs, genesisTimestamp, appParams)
|
||||
}
|
||||
|
||||
return appState, simAccs, chainID
|
||||
}
|
||||
|
||||
func genAuthGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, genesisState map[string]json.RawMessage) {
|
||||
authGenesis := auth.NewGenesisState(
|
||||
nil,
|
||||
auth.NewParams(
|
||||
func(r *rand.Rand) uint64 {
|
||||
var v uint64
|
||||
ap.GetOrGenerate(cdc, simulation.MaxMemoChars, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.MaxMemoChars](r).(uint64)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
func(r *rand.Rand) uint64 {
|
||||
var v uint64
|
||||
ap.GetOrGenerate(cdc, simulation.TxSigLimit, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.TxSigLimit](r).(uint64)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
func(r *rand.Rand) uint64 {
|
||||
var v uint64
|
||||
ap.GetOrGenerate(cdc, simulation.TxSizeCostPerByte, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.TxSizeCostPerByte](r).(uint64)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
func(r *rand.Rand) uint64 {
|
||||
var v uint64
|
||||
ap.GetOrGenerate(cdc, simulation.SigVerifyCostED25519, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.SigVerifyCostED25519](r).(uint64)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
func(r *rand.Rand) uint64 {
|
||||
var v uint64
|
||||
ap.GetOrGenerate(cdc, simulation.SigVerifyCostSECP256K1, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.SigVerifyCostSECP256K1](r).(uint64)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
),
|
||||
)
|
||||
|
||||
fmt.Printf("Selected randomly generated auth parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, authGenesis.Params))
|
||||
genesisState[auth.ModuleName] = cdc.MustMarshalJSON(authGenesis)
|
||||
}
|
||||
|
||||
func genBankGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, genesisState map[string]json.RawMessage) {
|
||||
bankGenesis := bank.NewGenesisState(
|
||||
func(r *rand.Rand) bool {
|
||||
var v bool
|
||||
ap.GetOrGenerate(cdc, simulation.SendEnabled, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.SendEnabled](r).(bool)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
)
|
||||
|
||||
fmt.Printf("Selected randomly generated bank parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, bankGenesis))
|
||||
genesisState[bank.ModuleName] = cdc.MustMarshalJSON(bankGenesis)
|
||||
}
|
||||
|
||||
func 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 {
|
||||
|
@ -137,8 +284,7 @@ func appStateRandomizedFn(r *rand.Rand, accs []simulation.Account, genesisTimest
|
|||
|
||||
startTime := genesisTimestamp.Unix()
|
||||
|
||||
// Allow for some vesting accounts to vest very quickly while others very
|
||||
// slowly.
|
||||
// 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 {
|
||||
|
@ -168,84 +314,239 @@ func appStateRandomizedFn(r *rand.Rand, accs []simulation.Account, genesisTimest
|
|||
}
|
||||
|
||||
genesisState[genaccounts.ModuleName] = cdc.MustMarshalJSON(genesisAccounts)
|
||||
}
|
||||
|
||||
authGenesis := auth.NewGenesisState(
|
||||
nil,
|
||||
auth.NewParams(
|
||||
simulation.ModuleParamSimulator["MaxMemoCharacters"](r).(uint64),
|
||||
simulation.ModuleParamSimulator["TxSigLimit"](r).(uint64),
|
||||
simulation.ModuleParamSimulator["TxSizeCostPerByte"](r).(uint64),
|
||||
simulation.ModuleParamSimulator["SigVerifyCostED25519"](r).(uint64),
|
||||
simulation.ModuleParamSimulator["SigVerifyCostSecp256k1"](r).(uint64),
|
||||
),
|
||||
)
|
||||
fmt.Printf("Selected randomly generated auth parameters:\n\t%+v\n", authGenesis)
|
||||
genesisState[auth.ModuleName] = cdc.MustMarshalJSON(authGenesis)
|
||||
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)
|
||||
})
|
||||
|
||||
bankGenesis := bank.NewGenesisState(r.Int63n(2) == 0)
|
||||
genesisState[bank.ModuleName] = cdc.MustMarshalJSON(bankGenesis)
|
||||
fmt.Printf("Selected randomly generated bank parameters:\n\t%+v\n", bankGenesis)
|
||||
|
||||
// Random genesis states
|
||||
vp := simulation.ModuleParamSimulator["VotingParams/VotingPeriod"](r).(time.Duration)
|
||||
govGenesis := gov.NewGenesisState(
|
||||
uint64(r.Intn(100)),
|
||||
gov.NewDepositParams(
|
||||
simulation.ModuleParamSimulator["DepositParams/MinDeposit"](r).(sdk.Coins),
|
||||
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(
|
||||
simulation.ModuleParamSimulator["TallyParams/Quorum"](r).(sdk.Dec),
|
||||
simulation.ModuleParamSimulator["TallyParams/Threshold"](r).(sdk.Dec),
|
||||
simulation.ModuleParamSimulator["TallyParams/Veto"](r).(sdk.Dec),
|
||||
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)
|
||||
fmt.Printf("Selected randomly generated governance parameters:\n\t%+v\n", govGenesis)
|
||||
}
|
||||
|
||||
func genMintGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, genesisState map[string]json.RawMessage) {
|
||||
mintGenesis := mint.NewGenesisState(
|
||||
mint.InitialMinter(
|
||||
func(r *rand.Rand) sdk.Dec {
|
||||
var v sdk.Dec
|
||||
ap.GetOrGenerate(cdc, simulation.Inflation, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.Inflation](r).(sdk.Dec)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
),
|
||||
mint.NewParams(
|
||||
sdk.DefaultBondDenom,
|
||||
func(r *rand.Rand) sdk.Dec {
|
||||
var v sdk.Dec
|
||||
ap.GetOrGenerate(cdc, simulation.InflationRateChange, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.InflationRateChange](r).(sdk.Dec)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
func(r *rand.Rand) sdk.Dec {
|
||||
var v sdk.Dec
|
||||
ap.GetOrGenerate(cdc, simulation.InflationMax, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.InflationMax](r).(sdk.Dec)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
func(r *rand.Rand) sdk.Dec {
|
||||
var v sdk.Dec
|
||||
ap.GetOrGenerate(cdc, simulation.InflationMin, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.InflationMin](r).(sdk.Dec)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
func(r *rand.Rand) sdk.Dec {
|
||||
var v sdk.Dec
|
||||
ap.GetOrGenerate(cdc, simulation.GoalBonded, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.GoalBonded](r).(sdk.Dec)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
uint64(60*60*8766/5),
|
||||
),
|
||||
)
|
||||
|
||||
fmt.Printf("Selected randomly generated minting parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, mintGenesis.Params))
|
||||
genesisState[mint.ModuleName] = cdc.MustMarshalJSON(mintGenesis)
|
||||
}
|
||||
|
||||
func genDistrGenesisState(cdc *codec.Codec, r *rand.Rand, ap simulation.AppParams, genesisState map[string]json.RawMessage) {
|
||||
distrGenesis := distr.GenesisState{
|
||||
FeePool: distr.InitialFeePool(),
|
||||
CommunityTax: func(r *rand.Rand) sdk.Dec {
|
||||
var v sdk.Dec
|
||||
ap.GetOrGenerate(cdc, simulation.CommunityTax, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.CommunityTax](r).(sdk.Dec)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
BaseProposerReward: func(r *rand.Rand) sdk.Dec {
|
||||
var v sdk.Dec
|
||||
ap.GetOrGenerate(cdc, simulation.BaseProposerReward, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.BaseProposerReward](r).(sdk.Dec)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
BonusProposerReward: func(r *rand.Rand) sdk.Dec {
|
||||
var v sdk.Dec
|
||||
ap.GetOrGenerate(cdc, simulation.BonusProposerReward, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.BonusProposerReward](r).(sdk.Dec)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
}
|
||||
|
||||
fmt.Printf("Selected randomly generated distribution parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, distrGenesis))
|
||||
genesisState[distr.ModuleName] = cdc.MustMarshalJSON(distrGenesis)
|
||||
}
|
||||
|
||||
func genSlashingGenesisState(
|
||||
cdc *codec.Codec, r *rand.Rand, stakingGen staking.GenesisState,
|
||||
ap simulation.AppParams, genesisState map[string]json.RawMessage,
|
||||
) {
|
||||
slashingGenesis := slashing.NewGenesisState(
|
||||
slashing.NewParams(
|
||||
stakingGen.Params.UnbondingTime,
|
||||
func(r *rand.Rand) int64 {
|
||||
var v int64
|
||||
ap.GetOrGenerate(cdc, simulation.SignedBlocksWindow, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.SignedBlocksWindow](r).(int64)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
func(r *rand.Rand) sdk.Dec {
|
||||
var v sdk.Dec
|
||||
ap.GetOrGenerate(cdc, simulation.MinSignedPerWindow, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.MinSignedPerWindow](r).(sdk.Dec)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
func(r *rand.Rand) time.Duration {
|
||||
var v time.Duration
|
||||
ap.GetOrGenerate(cdc, simulation.DowntimeJailDuration, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.DowntimeJailDuration](r).(time.Duration)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
func(r *rand.Rand) sdk.Dec {
|
||||
var v sdk.Dec
|
||||
ap.GetOrGenerate(cdc, simulation.SlashFractionDoubleSign, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.SlashFractionDoubleSign](r).(sdk.Dec)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
func(r *rand.Rand) sdk.Dec {
|
||||
var v sdk.Dec
|
||||
ap.GetOrGenerate(cdc, simulation.SlashFractionDowntime, &v, r,
|
||||
func(r *rand.Rand) {
|
||||
v = simulation.ModuleParamSimulator[simulation.SlashFractionDowntime](r).(sdk.Dec)
|
||||
})
|
||||
return v
|
||||
}(r),
|
||||
),
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
fmt.Printf("Selected randomly generated slashing parameters:\n%s\n", codec.MustMarshalJSONIndent(cdc, slashingGenesis.Params))
|
||||
genesisState[slashing.ModuleName] = cdc.MustMarshalJSON(slashingGenesis)
|
||||
}
|
||||
|
||||
func genStakingGenesisState(
|
||||
cdc *codec.Codec, r *rand.Rand, accs []simulation.Account, amount, numAccs, numInitiallyBonded int64,
|
||||
ap simulation.AppParams, genesisState map[string]json.RawMessage,
|
||||
) staking.GenesisState {
|
||||
|
||||
stakingGenesis := staking.NewGenesisState(
|
||||
staking.InitialPool(),
|
||||
staking.NewParams(
|
||||
simulation.ModuleParamSimulator["UnbondingTime"](r).(time.Duration),
|
||||
simulation.ModuleParamSimulator["MaxValidators"](r).(uint16),
|
||||
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,
|
||||
)
|
||||
fmt.Printf("Selected randomly generated staking parameters:\n\t%+v\n", stakingGenesis)
|
||||
|
||||
slashingParams := slashing.NewParams(
|
||||
stakingGenesis.Params.UnbondingTime,
|
||||
simulation.ModuleParamSimulator["SignedBlocksWindow"](r).(int64),
|
||||
simulation.ModuleParamSimulator["MinSignedPerWindow"](r).(sdk.Dec),
|
||||
simulation.ModuleParamSimulator["DowntimeJailDuration"](r).(time.Duration),
|
||||
simulation.ModuleParamSimulator["SlashFractionDoubleSign"](r).(sdk.Dec),
|
||||
simulation.ModuleParamSimulator["SlashFractionDowntime"](r).(sdk.Dec),
|
||||
var (
|
||||
validators []staking.Validator
|
||||
delegations []staking.Delegation
|
||||
)
|
||||
slashingGenesis := slashing.NewGenesisState(slashingParams, nil, nil)
|
||||
genesisState[slashing.ModuleName] = cdc.MustMarshalJSON(slashingGenesis)
|
||||
fmt.Printf("Selected randomly generated slashing parameters:\n\t%+v\n", slashingGenesis)
|
||||
|
||||
mintGenesis := mint.NewGenesisState(
|
||||
mint.InitialMinter(
|
||||
sdk.NewDecWithPrec(int64(r.Intn(99)), 2)),
|
||||
mint.NewParams(
|
||||
sdk.DefaultBondDenom,
|
||||
simulation.ModuleParamSimulator["InflationRateChange"](r).(sdk.Dec),
|
||||
simulation.ModuleParamSimulator["InflationMax"](r).(sdk.Dec),
|
||||
simulation.ModuleParamSimulator["InflationMin"](r).(sdk.Dec),
|
||||
simulation.ModuleParamSimulator["GoalBonded"](r).(sdk.Dec),
|
||||
uint64(60*60*8766/5),
|
||||
),
|
||||
)
|
||||
genesisState[mint.ModuleName] = cdc.MustMarshalJSON(mintGenesis)
|
||||
fmt.Printf("Selected randomly generated minting parameters:\n\t%+v\n", mintGenesis)
|
||||
|
||||
var validators []staking.Validator
|
||||
var delegations []staking.Delegation
|
||||
|
||||
valAddrs := make([]sdk.ValAddress, numInitiallyBonded)
|
||||
for i := 0; i < int(numInitiallyBonded); i++ {
|
||||
|
@ -255,7 +556,7 @@ func appStateRandomizedFn(r *rand.Rand, accs []simulation.Account, genesisTimest
|
|||
validator := staking.NewValidator(valAddr, accs[i].PubKey, staking.Description{})
|
||||
validator.Tokens = sdk.NewInt(amount)
|
||||
validator.DelegatorShares = sdk.NewDec(amount)
|
||||
delegation := staking.Delegation{accs[i].Address, valAddr, sdk.NewDec(amount)}
|
||||
delegation := staking.NewDelegation(accs[i].Address, valAddr, sdk.NewDec(amount))
|
||||
validators = append(validators, validator)
|
||||
delegations = append(delegations, delegation)
|
||||
}
|
||||
|
@ -263,54 +564,203 @@ func appStateRandomizedFn(r *rand.Rand, accs []simulation.Account, genesisTimest
|
|||
stakingGenesis.Pool.NotBondedTokens = sdk.NewInt((amount * numAccs) + (numInitiallyBonded * amount))
|
||||
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)
|
||||
|
||||
// TODO make use NewGenesisState
|
||||
distrGenesis := distr.GenesisState{
|
||||
FeePool: distr.InitialFeePool(),
|
||||
CommunityTax: sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2)),
|
||||
BaseProposerReward: sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2)),
|
||||
BonusProposerReward: sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2)),
|
||||
return stakingGenesis
|
||||
}
|
||||
genesisState[distr.ModuleName] = cdc.MustMarshalJSON(distrGenesis)
|
||||
fmt.Printf("Selected randomly generated distribution parameters:\n\t%+v\n", distrGenesis)
|
||||
|
||||
// Marshal genesis
|
||||
appState, err := MakeCodec().MarshalJSON(genesisState)
|
||||
func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
|
||||
cdc := MakeCodec()
|
||||
ap := make(simulation.AppParams)
|
||||
|
||||
if paramsFile != "" {
|
||||
bz, err := ioutil.ReadFile(paramsFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return appState, accs, "simulation"
|
||||
cdc.MustUnmarshalJSON(bz, &ap)
|
||||
}
|
||||
|
||||
func appStateFn(r *rand.Rand, accs []simulation.Account, genesisTimestamp time.Time,
|
||||
) (json.RawMessage, []simulation.Account, string) {
|
||||
|
||||
if genesisFile != "" {
|
||||
return appStateFromGenesisFileFn(r, accs, genesisTimestamp)
|
||||
}
|
||||
return appStateRandomizedFn(r, accs, genesisTimestamp)
|
||||
}
|
||||
|
||||
func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
|
||||
return []simulation.WeightedOperation{
|
||||
{5, authsim.SimulateDeductFee(app.accountKeeper, app.feeCollectionKeeper)},
|
||||
{100, banksim.SimulateMsgSend(app.accountKeeper, app.bankKeeper)},
|
||||
{10, banksim.SimulateSingleInputMsgMultiSend(app.accountKeeper, app.bankKeeper)},
|
||||
{50, distrsim.SimulateMsgSetWithdrawAddress(app.accountKeeper, app.distrKeeper)},
|
||||
{50, distrsim.SimulateMsgWithdrawDelegatorReward(app.accountKeeper, app.distrKeeper)},
|
||||
{50, distrsim.SimulateMsgWithdrawValidatorCommission(app.accountKeeper, app.distrKeeper)},
|
||||
{5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, govsim.SimulateTextProposalContent)},
|
||||
{5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, distrsim.SimulateCommunityPoolSpendProposalContent(app.distrKeeper))},
|
||||
{5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, paramsim.SimulateParamChangeProposalContent)},
|
||||
{100, govsim.SimulateMsgDeposit(app.govKeeper)},
|
||||
{100, stakingsim.SimulateMsgCreateValidator(app.accountKeeper, app.stakingKeeper)},
|
||||
{5, stakingsim.SimulateMsgEditValidator(app.stakingKeeper)},
|
||||
{100, stakingsim.SimulateMsgDelegate(app.accountKeeper, app.stakingKeeper)},
|
||||
{100, stakingsim.SimulateMsgUndelegate(app.accountKeeper, app.stakingKeeper)},
|
||||
{100, stakingsim.SimulateMsgBeginRedelegate(app.accountKeeper, app.stakingKeeper)},
|
||||
{100, slashingsim.SimulateMsgUnjail(app.slashingKeeper)},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightDeductFee, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 5
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
authsim.SimulateDeductFee(app.accountKeeper, app.feeCollectionKeeper),
|
||||
},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightMsgSend, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 100
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
banksim.SimulateMsgSend(app.accountKeeper, app.bankKeeper),
|
||||
},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightSingleInputMsgMultiSend, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 10
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
banksim.SimulateSingleInputMsgMultiSend(app.accountKeeper, app.bankKeeper),
|
||||
},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightMsgSetWithdrawAddress, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 50
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
distrsim.SimulateMsgSetWithdrawAddress(app.accountKeeper, app.distrKeeper),
|
||||
},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightMsgWithdrawDelegationReward, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 50
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
distrsim.SimulateMsgWithdrawDelegatorReward(app.accountKeeper, app.distrKeeper),
|
||||
},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightMsgWithdrawValidatorCommission, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 50
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
distrsim.SimulateMsgWithdrawValidatorCommission(app.accountKeeper, app.distrKeeper),
|
||||
},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightSubmitVotingSlashingTextProposal, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 5
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, govsim.SimulateTextProposalContent),
|
||||
},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightSubmitVotingSlashingCommunitySpendProposal, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 5
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, distrsim.SimulateCommunityPoolSpendProposalContent(app.distrKeeper)),
|
||||
},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightSubmitVotingSlashingParamChangeProposal, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 5
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, paramsim.SimulateParamChangeProposalContent),
|
||||
},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightMsgDeposit, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 100
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
govsim.SimulateMsgDeposit(app.govKeeper),
|
||||
},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightMsgCreateValidator, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 100
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
stakingsim.SimulateMsgCreateValidator(app.accountKeeper, app.stakingKeeper),
|
||||
},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightMsgEditValidator, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 5
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
stakingsim.SimulateMsgEditValidator(app.stakingKeeper),
|
||||
},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightMsgDelegate, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 100
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
stakingsim.SimulateMsgDelegate(app.accountKeeper, app.stakingKeeper),
|
||||
},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightMsgUndelegate, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 100
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
stakingsim.SimulateMsgUndelegate(app.accountKeeper, app.stakingKeeper),
|
||||
},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightMsgBeginRedelegate, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 100
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
stakingsim.SimulateMsgBeginRedelegate(app.accountKeeper, app.stakingKeeper),
|
||||
},
|
||||
{
|
||||
func(_ *rand.Rand) int {
|
||||
var v int
|
||||
ap.GetOrGenerate(cdc, OpWeightMsgUnjail, &v, nil,
|
||||
func(_ *rand.Rand) {
|
||||
v = 100
|
||||
})
|
||||
return v
|
||||
}(nil),
|
||||
slashingsim.SimulateMsgUnjail(app.slashingKeeper),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,12 +3,12 @@ package simapp
|
|||
import (
|
||||
"io"
|
||||
|
||||
dbm "github.com/tendermint/tendermint/libs/db"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
|
||||
bam "github.com/cosmos/cosmos-sdk/baseapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
dbm "github.com/tendermint/tendermint/libs/db"
|
||||
)
|
||||
|
||||
// NewSimAppUNSAFE is used for debugging purposes only.
|
||||
|
|
|
@ -34,7 +34,7 @@ var paramChangePool = []simParamChange{
|
|||
"MaxValidators",
|
||||
"",
|
||||
func(r *rand.Rand) string {
|
||||
return fmt.Sprintf("%d", simulation.ModuleParamSimulator["MaxValidators"](r).(uint16))
|
||||
return fmt.Sprintf("%d", simulation.ModuleParamSimulator[simulation.MaxValidators](r).(uint16))
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -42,7 +42,7 @@ var paramChangePool = []simParamChange{
|
|||
"UnbondingTime",
|
||||
"",
|
||||
func(r *rand.Rand) string {
|
||||
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator["UnbondingTime"](r).(time.Duration))
|
||||
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator[simulation.UnbondingTime](r).(time.Duration))
|
||||
},
|
||||
},
|
||||
// slashing parameters
|
||||
|
@ -51,7 +51,7 @@ var paramChangePool = []simParamChange{
|
|||
"SignedBlocksWindow",
|
||||
"",
|
||||
func(r *rand.Rand) string {
|
||||
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator["SignedBlocksWindow"](r).(int64))
|
||||
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator[simulation.SignedBlocksWindow](r).(int64))
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -59,7 +59,7 @@ var paramChangePool = []simParamChange{
|
|||
"MinSignedPerWindow",
|
||||
"",
|
||||
func(r *rand.Rand) string {
|
||||
return fmt.Sprintf("\"%s\"", simulation.ModuleParamSimulator["MinSignedPerWindow"](r).(sdk.Dec))
|
||||
return fmt.Sprintf("\"%s\"", simulation.ModuleParamSimulator[simulation.MinSignedPerWindow](r).(sdk.Dec))
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -67,7 +67,7 @@ var paramChangePool = []simParamChange{
|
|||
"SlashFractionDowntime",
|
||||
"",
|
||||
func(r *rand.Rand) string {
|
||||
return fmt.Sprintf("\"%s\"", simulation.ModuleParamSimulator["SlashFractionDowntime"](r).(sdk.Dec))
|
||||
return fmt.Sprintf("\"%s\"", simulation.ModuleParamSimulator[simulation.SlashFractionDowntime](r).(sdk.Dec))
|
||||
},
|
||||
},
|
||||
// minting parameters
|
||||
|
@ -76,7 +76,7 @@ var paramChangePool = []simParamChange{
|
|||
"InflationRateChange",
|
||||
"",
|
||||
func(r *rand.Rand) string {
|
||||
return fmt.Sprintf("\"%s\"", simulation.ModuleParamSimulator["InflationRateChange"](r).(sdk.Dec))
|
||||
return fmt.Sprintf("\"%s\"", simulation.ModuleParamSimulator[simulation.InflationRateChange](r).(sdk.Dec))
|
||||
},
|
||||
},
|
||||
// gov parameters
|
||||
|
@ -85,7 +85,7 @@ var paramChangePool = []simParamChange{
|
|||
"votingparams",
|
||||
"",
|
||||
func(r *rand.Rand) string {
|
||||
return fmt.Sprintf(`{"voting_period": "%d"}`, simulation.ModuleParamSimulator["VotingParams/VotingPeriod"](r).(time.Duration))
|
||||
return fmt.Sprintf(`{"voting_period": "%d"}`, simulation.ModuleParamSimulator[simulation.VotingParamsVotingPeriod](r).(time.Duration))
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -93,7 +93,7 @@ var paramChangePool = []simParamChange{
|
|||
"depositparams",
|
||||
"",
|
||||
func(r *rand.Rand) string {
|
||||
return fmt.Sprintf(`{"max_deposit_period": "%d"}`, simulation.ModuleParamSimulator["VotingParams/VotingPeriod"](r).(time.Duration))
|
||||
return fmt.Sprintf(`{"max_deposit_period": "%d"}`, simulation.ModuleParamSimulator[simulation.VotingParamsVotingPeriod](r).(time.Duration))
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -105,9 +105,9 @@ var paramChangePool = []simParamChange{
|
|||
key string
|
||||
value sdk.Dec
|
||||
}{
|
||||
{"quorum", simulation.ModuleParamSimulator["TallyParams/Quorum"](r).(sdk.Dec)},
|
||||
{"threshold", simulation.ModuleParamSimulator["TallyParams/Threshold"](r).(sdk.Dec)},
|
||||
{"veto", simulation.ModuleParamSimulator["TallyParams/Veto"](r).(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)
|
||||
|
@ -134,7 +134,7 @@ var paramChangePool = []simParamChange{
|
|||
"MaxMemoCharacters",
|
||||
"",
|
||||
func(r *rand.Rand) string {
|
||||
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator["MaxMemoCharacters"](r).(uint64))
|
||||
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator[simulation.MaxMemoChars](r).(uint64))
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -142,7 +142,7 @@ var paramChangePool = []simParamChange{
|
|||
"TxSigLimit",
|
||||
"",
|
||||
func(r *rand.Rand) string {
|
||||
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator["TxSigLimit"](r).(uint64))
|
||||
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator[simulation.TxSigLimit](r).(uint64))
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -150,7 +150,7 @@ var paramChangePool = []simParamChange{
|
|||
"TxSizeCostPerByte",
|
||||
"",
|
||||
func(r *rand.Rand) string {
|
||||
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator["TxSizeCostPerByte"](r).(uint64))
|
||||
return fmt.Sprintf("\"%d\"", simulation.ModuleParamSimulator[simulation.TxSizeCostPerByte](r).(uint64))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package simulation
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
|
@ -13,6 +15,34 @@ const (
|
|||
|
||||
// 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
|
||||
|
@ -37,72 +67,104 @@ var (
|
|||
// values simulated should be within valid acceptable range for the given
|
||||
// parameter.
|
||||
ModuleParamSimulator = map[string]func(r *rand.Rand) interface{}{
|
||||
"MaxMemoCharacters": 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{} {
|
||||
TxSigLimit: func(r *rand.Rand) interface{} {
|
||||
return uint64(r.Intn(7) + 1)
|
||||
},
|
||||
"TxSizeCostPerByte": func(r *rand.Rand) interface{} {
|
||||
TxSizeCostPerByte: func(r *rand.Rand) interface{} {
|
||||
return uint64(RandIntBetween(r, 5, 15))
|
||||
},
|
||||
"SigVerifyCostED25519": func(r *rand.Rand) interface{} {
|
||||
SigVerifyCostED25519: func(r *rand.Rand) interface{} {
|
||||
return uint64(RandIntBetween(r, 500, 1000))
|
||||
},
|
||||
"SigVerifyCostSecp256k1": func(r *rand.Rand) interface{} {
|
||||
SigVerifyCostSECP256K1: func(r *rand.Rand) interface{} {
|
||||
return uint64(RandIntBetween(r, 500, 1000))
|
||||
},
|
||||
"DepositParams/MinDeposit": func(r *rand.Rand) interface{} {
|
||||
DepositParamsMinDeposit: func(r *rand.Rand) interface{} {
|
||||
return sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, int64(RandIntBetween(r, 1, 1e3)))}
|
||||
},
|
||||
"VotingParams/VotingPeriod": func(r *rand.Rand) interface{} {
|
||||
VotingParamsVotingPeriod: func(r *rand.Rand) interface{} {
|
||||
return time.Duration(RandIntBetween(r, 1, 2*60*60*24*2)) * time.Second
|
||||
},
|
||||
"TallyParams/Quorum": func(r *rand.Rand) interface{} {
|
||||
TallyParamsQuorum: func(r *rand.Rand) interface{} {
|
||||
return sdk.NewDecWithPrec(int64(RandIntBetween(r, 334, 500)), 3)
|
||||
},
|
||||
"TallyParams/Threshold": func(r *rand.Rand) interface{} {
|
||||
TallyParamsThreshold: func(r *rand.Rand) interface{} {
|
||||
return sdk.NewDecWithPrec(int64(RandIntBetween(r, 450, 550)), 3)
|
||||
},
|
||||
"TallyParams/Veto": func(r *rand.Rand) interface{} {
|
||||
TallyParamsVeto: func(r *rand.Rand) interface{} {
|
||||
return sdk.NewDecWithPrec(int64(RandIntBetween(r, 250, 334)), 3)
|
||||
},
|
||||
"UnbondingTime": func(r *rand.Rand) interface{} {
|
||||
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{} {
|
||||
MaxValidators: func(r *rand.Rand) interface{} {
|
||||
return uint16(r.Intn(250) + 1)
|
||||
},
|
||||
"SignedBlocksWindow": func(r *rand.Rand) interface{} {
|
||||
SignedBlocksWindow: func(r *rand.Rand) interface{} {
|
||||
return int64(RandIntBetween(r, 10, 1000))
|
||||
},
|
||||
"MinSignedPerWindow": func(r *rand.Rand) interface{} {
|
||||
MinSignedPerWindow: func(r *rand.Rand) interface{} {
|
||||
return sdk.NewDecWithPrec(int64(r.Intn(10)), 1)
|
||||
},
|
||||
"DowntimeJailDuration": func(r *rand.Rand) interface{} {
|
||||
DowntimeJailDuration: func(r *rand.Rand) interface{} {
|
||||
return time.Duration(RandIntBetween(r, 60, 60*60*24)) * time.Second
|
||||
},
|
||||
"SlashFractionDoubleSign": func(r *rand.Rand) interface{} {
|
||||
SlashFractionDoubleSign: func(r *rand.Rand) interface{} {
|
||||
return sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(50) + 1)))
|
||||
},
|
||||
"SlashFractionDowntime": func(r *rand.Rand) interface{} {
|
||||
SlashFractionDowntime: func(r *rand.Rand) interface{} {
|
||||
return sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(200) + 1)))
|
||||
},
|
||||
"InflationRateChange": func(r *rand.Rand) interface{} {
|
||||
InflationRateChange: func(r *rand.Rand) interface{} {
|
||||
return sdk.NewDecWithPrec(int64(r.Intn(99)), 2)
|
||||
},
|
||||
"InflationMax": func(r *rand.Rand) interface{} {
|
||||
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{} {
|
||||
InflationMin: func(r *rand.Rand) interface{} {
|
||||
return sdk.NewDecWithPrec(7, 2)
|
||||
},
|
||||
"GoalBonded": func(r *rand.Rand) interface{} {
|
||||
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))
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
AppParams map[string]json.RawMessage
|
||||
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
|
||||
// ParamSimulator is used to generate a random value.
|
||||
func (sp AppParams) GetOrGenerate(cdc *codec.Codec, key string, ptr interface{}, r *rand.Rand, ps ParamSimulator) {
|
||||
if v, ok := sp[key]; ok && v != nil {
|
||||
cdc.MustUnmarshalJSON(v, ptr)
|
||||
return
|
||||
}
|
||||
|
||||
ps(r)
|
||||
}
|
||||
|
||||
// Simulation parameters
|
||||
type Params struct {
|
||||
PastEvidenceFraction float64
|
||||
|
@ -113,18 +175,6 @@ type Params struct {
|
|||
BlockSizeTransitionMatrix TransitionMatrix
|
||||
}
|
||||
|
||||
// Return default simulation parameters
|
||||
func DefaultParams() Params {
|
||||
return Params{
|
||||
PastEvidenceFraction: 0.5,
|
||||
NumKeys: 250,
|
||||
EvidenceFraction: 0.5,
|
||||
InitialLivenessWeightings: []int{40, 5, 5},
|
||||
LivenessTransitionMatrix: defaultLivenessTransitionMatrix,
|
||||
BlockSizeTransitionMatrix: defaultBlockSizeTransitionMatrix,
|
||||
}
|
||||
}
|
||||
|
||||
// Return random simulation parameters
|
||||
func RandomParams(r *rand.Rand) Params {
|
||||
return Params{
|
||||
|
|
|
@ -54,12 +54,14 @@ func SimulateFromSeed(
|
|||
fmt.Fprintf(w, "Starting SimulateFromSeed with randomness created with seed %d\n", int(seed))
|
||||
|
||||
r := rand.New(rand.NewSource(seed))
|
||||
params := RandomParams(r) // := DefaultParams()
|
||||
fmt.Fprintf(w, "Randomized simulation params: %+v\n", params)
|
||||
params := RandomParams(r)
|
||||
fmt.Fprintf(w, "Randomized simulation params: \n%s\n", mustMarshalJSONIndent(params))
|
||||
|
||||
genesisTimestamp := RandTimestamp(r)
|
||||
fmt.Printf("Starting the simulation from time %v, unixtime %v\n",
|
||||
genesisTimestamp.UTC().Format(time.UnixDate), genesisTimestamp.Unix())
|
||||
fmt.Printf(
|
||||
"Starting the simulation from time %v, unixtime %v\n",
|
||||
genesisTimestamp.UTC().Format(time.UnixDate), genesisTimestamp.Unix(),
|
||||
)
|
||||
|
||||
timeDiff := maxTimePerBlock - minTimePerBlock
|
||||
accs := RandomAccounts(r, params.NumKeys)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package simulation
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
@ -60,22 +61,6 @@ func getBlockSize(r *rand.Rand, params Params,
|
|||
return state, blocksize
|
||||
}
|
||||
|
||||
// PeriodicInvariant returns an Invariant function closure that asserts a given
|
||||
// invariant if the mock application's last block modulo the given period is
|
||||
// congruent to the given offset.
|
||||
//
|
||||
// NOTE this function is intended to be used manually used while running
|
||||
// computationally heavy simulations.
|
||||
// TODO reference this function in the codebase probably through use of a switch
|
||||
func PeriodicInvariant(invariant sdk.Invariant, period int, offset int) sdk.Invariant {
|
||||
return func(ctx sdk.Context) error {
|
||||
if int(ctx.BlockHeight())%period == offset {
|
||||
return invariant(ctx)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// PeriodicInvariants returns an array of wrapped Invariants. Where each
|
||||
// invariant function is only executed periodically defined by period and offset.
|
||||
func PeriodicInvariants(invariants []sdk.Invariant, period int, offset int) []sdk.Invariant {
|
||||
|
@ -91,3 +76,12 @@ func PeriodicInvariants(invariants []sdk.Invariant, period int, offset int) []sd
|
|||
}
|
||||
return outInvariants
|
||||
}
|
||||
|
||||
func mustMarshalJSONIndent(o interface{}) []byte {
|
||||
bz, err := json.MarshalIndent(o, "", " ")
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to JSON encode: %s", err))
|
||||
}
|
||||
|
||||
return bz
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue