-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e46c733
commit a439282
Showing
4 changed files
with
345 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,260 @@ | ||
package app_test | ||
|
||
import ( | ||
cryptorand "crypto/rand" | ||
"encoding/json" | ||
"fmt" | ||
"math/big" | ||
"math/rand" | ||
"os" | ||
"time" | ||
|
||
"cosmossdk.io/math" | ||
storetypes "cosmossdk.io/store/types" | ||
"github.com/cosmos/cosmos-sdk/baseapp" | ||
"github.com/cosmos/cosmos-sdk/codec" | ||
"github.com/cosmos/cosmos-sdk/runtime" | ||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/cosmos/cosmos-sdk/types/module" | ||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" | ||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation" | ||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" | ||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" | ||
simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" | ||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" | ||
) | ||
|
||
type storeKeysPrefixes struct { | ||
A storetypes.StoreKey | ||
B storetypes.StoreKey | ||
Prefixes [][]byte | ||
} | ||
|
||
// fauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of | ||
// an IAVLStore for faster simulation speed. | ||
func fauxMerkleModeOpt(bapp *baseapp.BaseApp) { | ||
bapp.SetFauxMerkleMode() | ||
} | ||
|
||
// simulationOperations retrieves the simulation params from the provided file path | ||
// and returns all the modules weighted operations | ||
func simulationOperations(app runtime.AppI, cdc codec.JSONCodec, config simtypes.Config) []simtypes.WeightedOperation { | ||
simState := module.SimulationState{ | ||
AppParams: make(simtypes.AppParams), | ||
Cdc: cdc, | ||
TxConfig: moduletestutil.MakeTestTxConfig(), | ||
BondDenom: sdk.DefaultBondDenom, | ||
} | ||
|
||
if config.ParamsFile != "" { | ||
bz, err := os.ReadFile(config.ParamsFile) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
err = json.Unmarshal(bz, &simState.AppParams) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
simState.LegacyProposalContents = nil | ||
simState.ProposalMsgs = app.SimulationManager().GetProposalMsgs(simState) | ||
return app.SimulationManager().WeightedOperations(simState) | ||
} | ||
|
||
// Simulation parameter constants | ||
const ( | ||
StakePerAccount = "stake_per_account" | ||
InitiallyBondedValidators = "initially_bonded_validators" | ||
) | ||
|
||
// appStateFn returns the initial application state using a genesis or the simulation parameters. | ||
// NOTE: This function is a modified version of | ||
// github.com/cosmos/cosmos-sdk/blob/7e6948f50cd4838a0161838a099f74e0b5b0213c/testutil/sims/state_helpers.go#L56 | ||
func appStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager, genesisState map[string]json.RawMessage) simtypes.AppStateFn { | ||
return func( | ||
r *rand.Rand, | ||
accs []simtypes.Account, | ||
config simtypes.Config, | ||
) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) { | ||
if simcli.FlagGenesisTimeValue == 0 { | ||
genesisTimestamp = simtypes.RandTimestamp(r) | ||
} else { | ||
genesisTimestamp = time.Unix(simcli.FlagGenesisTimeValue, 0) | ||
} | ||
|
||
chainID = config.ChainID | ||
switch { | ||
case config.ParamsFile != "" && config.GenesisFile != "": | ||
panic("cannot provide both a genesis file and a params file") | ||
|
||
case config.GenesisFile != "": | ||
// override the default chain-id from simapp to set it later to the config | ||
genesisDoc, accounts, err := simtestutil.AppStateFromGenesisFileFn(r, cdc, config.GenesisFile) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
if simcli.FlagGenesisTimeValue == 0 { | ||
// use genesis timestamp if no custom timestamp is provided (i.e no random timestamp) | ||
genesisTimestamp = genesisDoc.GenesisTime | ||
} | ||
|
||
appState = genesisDoc.AppState | ||
chainID = genesisDoc.ChainID | ||
simAccs = accounts | ||
|
||
case config.ParamsFile != "": | ||
appParams := make(simtypes.AppParams) | ||
bz, err := os.ReadFile(config.ParamsFile) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
err = json.Unmarshal(bz, &appParams) | ||
if err != nil { | ||
panic(err) | ||
} | ||
appState, simAccs = appStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState) | ||
|
||
default: | ||
appParams := make(simtypes.AppParams) | ||
appState, simAccs = appStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState) | ||
} | ||
|
||
rawState := make(map[string]json.RawMessage) | ||
err := json.Unmarshal(appState, &rawState) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
stakingStateBz, ok := rawState[stakingtypes.ModuleName] | ||
if !ok { | ||
panic("staking genesis state is missing") | ||
} | ||
|
||
stakingState := new(stakingtypes.GenesisState) | ||
if err = cdc.UnmarshalJSON(stakingStateBz, stakingState); err != nil { | ||
panic(err) | ||
} | ||
// compute not bonded balance | ||
notBondedTokens := math.ZeroInt() | ||
for _, val := range stakingState.Validators { | ||
if val.Status != stakingtypes.Unbonded { | ||
continue | ||
} | ||
notBondedTokens = notBondedTokens.Add(val.GetTokens()) | ||
} | ||
notBondedCoins := sdk.NewCoin(stakingState.Params.BondDenom, notBondedTokens) | ||
// edit bank state to make it have the not bonded pool tokens | ||
bankStateBz, ok := rawState[banktypes.ModuleName] | ||
// TODO(fdymylja/jonathan): should we panic in this case | ||
if !ok { | ||
panic("bank genesis state is missing") | ||
} | ||
bankState := new(banktypes.GenesisState) | ||
if err = cdc.UnmarshalJSON(bankStateBz, bankState); err != nil { | ||
panic(err) | ||
} | ||
|
||
stakingAddr := authtypes.NewModuleAddress(stakingtypes.NotBondedPoolName).String() | ||
var found bool | ||
for _, balance := range bankState.Balances { | ||
if balance.Address == stakingAddr { | ||
found = true | ||
break | ||
} | ||
} | ||
if !found { | ||
bankState.Balances = append(bankState.Balances, banktypes.Balance{ | ||
Address: stakingAddr, | ||
Coins: sdk.NewCoins(notBondedCoins), | ||
}) | ||
} | ||
|
||
// change appState back | ||
rawState[stakingtypes.ModuleName] = cdc.MustMarshalJSON(stakingState) | ||
rawState[banktypes.ModuleName] = cdc.MustMarshalJSON(bankState) | ||
|
||
// replace appstate | ||
appState, err = json.Marshal(rawState) | ||
if err != nil { | ||
panic(err) | ||
} | ||
return appState, simAccs, chainID, genesisTimestamp | ||
} | ||
} | ||
|
||
// appStateRandomizedFn creates calls each module's GenesisState generator function | ||
// and creates the simulation params | ||
func appStateRandomizedFn( | ||
simManager *module.SimulationManager, | ||
r *rand.Rand, | ||
cdc codec.JSONCodec, | ||
accs []simtypes.Account, | ||
genesisTimestamp time.Time, | ||
appParams simtypes.AppParams, | ||
genesisState map[string]json.RawMessage, | ||
) (json.RawMessage, []simtypes.Account) { | ||
numAccs := int64(len(accs)) | ||
// generate a random amount of initial stake coins and a random initial | ||
// number of bonded accounts | ||
var ( | ||
numInitiallyBonded int64 | ||
initialStake math.Int | ||
) | ||
|
||
// max value 10^24 aseda | ||
max := big.NewInt(0).Exp(big.NewInt(10), big.NewInt(24), nil) | ||
initialStakeAmount, err := cryptorand.Int(cryptorand.Reader, max) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
appParams.GetOrGenerate( | ||
StakePerAccount, &initialStake, r, | ||
func(r *rand.Rand) { | ||
initialStake = math.NewIntFromBigInt(initialStakeAmount) | ||
}, | ||
) | ||
appParams.GetOrGenerate( | ||
InitiallyBondedValidators, &numInitiallyBonded, r, | ||
func(r *rand.Rand) { numInitiallyBonded = int64(r.Intn(300)) }, | ||
) | ||
|
||
if numInitiallyBonded > numAccs { | ||
numInitiallyBonded = numAccs | ||
} | ||
|
||
fmt.Printf( | ||
`Selected randomly generated parameters for simulated genesis: | ||
{ | ||
stake_per_account: "%s", | ||
initially_bonded_validators: "%d" | ||
} | ||
`, initialStake.String(), numInitiallyBonded, | ||
) | ||
|
||
simState := &module.SimulationState{ | ||
AppParams: appParams, | ||
Cdc: cdc, | ||
Rand: r, | ||
GenState: genesisState, | ||
Accounts: accs, | ||
InitialStake: initialStake, | ||
NumBonded: numInitiallyBonded, | ||
BondDenom: sdk.DefaultBondDenom, | ||
GenTimestamp: genesisTimestamp, | ||
} | ||
|
||
simManager.GenerateGenesisStates(simState) | ||
|
||
appState, err := json.Marshal(genesisState) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
return appState, accs | ||
} |
Oops, something went wrong.