191 lines
6.4 KiB
Go
191 lines
6.4 KiB
Go
package simulation
|
|
|
|
import (
|
|
"encoding/json"
|
|
"math/rand"
|
|
"time"
|
|
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
)
|
|
|
|
// nolint
|
|
const (
|
|
// Minimum time per block
|
|
minTimePerBlock int64 = 10000 / 2
|
|
|
|
// Maximum time per block
|
|
maxTimePerBlock int64 = 10000
|
|
|
|
// Simulation parameter constants
|
|
SendEnabled = "send_enabled"
|
|
MaxMemoChars = "max_memo_characters"
|
|
TxSigLimit = "tx_sig_limit"
|
|
TxSizeCostPerByte = "tx_size_cost_per_byte"
|
|
SigVerifyCostED25519 = "sig_verify_cost_ed25519"
|
|
SigVerifyCostSECP256K1 = "sig_verify_cost_secp256k1"
|
|
DepositParamsMinDeposit = "deposit_params_min_deposit"
|
|
VotingParamsVotingPeriod = "voting_params_voting_period"
|
|
TallyParamsQuorum = "tally_params_quorum"
|
|
TallyParamsThreshold = "tally_params_threshold"
|
|
TallyParamsVeto = "tally_params_veto"
|
|
UnbondingTime = "unbonding_time"
|
|
MaxValidators = "max_validators"
|
|
SignedBlocksWindow = "signed_blocks_window"
|
|
MinSignedPerWindow = "min_signed_per_window"
|
|
DowntimeJailDuration = "downtime_jail_duration"
|
|
SlashFractionDoubleSign = "slash_fraction_double_sign"
|
|
SlashFractionDowntime = "slash_fraction_downtime"
|
|
InflationRateChange = "inflation_rate_change"
|
|
Inflation = "inflation"
|
|
InflationMax = "inflation_max"
|
|
InflationMin = "inflation_min"
|
|
GoalBonded = "goal_bonded"
|
|
CommunityTax = "community_tax"
|
|
BaseProposerReward = "base_proposer_reward"
|
|
BonusProposerReward = "bonus_proposer_reward"
|
|
)
|
|
|
|
// TODO explain transitional matrix usage
|
|
var (
|
|
// Currently there are 3 different liveness types,
|
|
// fully online, spotty connection, offline.
|
|
defaultLivenessTransitionMatrix, _ = CreateTransitionMatrix([][]int{
|
|
{90, 20, 1},
|
|
{10, 50, 5},
|
|
{0, 10, 1000},
|
|
})
|
|
|
|
// 3 states: rand in range [0, 4*provided blocksize],
|
|
// rand in range [0, 2 * provided blocksize], 0
|
|
defaultBlockSizeTransitionMatrix, _ = CreateTransitionMatrix([][]int{
|
|
{85, 5, 0},
|
|
{15, 92, 1},
|
|
{0, 3, 99},
|
|
})
|
|
|
|
// ModuleParamSimulator defines module parameter value simulators. All
|
|
// values simulated should be within valid acceptable range for the given
|
|
// parameter.
|
|
ModuleParamSimulator = map[string]func(r *rand.Rand) interface{}{
|
|
SendEnabled: func(r *rand.Rand) interface{} {
|
|
return r.Int63n(2) == 0
|
|
},
|
|
MaxMemoChars: func(r *rand.Rand) interface{} {
|
|
return uint64(RandIntBetween(r, 100, 200))
|
|
},
|
|
TxSigLimit: func(r *rand.Rand) interface{} {
|
|
return uint64(r.Intn(7) + 1)
|
|
},
|
|
TxSizeCostPerByte: func(r *rand.Rand) interface{} {
|
|
return uint64(RandIntBetween(r, 5, 15))
|
|
},
|
|
SigVerifyCostED25519: func(r *rand.Rand) interface{} {
|
|
return uint64(RandIntBetween(r, 500, 1000))
|
|
},
|
|
SigVerifyCostSECP256K1: func(r *rand.Rand) interface{} {
|
|
return uint64(RandIntBetween(r, 500, 1000))
|
|
},
|
|
DepositParamsMinDeposit: func(r *rand.Rand) interface{} {
|
|
return sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, int64(RandIntBetween(r, 1, 1e3)))}
|
|
},
|
|
VotingParamsVotingPeriod: func(r *rand.Rand) interface{} {
|
|
return time.Duration(RandIntBetween(r, 1, 2*60*60*24*2)) * time.Second
|
|
},
|
|
TallyParamsQuorum: func(r *rand.Rand) interface{} {
|
|
return sdk.NewDecWithPrec(int64(RandIntBetween(r, 334, 500)), 3)
|
|
},
|
|
TallyParamsThreshold: func(r *rand.Rand) interface{} {
|
|
return sdk.NewDecWithPrec(int64(RandIntBetween(r, 450, 550)), 3)
|
|
},
|
|
TallyParamsVeto: func(r *rand.Rand) interface{} {
|
|
return sdk.NewDecWithPrec(int64(RandIntBetween(r, 250, 334)), 3)
|
|
},
|
|
UnbondingTime: func(r *rand.Rand) interface{} {
|
|
return time.Duration(RandIntBetween(r, 60, 60*60*24*3*2)) * time.Second
|
|
},
|
|
MaxValidators: func(r *rand.Rand) interface{} {
|
|
return uint16(r.Intn(250) + 1)
|
|
},
|
|
SignedBlocksWindow: func(r *rand.Rand) interface{} {
|
|
return int64(RandIntBetween(r, 10, 1000))
|
|
},
|
|
MinSignedPerWindow: func(r *rand.Rand) interface{} {
|
|
return sdk.NewDecWithPrec(int64(r.Intn(10)), 1)
|
|
},
|
|
DowntimeJailDuration: func(r *rand.Rand) interface{} {
|
|
return time.Duration(RandIntBetween(r, 60, 60*60*24)) * time.Second
|
|
},
|
|
SlashFractionDoubleSign: func(r *rand.Rand) interface{} {
|
|
return sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(50) + 1)))
|
|
},
|
|
SlashFractionDowntime: func(r *rand.Rand) interface{} {
|
|
return sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(200) + 1)))
|
|
},
|
|
InflationRateChange: func(r *rand.Rand) interface{} {
|
|
return sdk.NewDecWithPrec(int64(r.Intn(99)), 2)
|
|
},
|
|
Inflation: func(r *rand.Rand) interface{} {
|
|
return sdk.NewDecWithPrec(int64(r.Intn(99)), 2)
|
|
},
|
|
InflationMax: func(r *rand.Rand) interface{} {
|
|
return sdk.NewDecWithPrec(20, 2)
|
|
},
|
|
InflationMin: func(r *rand.Rand) interface{} {
|
|
return sdk.NewDecWithPrec(7, 2)
|
|
},
|
|
GoalBonded: func(r *rand.Rand) interface{} {
|
|
return sdk.NewDecWithPrec(67, 2)
|
|
},
|
|
CommunityTax: func(r *rand.Rand) interface{} {
|
|
return sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2))
|
|
},
|
|
BaseProposerReward: func(r *rand.Rand) interface{} {
|
|
return sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2))
|
|
},
|
|
BonusProposerReward: func(r *rand.Rand) interface{} {
|
|
return sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2))
|
|
},
|
|
}
|
|
)
|
|
|
|
// TODO add description
|
|
type (
|
|
AppParams map[string]json.RawMessage
|
|
ParamSimulator func(r *rand.Rand)
|
|
)
|
|
|
|
// 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
|
|
NumKeys int
|
|
EvidenceFraction float64
|
|
InitialLivenessWeightings []int
|
|
LivenessTransitionMatrix TransitionMatrix
|
|
BlockSizeTransitionMatrix TransitionMatrix
|
|
}
|
|
|
|
// Return random simulation parameters
|
|
func RandomParams(r *rand.Rand) Params {
|
|
return Params{
|
|
PastEvidenceFraction: r.Float64(),
|
|
NumKeys: RandIntBetween(r, 2, 250),
|
|
EvidenceFraction: r.Float64(),
|
|
InitialLivenessWeightings: []int{RandIntBetween(r, 1, 80), r.Intn(10), r.Intn(10)},
|
|
LivenessTransitionMatrix: defaultLivenessTransitionMatrix,
|
|
BlockSizeTransitionMatrix: defaultBlockSizeTransitionMatrix,
|
|
}
|
|
}
|