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:
Alexander Bezobchuk 2019-06-08 16:55:47 -04:00 committed by frog power 4000
parent b4eb4a9e64
commit 6606007297
9 changed files with 800 additions and 177 deletions

View File

@ -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

93
simapp/doc.go Normal file
View File

@ -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

23
simapp/params.go Normal file
View File

@ -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"
)

View File

@ -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(&paramsFile, "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)),
}
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)
if err != nil {
panic(err)
}
return appState, accs, "simulation"
}
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)
return stakingGenesis
}
func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
cdc := MakeCodec()
ap := make(simulation.AppParams)
if paramsFile != "" {
bz, err := ioutil.ReadFile(paramsFile)
if err != nil {
panic(err)
}
cdc.MustUnmarshalJSON(bz, &ap)
}
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),
},
}
}

View File

@ -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.

View File

@ -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))
},
},
}

View File

@ -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{

View File

@ -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)

View File

@ -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
}