diff --git a/Makefile b/Makefile index 5d2cb8493..645973472 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ PACKAGES=$(shell go list ./... | grep -v '/vendor/') -PACKAGES_NOCLITEST=$(shell go list ./... | grep -v '/vendor/' | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test) -PACKAGES_SIMTEST=$(shell go list ./... | grep -v '/vendor/') +PACKAGES_NOCLITEST=$(shell go list ./... | grep -v '/vendor/' | grep -v '/simulation' | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test) +PACKAGES_SIMTEST=$(shell go list ./... | grep -v '/vendor/' | grep '/simulation') COMMIT_HASH := $(shell git rev-parse --short HEAD) BUILD_TAGS = netgo ledger BUILD_FLAGS = -tags "${BUILD_TAGS}" -ldflags "-X github.com/cosmos/cosmos-sdk/version.GitCommit=${COMMIT_HASH}" @@ -115,6 +115,7 @@ test_race: test_sim: @ENABLE_GAIA_SIMULATION=1 go test ./cmd/gaia/app -run TestFullGaiaSimulation -v + @go test $(PACKAGES_SIMTEST) test_cover: @bash tests/test_cover.sh diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index a42a34bc6..2fd2a55b6 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -1,6 +1,8 @@ package app import ( + "encoding/json" + "math/rand" "os" "testing" @@ -9,8 +11,10 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/mock/simulation" stake "github.com/cosmos/cosmos-sdk/x/stake" + stakesim "github.com/cosmos/cosmos-sdk/x/stake/simulation" ) const ( @@ -21,6 +25,33 @@ const ( simulationEnv = "ENABLE_GAIA_SIMULATION" ) +func appStateFn(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage { + var genesisAccounts []GenesisAccount + + // Randomly generate some genesis accounts + for _, addr := range accs { + coins := sdk.Coins{sdk.Coin{"steak", sdk.NewInt(100)}} + genesisAccounts = append(genesisAccounts, GenesisAccount{ + Address: addr, + Coins: coins, + }) + } + + // Default genesis state + genesis := GenesisState{ + Accounts: genesisAccounts, + StakeData: stake.DefaultGenesisState(), + } + + // Marshal genesis + appState, err := MakeCodec().MarshalJSON(genesis) + if err != nil { + panic(err) + } + + return appState +} + func TestFullGaiaSimulation(t *testing.T) { if os.Getenv(simulationEnv) == "" { t.Skip("Skipping Gaia simulation") @@ -32,24 +63,16 @@ func TestFullGaiaSimulation(t *testing.T) { app := NewGaiaApp(logger, db, nil) require.Equal(t, "GaiaApp", app.Name()) - // Default genesis state - genesis := GenesisState{ - Accounts: []GenesisAccount{}, - StakeData: stake.DefaultGenesisState(), - } - - // Marshal genesis - appState, err := MakeCodec().MarshalJSON(genesis) - if err != nil { - panic(err) - } - // Run randomized simulation simulation.Simulate( - t, app.BaseApp, appState, - []simulation.TestAndRunTx{}, + t, app.BaseApp, appStateFn, + []simulation.TestAndRunTx{ + stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper), + }, []simulation.RandSetup{}, - []simulation.Invariant{}, + []simulation.Invariant{ + stakesim.AllInvariants(app.coinKeeper, app.stakeKeeper, app.accountMapper), + }, NumKeys, NumBlocks, BlockSize, diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index fdb1c9d42..eca9757c5 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -8,6 +8,7 @@ import ( "time" "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/mock" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" @@ -15,26 +16,24 @@ import ( // Simulate tests application by sending random messages. func Simulate( - t *testing.T, app *baseapp.BaseApp, appState json.RawMessage, ops []TestAndRunTx, setups []RandSetup, + t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage, ops []TestAndRunTx, setups []RandSetup, invariants []Invariant, numKeys int, numBlocks int, blockSize int, ) { time := time.Now().UnixNano() - SimulateFromSeed(t, app, appState, time, ops, setups, invariants, numKeys, numBlocks, blockSize) + SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numKeys, numBlocks, blockSize) } // SimulateFromSeed tests an application by running the provided // operations, testing the provided invariants, but using the provided seed. func SimulateFromSeed( - t *testing.T, app *baseapp.BaseApp, appState json.RawMessage, seed int64, ops []TestAndRunTx, setups []RandSetup, + t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []TestAndRunTx, setups []RandSetup, invariants []Invariant, numKeys int, numBlocks int, blockSize int, ) { - log := fmt.Sprintf("Starting SingleModuleTest with randomness created with seed %d", int(seed)) - keys, _ := mock.GeneratePrivKeyAddressPairs(numKeys) + log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) + keys, addrs := mock.GeneratePrivKeyAddressPairs(numKeys) r := rand.New(rand.NewSource(seed)) - // XXX TODO - // RandomSetGenesis(r, app, addrs, []string{"foocoin"}) - app.InitChain(abci.RequestInitChain{AppStateBytes: appState}) + app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, addrs)}) for i := 0; i < len(setups); i++ { setups[i](r, keys) } @@ -66,6 +65,7 @@ func SimulateFromSeed( } } +// AssertAllInvariants asserts a list of provided invariants against application state func AssertAllInvariants(t *testing.T, app *baseapp.BaseApp, tests []Invariant, log string) { for i := 0; i < len(tests); i++ { tests[i](t, app, log) diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go new file mode 100644 index 000000000..2c7bf80f4 --- /dev/null +++ b/x/stake/simulation/msgs.go @@ -0,0 +1,246 @@ +package simulation + +import ( + "fmt" + "math/rand" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/mock" + "github.com/cosmos/cosmos-sdk/x/mock/simulation" + "github.com/cosmos/cosmos-sdk/x/stake" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" +) + +// SimulateMsgCreateValidator +func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string) (action string, err sdk.Error) { + denom := k.GetParams(ctx).BondDenom + description := stake.Description{ + Moniker: simulation.RandStringOfLength(r, 10), + } + key := keys[r.Intn(len(keys))] + pubkey := key.PubKey() + address := sdk.AccAddress(pubkey.Address()) + amount := m.GetAccount(ctx, address).GetCoins().AmountOf(denom) + if amount.GT(sdk.ZeroInt()) { + amount = sdk.NewInt(int64(r.Intn(int(amount.Int64())))) + } + if amount.Equal(sdk.ZeroInt()) { + return "nop", nil + } + msg := stake.MsgCreateValidator{ + Description: description, + ValidatorAddr: address, + DelegatorAddr: address, + PubKey: pubkey, + Delegation: sdk.NewIntCoin(denom, amount), + } + require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + ctx, write := ctx.CacheContext() + result := stake.NewHandler(k)(ctx, msg) + if result.IsOK() { + write() + } + // require.True(t, result.IsOK(), "expected OK result but instead got %v", result) + action = fmt.Sprintf("TestMsgCreateValidator: %s", msg.GetSignBytes()) + return action, nil + } +} + +// SimulateMsgEditValidator +func SimulateMsgEditValidator(k stake.Keeper) simulation.TestAndRunTx { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string) (action string, err sdk.Error) { + description := stake.Description{ + Moniker: simulation.RandStringOfLength(r, 10), + Identity: simulation.RandStringOfLength(r, 10), + Website: simulation.RandStringOfLength(r, 10), + Details: simulation.RandStringOfLength(r, 10), + } + key := keys[r.Intn(len(keys))] + pubkey := key.PubKey() + address := sdk.AccAddress(pubkey.Address()) + msg := stake.MsgEditValidator{ + Description: description, + ValidatorAddr: address, + } + require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + ctx, write := ctx.CacheContext() + result := stake.NewHandler(k)(ctx, msg) + if result.IsOK() { + write() + } + action = fmt.Sprintf("TestMsgEditValidator: %s", msg.GetSignBytes()) + return action, nil + } +} + +// SimulateMsgDelegate +func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string) (action string, err sdk.Error) { + denom := k.GetParams(ctx).BondDenom + validatorKey := keys[r.Intn(len(keys))] + validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) + delegatorKey := keys[r.Intn(len(keys))] + delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) + amount := m.GetAccount(ctx, delegatorAddress).GetCoins().AmountOf(denom) + if amount.GT(sdk.ZeroInt()) { + amount = sdk.NewInt(int64(r.Intn(int(amount.Int64())))) + } + if amount.Equal(sdk.ZeroInt()) { + return "nop", nil + } + msg := stake.MsgDelegate{ + DelegatorAddr: delegatorAddress, + ValidatorAddr: validatorAddress, + Delegation: sdk.NewIntCoin(denom, amount), + } + require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + ctx, write := ctx.CacheContext() + result := stake.NewHandler(k)(ctx, msg) + if result.IsOK() { + write() + } + action = fmt.Sprintf("TestMsgDelegate: %s", msg.GetSignBytes()) + return action, nil + } +} + +// SimulateMsgBeginUnbonding +func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string) (action string, err sdk.Error) { + denom := k.GetParams(ctx).BondDenom + validatorKey := keys[r.Intn(len(keys))] + validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) + delegatorKey := keys[r.Intn(len(keys))] + delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) + amount := m.GetAccount(ctx, delegatorAddress).GetCoins().AmountOf(denom) + if amount.GT(sdk.ZeroInt()) { + amount = sdk.NewInt(int64(r.Intn(int(amount.Int64())))) + } + if amount.Equal(sdk.ZeroInt()) { + return "nop", nil + } + msg := stake.MsgBeginUnbonding{ + DelegatorAddr: delegatorAddress, + ValidatorAddr: validatorAddress, + SharesAmount: sdk.NewRatFromInt(amount), + } + require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + ctx, write := ctx.CacheContext() + result := stake.NewHandler(k)(ctx, msg) + if result.IsOK() { + write() + } + action = fmt.Sprintf("TestMsgBeginUnbonding: %s", msg.GetSignBytes()) + return action, nil + } +} + +// SimulateMsgCompleteUnbonding +func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.TestAndRunTx { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string) (action string, err sdk.Error) { + validatorKey := keys[r.Intn(len(keys))] + validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) + delegatorKey := keys[r.Intn(len(keys))] + delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) + msg := stake.MsgCompleteUnbonding{ + DelegatorAddr: delegatorAddress, + ValidatorAddr: validatorAddress, + } + require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + ctx, write := ctx.CacheContext() + result := stake.NewHandler(k)(ctx, msg) + if result.IsOK() { + write() + } + action = fmt.Sprintf("TestMsgCompleteUnbonding with %s", msg.GetSignBytes()) + return action, nil + } +} + +// SimulateMsgBeginRedelegate +func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string) (action string, err sdk.Error) { + denom := k.GetParams(ctx).BondDenom + sourceValidatorKey := keys[r.Intn(len(keys))] + sourceValidatorAddress := sdk.AccAddress(sourceValidatorKey.PubKey().Address()) + destValidatorKey := keys[r.Intn(len(keys))] + destValidatorAddress := sdk.AccAddress(destValidatorKey.PubKey().Address()) + delegatorKey := keys[r.Intn(len(keys))] + delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) + // TODO + amount := m.GetAccount(ctx, delegatorAddress).GetCoins().AmountOf(denom) + if amount.GT(sdk.ZeroInt()) { + amount = sdk.NewInt(int64(r.Intn(int(amount.Int64())))) + } + if amount.Equal(sdk.ZeroInt()) { + return "nop", nil + } + msg := stake.MsgBeginRedelegate{ + DelegatorAddr: delegatorAddress, + ValidatorSrcAddr: sourceValidatorAddress, + ValidatorDstAddr: destValidatorAddress, + SharesAmount: sdk.NewRatFromInt(amount), + } + require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + ctx, write := ctx.CacheContext() + result := stake.NewHandler(k)(ctx, msg) + if result.IsOK() { + write() + } + action = fmt.Sprintf("TestMsgBeginRedelegate: %s", msg.GetSignBytes()) + return action, nil + } +} + +// SimulateMsgCompleteRedelegate +func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.TestAndRunTx { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string) (action string, err sdk.Error) { + validatorSrcKey := keys[r.Intn(len(keys))] + validatorSrcAddress := sdk.AccAddress(validatorSrcKey.PubKey().Address()) + validatorDstKey := keys[r.Intn(len(keys))] + validatorDstAddress := sdk.AccAddress(validatorDstKey.PubKey().Address()) + delegatorKey := keys[r.Intn(len(keys))] + delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) + msg := stake.MsgCompleteRedelegate{ + DelegatorAddr: delegatorAddress, + ValidatorSrcAddr: validatorSrcAddress, + ValidatorDstAddr: validatorDstAddress, + } + require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + ctx, write := ctx.CacheContext() + result := stake.NewHandler(k)(ctx, msg) + if result.IsOK() { + write() + } + action = fmt.Sprintf("TestMsgCompleteRedelegate with %s", msg.GetSignBytes()) + return action, nil + } +} + +// SimulationSetup +func SimulationSetup(mapp *mock.App, k stake.Keeper) simulation.RandSetup { + return func(r *rand.Rand, privKeys []crypto.PrivKey) { + ctx := mapp.NewContext(false, abci.Header{}) + stake.InitGenesis(ctx, k, stake.DefaultGenesisState()) + params := k.GetParams(ctx) + denom := params.BondDenom + loose := sdk.ZeroInt() + mapp.AccountMapper.IterateAccounts(ctx, func(acc auth.Account) bool { + balance := sdk.NewInt(int64(r.Intn(1000000))) + acc.SetCoins(acc.GetCoins().Plus(sdk.Coins{sdk.NewIntCoin(denom, balance)})) + mapp.AccountMapper.SetAccount(ctx, acc) + loose = loose.Add(balance) + return false + }) + pool := k.GetPool(ctx) + pool.LooseTokens = pool.LooseTokens.Add(sdk.NewRat(loose.Int64(), 1)) + k.SetPool(ctx, pool) + } +} diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index 8e5a48a21..c26f6c82c 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -2,262 +2,16 @@ package simulation import ( "encoding/json" - "fmt" - "math/rand" "testing" - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/mock" "github.com/cosmos/cosmos-sdk/x/mock/simulation" "github.com/cosmos/cosmos-sdk/x/stake" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto" ) -var ( - stats = make(map[string]int) -) - -// SimulateMsgCreateValidator -func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string) (action string, err sdk.Error) { - denom := k.GetParams(ctx).BondDenom - description := stake.Description{ - Moniker: simulation.RandStringOfLength(r, 10), - } - key := keys[r.Intn(len(keys))] - pubkey := key.PubKey() - address := sdk.AccAddress(pubkey.Address()) - amount := m.GetAccount(ctx, address).GetCoins().AmountOf(denom) - if amount.GT(sdk.ZeroInt()) { - amount = sdk.NewInt(int64(r.Intn(int(amount.Int64())))) - } - if amount.Equal(sdk.ZeroInt()) { - return "nop", nil - } - msg := stake.MsgCreateValidator{ - Description: description, - ValidatorAddr: address, - DelegatorAddr: address, - PubKey: pubkey, - Delegation: sdk.NewIntCoin(denom, amount), - } - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) - ctx, write := ctx.CacheContext() - result := stake.NewHandler(k)(ctx, msg) - if result.IsOK() { - write() - } - stats[fmt.Sprintf("stake/createvalidator/%v", result.IsOK())] += 1 - // require.True(t, result.IsOK(), "expected OK result but instead got %v", result) - action = fmt.Sprintf("TestMsgCreateValidator: %s", msg.GetSignBytes()) - return action, nil - } -} - -// SimulateMsgEditValidator -func SimulateMsgEditValidator(k stake.Keeper) simulation.TestAndRunTx { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string) (action string, err sdk.Error) { - description := stake.Description{ - Moniker: simulation.RandStringOfLength(r, 10), - Identity: simulation.RandStringOfLength(r, 10), - Website: simulation.RandStringOfLength(r, 10), - Details: simulation.RandStringOfLength(r, 10), - } - key := keys[r.Intn(len(keys))] - pubkey := key.PubKey() - address := sdk.AccAddress(pubkey.Address()) - msg := stake.MsgEditValidator{ - Description: description, - ValidatorAddr: address, - } - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) - ctx, write := ctx.CacheContext() - result := stake.NewHandler(k)(ctx, msg) - if result.IsOK() { - write() - } - stats[fmt.Sprintf("stake/editvalidator/%v", result.IsOK())] += 1 - action = fmt.Sprintf("TestMsgEditValidator: %s", msg.GetSignBytes()) - return action, nil - } -} - -// SimulateMsgDelegate -func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string) (action string, err sdk.Error) { - denom := k.GetParams(ctx).BondDenom - validatorKey := keys[r.Intn(len(keys))] - validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) - delegatorKey := keys[r.Intn(len(keys))] - delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) - amount := m.GetAccount(ctx, delegatorAddress).GetCoins().AmountOf(denom) - if amount.GT(sdk.ZeroInt()) { - amount = sdk.NewInt(int64(r.Intn(int(amount.Int64())))) - } - if amount.Equal(sdk.ZeroInt()) { - return "nop", nil - } - msg := stake.MsgDelegate{ - DelegatorAddr: delegatorAddress, - ValidatorAddr: validatorAddress, - Delegation: sdk.NewIntCoin(denom, amount), - } - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) - ctx, write := ctx.CacheContext() - result := stake.NewHandler(k)(ctx, msg) - if result.IsOK() { - write() - } - stats[fmt.Sprintf("stake/delegate/%v", result.IsOK())] += 1 - action = fmt.Sprintf("TestMsgDelegate: %s", msg.GetSignBytes()) - return action, nil - } -} - -// SimulateMsgBeginUnbonding -func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string) (action string, err sdk.Error) { - denom := k.GetParams(ctx).BondDenom - validatorKey := keys[r.Intn(len(keys))] - validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) - delegatorKey := keys[r.Intn(len(keys))] - delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) - amount := m.GetAccount(ctx, delegatorAddress).GetCoins().AmountOf(denom) - if amount.GT(sdk.ZeroInt()) { - amount = sdk.NewInt(int64(r.Intn(int(amount.Int64())))) - } - if amount.Equal(sdk.ZeroInt()) { - return "nop", nil - } - msg := stake.MsgBeginUnbonding{ - DelegatorAddr: delegatorAddress, - ValidatorAddr: validatorAddress, - SharesAmount: sdk.NewRatFromInt(amount), - } - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) - ctx, write := ctx.CacheContext() - result := stake.NewHandler(k)(ctx, msg) - if result.IsOK() { - write() - } - stats[fmt.Sprintf("stake/beginunbonding/%v", result.IsOK())] += 1 - action = fmt.Sprintf("TestMsgBeginUnbonding: %s", msg.GetSignBytes()) - return action, nil - } -} - -// SimulateMsgCompleteUnbonding -func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.TestAndRunTx { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string) (action string, err sdk.Error) { - validatorKey := keys[r.Intn(len(keys))] - validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) - delegatorKey := keys[r.Intn(len(keys))] - delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) - msg := stake.MsgCompleteUnbonding{ - DelegatorAddr: delegatorAddress, - ValidatorAddr: validatorAddress, - } - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) - ctx, write := ctx.CacheContext() - result := stake.NewHandler(k)(ctx, msg) - if result.IsOK() { - write() - } - stats[fmt.Sprintf("stake/completeunbonding/%v", result.IsOK())] += 1 - action = fmt.Sprintf("TestMsgCompleteUnbonding with %s", msg.GetSignBytes()) - return action, nil - } -} - -// SimulateMsgBeginRedelegate -func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string) (action string, err sdk.Error) { - denom := k.GetParams(ctx).BondDenom - sourceValidatorKey := keys[r.Intn(len(keys))] - sourceValidatorAddress := sdk.AccAddress(sourceValidatorKey.PubKey().Address()) - destValidatorKey := keys[r.Intn(len(keys))] - destValidatorAddress := sdk.AccAddress(destValidatorKey.PubKey().Address()) - delegatorKey := keys[r.Intn(len(keys))] - delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) - // TODO - amount := m.GetAccount(ctx, delegatorAddress).GetCoins().AmountOf(denom) - if amount.GT(sdk.ZeroInt()) { - amount = sdk.NewInt(int64(r.Intn(int(amount.Int64())))) - } - if amount.Equal(sdk.ZeroInt()) { - return "nop", nil - } - msg := stake.MsgBeginRedelegate{ - DelegatorAddr: delegatorAddress, - ValidatorSrcAddr: sourceValidatorAddress, - ValidatorDstAddr: destValidatorAddress, - SharesAmount: sdk.NewRatFromInt(amount), - } - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) - ctx, write := ctx.CacheContext() - result := stake.NewHandler(k)(ctx, msg) - if result.IsOK() { - write() - } - stats[fmt.Sprintf("stake/beginredelegate/%v", result.IsOK())] += 1 - action = fmt.Sprintf("TestMsgBeginRedelegate: %s", msg.GetSignBytes()) - return action, nil - } -} - -// SimulateMsgCompleteRedelegate -func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.TestAndRunTx { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string) (action string, err sdk.Error) { - validatorSrcKey := keys[r.Intn(len(keys))] - validatorSrcAddress := sdk.AccAddress(validatorSrcKey.PubKey().Address()) - validatorDstKey := keys[r.Intn(len(keys))] - validatorDstAddress := sdk.AccAddress(validatorDstKey.PubKey().Address()) - delegatorKey := keys[r.Intn(len(keys))] - delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) - msg := stake.MsgCompleteRedelegate{ - DelegatorAddr: delegatorAddress, - ValidatorSrcAddr: validatorSrcAddress, - ValidatorDstAddr: validatorDstAddress, - } - require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) - ctx, write := ctx.CacheContext() - result := stake.NewHandler(k)(ctx, msg) - if result.IsOK() { - write() - } - stats[fmt.Sprintf("stake/completeredelegate/%v", result.IsOK())] += 1 - action = fmt.Sprintf("TestMsgCompleteRedelegate with %s", msg.GetSignBytes()) - return action, nil - } -} - -// SimulationSetup -func SimulationSetup(mapp *mock.App, k stake.Keeper) simulation.RandSetup { - return func(r *rand.Rand, privKeys []crypto.PrivKey) { - ctx := mapp.NewContext(false, abci.Header{}) - stake.InitGenesis(ctx, k, stake.DefaultGenesisState()) - params := k.GetParams(ctx) - denom := params.BondDenom - loose := sdk.ZeroInt() - mapp.AccountMapper.IterateAccounts(ctx, func(acc auth.Account) bool { - balance := sdk.NewInt(int64(r.Intn(1000000))) - acc.SetCoins(acc.GetCoins().Plus(sdk.Coins{sdk.NewIntCoin(denom, balance)})) - mapp.AccountMapper.SetAccount(ctx, acc) - loose = loose.Add(balance) - return false - }) - pool := k.GetPool(ctx) - pool.LooseTokens = pool.LooseTokens.Add(sdk.NewRat(loose.Int64(), 1)) - k.SetPool(ctx, pool) - } -} - // TestStakeWithRandomMessages func TestStakeWithRandomMessages(t *testing.T) { mapp := mock.NewApp() @@ -297,6 +51,4 @@ func TestStakeWithRandomMessages(t *testing.T) { AllInvariants(coinKeeper, stakeKeeper, mapp.AccountMapper), }, 10, 100, 500, ) - - fmt.Printf("Stats: %v\n", stats) }