Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R4R: Simulation improvements (logging fix, random genesis parameters) #2617

Merged
merged 23 commits into from
Nov 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
4e44ddf
Print out initial update on every block
cwgoes Oct 28, 2018
38ceea1
Randomize simulation parameters
cwgoes Oct 28, 2018
4e48217
Randomize initial liveness weightings
cwgoes Oct 28, 2018
46e6b40
Randomize genesis parameters
cwgoes Oct 28, 2018
3884b13
Update PENDING.md
cwgoes Oct 28, 2018
991573e
Avoid dividing-by-zero
cwgoes Oct 28, 2018
f5918db
More simulation seeds, more blocks in CI version
cwgoes Oct 29, 2018
e2aa3e9
Update cmd/gaia/app/sim_test.go
zmanian Oct 29, 2018
01c235d
Update cmd/gaia/app/sim_test.go
zmanian Oct 29, 2018
f13f602
Update cmd/gaia/app/sim_test.go
zmanian Oct 29, 2018
1868ee3
Merge remote-tracking branch 'origin/develop' into cwgoes/simulation-…
rigelrozanski Oct 31, 2018
a84cf4f
Merge tag 'v0.25.0' into develop
cwgoes Nov 1, 2018
fb0f4a4
Merge branch 'develop' into cwgoes/simulation-transubstantiated
cwgoes Nov 1, 2018
d9907cc
Address comments
cwgoes Nov 1, 2018
f695a66
Minimize variable passing
cwgoes Nov 1, 2018
39165c9
fixed power store invariant
sunnya97 Nov 2, 2018
3cf6687
PENDING
sunnya97 Nov 2, 2018
42eb4e2
IterateValidatorsBonded -> IterateBondedValidatorsByPower
sunnya97 Nov 2, 2018
888c061
WriteValidators uses IterateLastValidators rather than IterateBondedV…
sunnya97 Nov 2, 2018
13d933f
fixed democoin interface
sunnya97 Nov 2, 2018
191a732
fixed comment
sunnya97 Nov 3, 2018
559ebb7
Merge PR #2671: Power Store Invariant
rigelrozanski Nov 3, 2018
7b10ac4
Merge branch 'develop' into cwgoes/simulation-transubstantiated
Nov 3, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ IMPROVEMENTS

* SDK
- #2573 [x/distribution] add accum invariance
- #2556 [x/mock/simulation] Fix debugging output
- #2396 [x/mock/simulation] Change parameters to get more slashes
- #2617 [x/mock/simulation] Randomize all genesis parameters
- #2669 [x/stake] Added invarant check to make sure validator's power aligns with its spot in the power store.
- \#1924 [x/mock/simulation] Use a transition matrix for block size
- \#2660 [x/mock/simulation] Staking transactions get tested far more frequently
- #2610 [x/stake] Block redelegation to and from the same validator
Expand All @@ -57,6 +61,7 @@ BUG FIXES
* Gaia CLI (`gaiacli`)

* Gaia
- #2670 [x/stake] fixed incorrent `IterateBondedValidators` and split into two functions: `IterateBondedValidators` and `IterateLastBlockConsValidators`

* SDK
- #2625 [x/gov] fix AppendTag function usage error
Expand Down
1 change: 1 addition & 0 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res

ctx := sdk.NewContext(app.cms.CacheMultiStore(), app.checkState.ctx.BlockHeader(), true, app.Logger).
WithMinimumFees(app.minimumFees)

// Passes the rest of the path as an argument to the querier.
// For example, in the path "custom/gov/proposal/test", the gov querier gets []string{"proposal", "test"} as the path
resBytes, err := querier(ctx, path[2:], req)
Expand Down
78 changes: 65 additions & 13 deletions cmd/gaia/app/sim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"math/rand"
"os"
"testing"
"time"

"github.com/stretchr/testify/require"

Expand Down Expand Up @@ -50,42 +51,93 @@ func init() {
func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
var genesisAccounts []GenesisAccount

amt := int64(10000)
amount := int64(r.Intn(1e6))
numInitiallyBonded := int64(r.Intn(250))
numAccs := int64(len(accs))
if numInitiallyBonded > numAccs {
numInitiallyBonded = numAccs
}
fmt.Printf("Selected randomly generated parameters for simulated genesis: {amount of steak per account: %v, initially bonded validators: %v}\n", amount, numInitiallyBonded)

// Randomly generate some genesis accounts
for _, acc := range accs {
coins := sdk.Coins{sdk.Coin{"steak", sdk.NewInt(amt)}}
coins := sdk.Coins{sdk.Coin{"steak", sdk.NewInt(amount)}}
genesisAccounts = append(genesisAccounts, GenesisAccount{
Address: acc.Address,
Coins: coins,
})
}

// Default genesis state
govGenesis := gov.DefaultGenesisState()
stakeGenesis := stake.DefaultGenesisState()
slashingGenesis := slashing.DefaultGenesisState()
// Random genesis states
govGenesis := gov.GenesisState{
StartingProposalID: int64(r.Intn(100)),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense for randomized genesis states to be defined within the module itself?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question. I think they may need to be dependent (e.g. the max evidence age for slashing should be the unbonding period), although in that case I wonder if we should just share the parameters themselves...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we have that sort of requirement, they definitely should be dependent when being set or be the same variable

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets keep things here for a bit... we lose agility by organizing things too far, and simulation is an edge application, so I think it's fine as is for now.

DepositProcedure: gov.DepositProcedure{
MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", int64(r.Intn(1e3)))},
MaxDepositPeriod: time.Duration(r.Intn(2*172800)) * time.Second,
},
VotingProcedure: gov.VotingProcedure{
VotingPeriod: time.Duration(r.Intn(2*172800)) * time.Second,
},
TallyingProcedure: gov.TallyingProcedure{
Threshold: sdk.NewDecWithPrec(5, 1),
Veto: sdk.NewDecWithPrec(334, 3),
GovernancePenalty: sdk.NewDecWithPrec(1, 2),
},
}
fmt.Printf("Selected randomly generated governance parameters: %+v\n", govGenesis)
stakeGenesis := stake.GenesisState{
Pool: stake.InitialPool(),
Params: stake.Params{
UnbondingTime: time.Duration(r.Intn(60*60*24*3*2)) * time.Second,
MaxValidators: uint16(r.Intn(250)),
BondDenom: "steak",
},
}
fmt.Printf("Selected randomly generated staking parameters: %+v\n", stakeGenesis)
slashingGenesis := slashing.GenesisState{
Params: slashing.Params{
MaxEvidenceAge: stakeGenesis.Params.UnbondingTime,
DoubleSignUnbondDuration: time.Duration(r.Intn(60*60*24)) * time.Second,
SignedBlocksWindow: int64(r.Intn(1000)),
DowntimeUnbondDuration: time.Duration(r.Intn(86400)) * time.Second,
MinSignedPerWindow: sdk.NewDecWithPrec(int64(r.Intn(10)), 1),
SlashFractionDoubleSign: sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(50) + 1))),
SlashFractionDowntime: sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(200) + 1))),
},
}
fmt.Printf("Selected randomly generated slashing parameters: %+v\n", slashingGenesis)
mintGenesis := mint.GenesisState{
Minter: mint.Minter{
InflationLastTime: time.Unix(0, 0),
Inflation: sdk.NewDecWithPrec(int64(r.Intn(99)), 2),
},
Params: mint.Params{
MintDenom: "steak",
InflationRateChange: sdk.NewDecWithPrec(int64(r.Intn(99)), 2),
InflationMax: sdk.NewDecWithPrec(20, 2),
InflationMin: sdk.NewDecWithPrec(7, 2),
GoalBonded: sdk.NewDecWithPrec(67, 2),
},
}
fmt.Printf("Selected randomly generated minting parameters: %v\n", mintGenesis)
var validators []stake.Validator
var delegations []stake.Delegation

// XXX Try different numbers of initially bonded validators
numInitiallyBonded := int64(50)
valAddrs := make([]sdk.ValAddress, numInitiallyBonded)
for i := 0; i < int(numInitiallyBonded); i++ {
valAddr := sdk.ValAddress(accs[i].Address)
valAddrs[i] = valAddr

validator := stake.NewValidator(valAddr, accs[i].PubKey, stake.Description{})
validator.Tokens = sdk.NewDec(amt)
validator.DelegatorShares = sdk.NewDec(amt)
delegation := stake.Delegation{accs[i].Address, valAddr, sdk.NewDec(amt), 0}
validator.Tokens = sdk.NewDec(amount)
validator.DelegatorShares = sdk.NewDec(amount)
delegation := stake.Delegation{accs[i].Address, valAddr, sdk.NewDec(amount), 0}
validators = append(validators, validator)
delegations = append(delegations, delegation)
}
stakeGenesis.Pool.LooseTokens = sdk.NewDec(amt*250 + (numInitiallyBonded * amt))
stakeGenesis.Pool.LooseTokens = sdk.NewDec((amount * numAccs) + (numInitiallyBonded * amount))
stakeGenesis.Validators = validators
stakeGenesis.Bonds = delegations
mintGenesis := mint.DefaultGenesisState()

genesis := GenesisState{
Accounts: genesisAccounts,
Expand Down
9 changes: 7 additions & 2 deletions examples/democoin/mock/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,13 @@ func (vs *ValidatorSet) IterateValidators(ctx sdk.Context, fn func(index int64,
}
}

// IterateValidatorsBonded implements sdk.ValidatorSet
func (vs *ValidatorSet) IterateValidatorsBonded(ctx sdk.Context, fn func(index int64, Validator sdk.Validator) bool) {
// IterateBondedValidatorsByPower implements sdk.ValidatorSet
func (vs *ValidatorSet) IterateBondedValidatorsByPower(ctx sdk.Context, fn func(index int64, Validator sdk.Validator) bool) {
vs.IterateValidators(ctx, fn)
}

// IterateLastValidators implements sdk.ValidatorSet
func (vs *ValidatorSet) IterateLastValidators(ctx sdk.Context, fn func(index int64, Validator sdk.Validator) bool) {
vs.IterateValidators(ctx, fn)
}

Expand Down
3 changes: 2 additions & 1 deletion scripts/multisim.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/bin/bash

seeds=(1 2 4 7 9 20 32 123 124 582 1893 2989 3012 4728 37827 981928 87821 891823782 989182 89182391)
seeds=(1 2 4 7 9 20 32 123 124 582 1893 2989 3012 4728 37827 981928 87821 891823782 989182 89182391 \
11 22 44 77 99 2020 3232 123123 124124 582582 18931893 29892989 30123012 47284728 37827)
blocks=$1

echo "Running multi-seed simulation with seeds ${seeds[@]}"
Expand Down
6 changes: 5 additions & 1 deletion types/stake.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ type ValidatorSet interface {
func(index int64, validator Validator) (stop bool))

// iterate through bonded validators by operator address, execute func for each validator
IterateValidatorsBonded(Context,
IterateBondedValidatorsByPower(Context,
func(index int64, validator Validator) (stop bool))

// iterate through the consensus validator set of the last block by operator address, execute func for each validator
IterateLastValidators(Context,
func(index int64, validator Validator) (stop bool))

Validator(Context, ValAddress) Validator // get a particular validator by operator address
Expand Down
2 changes: 1 addition & 1 deletion x/gov/tally.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall
totalVotingPower := sdk.ZeroDec()
currValidators := make(map[string]validatorGovInfo)

keeper.vs.IterateValidatorsBonded(ctx, func(index int64, validator sdk.Validator) (stop bool) {
keeper.vs.IterateBondedValidatorsByPower(ctx, func(index int64, validator sdk.Validator) (stop bool) {
currValidators[validator.GetOperator().String()] = validatorGovInfo{
Address: validator.GetOperator(),
Power: validator.GetPower(),
Expand Down
37 changes: 0 additions & 37 deletions x/mock/simulation/constants.go

This file was deleted.

66 changes: 66 additions & 0 deletions x/mock/simulation/params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package simulation

import (
"math/rand"
)

const (
// Minimum time per block
minTimePerBlock int64 = 10000 / 2

// Maximum time per block
maxTimePerBlock int64 = 10000

// TODO Remove in favor of binary search for invariant violation
onOperation bool = false
)

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

// Simulation parameters
type Params struct {
PastEvidenceFraction float64
NumKeys int
EvidenceFraction float64
InitialLivenessWeightings []int
LivenessTransitionMatrix TransitionMatrix
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{
PastEvidenceFraction: r.Float64(),
NumKeys: r.Intn(250),
EvidenceFraction: r.Float64(),
InitialLivenessWeightings: []int{r.Intn(80), r.Intn(10), r.Intn(10)},
LivenessTransitionMatrix: defaultLivenessTransitionMatrix,
BlockSizeTransitionMatrix: defaultBlockSizeTransitionMatrix,
}
}
Loading