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

update sims operations to use baseapp #4946

Merged
merged 84 commits into from
Oct 23, 2019
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
f22313a
update operations to use baseapp
fedekunze Aug 22, 2019
8f1240c
Merge branch 'master' of https://github.com/cosmos/cosmos-sdk into fe…
fedekunze Aug 26, 2019
5a31d65
updates and cleanup operations
fedekunze Aug 26, 2019
89cf7b9
Merge branch 'master' of https://github.com/cosmos/cosmos-sdk into fe…
fedekunze Aug 27, 2019
5f606ea
update operations
fedekunze Aug 27, 2019
d450ebb
restructure sim ops params
fedekunze Aug 27, 2019
abb288f
merge master
fedekunze Aug 27, 2019
51bf12b
merge master
fedekunze Aug 28, 2019
fe3f6f3
rename sim /operations/msg.go to /operations.go
fedekunze Aug 28, 2019
f3a398b
move GenTx to a helper pkg to avoid circle deps
fedekunze Aug 28, 2019
666a301
rm msg.ValidateBasic
fedekunze Aug 28, 2019
1bb0adc
changelog
fedekunze Aug 28, 2019
b300de0
random fees; delete auth's DeductFees sim operation
fedekunze Aug 29, 2019
bcf6796
add chain-id for sig verification
fedekunze Aug 29, 2019
bb47279
Update x/simulation/account.go
fedekunze Aug 29, 2019
b52a122
fix bank, gov and distr errors
fedekunze Aug 29, 2019
08af7df
Merge branch 'fedekunze/4935-sim-ops-baseapp' of https://github.com/c…
fedekunze Aug 29, 2019
a0a4105
fix staking and slashing errors; increase prob for send enabled
fedekunze Aug 29, 2019
0d33e53
increase gas x10
fedekunze Aug 29, 2019
d2d8e06
make format
fedekunze Aug 29, 2019
882b529
fix some distr and staking edge cases
fedekunze Aug 29, 2019
86798bd
fix all edge cases
fedekunze Aug 30, 2019
8a5a8f7
golang ci
fedekunze Aug 30, 2019
d2433c8
rename acc vars; default no fees to 0stake
fedekunze Aug 30, 2019
0172569
cleanup; check for exchange rate and skip invalid ops
fedekunze Aug 30, 2019
2a2c369
fixes
fedekunze Aug 30, 2019
50f6959
check for max entries
fedekunze Aug 30, 2019
309348a
add pubkey to genaccounts
fedekunze Aug 30, 2019
4e2d3b3
fix gov bug
fedekunze Sep 2, 2019
e662201
update staking sim ops
fedekunze Sep 2, 2019
f1c3e12
fix small redelegation error
fedekunze Sep 2, 2019
3298d5d
fix small self delegation on unjail
fedekunze Sep 2, 2019
8501356
Merge branch 'master' of https://github.com/cosmos/cosmos-sdk into fe…
fedekunze Sep 2, 2019
e615ee1
rm inf loop on random val/accs
fedekunze Sep 2, 2019
9e81756
copy array
fedekunze Sep 2, 2019
490bc77
add ok boolean to RandomValidator return values
fedekunze Sep 2, 2019
2139e75
format
fedekunze Sep 2, 2019
7da6f34
Update x/bank/simulation/operations.go
fedekunze Sep 4, 2019
bd7ed37
Update simapp/helpers/test_helpers.go
fedekunze Sep 4, 2019
59620ed
address @colin-axner comments
fedekunze Sep 4, 2019
b2b4a63
add genaccount pubkey validation
fedekunze Sep 4, 2019
c739839
fix test
fedekunze Sep 4, 2019
8d5a90e
update operations and move RandomFees to x/simulation
fedekunze Sep 5, 2019
52875e5
update gov ops
fedekunze Sep 5, 2019
ae94071
merge master
fedekunze Sep 5, 2019
c49543f
address @alexanderbez comments
fedekunze Sep 6, 2019
86503a9
avoid modifications to config
fedekunze Sep 6, 2019
496fa15
reorder params
fedekunze Sep 6, 2019
337a25c
Merge branch 'master' of https://github.com/cosmos/cosmos-sdk into fe…
fedekunze Sep 9, 2019
efcab1d
changelog
fedekunze Sep 9, 2019
d4df4bf
Update x/distribution/simulation/genesis.go
fedekunze Sep 11, 2019
4f9961a
merge master
fedekunze Sep 24, 2019
8396254
Merge branch 'fedekunze/4935-sim-ops-baseapp' of https://github.com/c…
fedekunze Sep 24, 2019
a188a77
remove named return values
fedekunze Sep 24, 2019
ea3594b
ensure all operations are simulated
fedekunze Sep 25, 2019
f39fc77
Merge branch 'master' into fedekunze/4935-sim-ops-baseapp
fedekunze Sep 25, 2019
c79bc9a
golangci
fedekunze Sep 25, 2019
5491db8
Merge branch 'fedekunze/4935-sim-ops-baseapp' of https://github.com/c…
fedekunze Sep 25, 2019
c9faeeb
add nolint
fedekunze Sep 25, 2019
b310b12
disable whitespace and funlen linter
fedekunze Sep 25, 2019
446179d
disable godox
fedekunze Sep 25, 2019
42eebc3
add TODO on unjail
fedekunze Sep 25, 2019
272e08a
update ops weights
fedekunze Sep 25, 2019
5a3712d
address @alexanderbez comments
fedekunze Sep 30, 2019
c45382b
remove dup
fedekunze Sep 30, 2019
efd2edb
update godoc
fedekunze Sep 30, 2019
daa8206
Merge branch 'master' into fedekunze/4935-sim-ops-baseapp
fedekunze Sep 30, 2019
def149f
x/slashing/simulation/operations.go linting
alexanderbez Sep 30, 2019
57bcfbb
x/staking/simulation/operations.go linting
alexanderbez Sep 30, 2019
5719686
update operations format
fedekunze Oct 1, 2019
0bf30c3
Merge branch 'master' into fedekunze/4935-sim-ops-baseapp
fedekunze Oct 1, 2019
7c3314e
x/bank/simulation/operations.go linting
alexanderbez Oct 1, 2019
4a24fb8
x/distribution/simulation/operations.go linting
alexanderbez Oct 2, 2019
a15b55f
x/staking/simulation/operations.go linting
alexanderbez Oct 2, 2019
95f0b04
merge master
fedekunze Oct 15, 2019
42fd548
start changes: make bank simulate send multiple coins, code cleanup
AdityaSripal Oct 17, 2019
0c65eda
fix nondeterminism bug
AdityaSripal Oct 17, 2019
cf215f8
fix txsiglimit err
AdityaSripal Oct 17, 2019
99baf18
fix multisend bug
AdityaSripal Oct 17, 2019
33ee0e0
simplify simulation, cleanup opt privkey args
AdityaSripal Oct 18, 2019
bc1027d
make slashing test invalid unjail msgs
AdityaSripal Oct 18, 2019
202fe2b
Merge branch 'master' into fedekunze/4935-sim-ops-baseapp
alexanderbez Oct 22, 2019
716d00d
Update simapp/state.go
alexanderbez Oct 22, 2019
6ed2005
golangCI changes
fedekunze Oct 23, 2019
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ longer panics if the store to load contains substores that we didn't explicitly
`ParamChangeProposal`s
* (simulation) [\#4893](https://github.com/cosmos/cosmos-sdk/issues/4893) Change SimApp keepers to be public and add getter functions for keys and codec
* (simulation) [\#4906](https://github.com/cosmos/cosmos-sdk/issues/4906) Add simulation `Config` struct that wraps simulation flags
* (simulation) [\#4935](https://github.com/cosmos/cosmos-sdk/issues/4935) Update simulation to reflect a proper `ABCI` application without bypassing `BaseApp` semantics
* (store) [\#4792](https://github.com/cosmos/cosmos-sdk/issues/4792) panic on non-registered store
* (types) [\#4821](https://github.com/cosmos/cosmos-sdk/issues/4821) types/errors package added with support for stacktraces. It is meant as a more feature-rich replacement for sdk.Errors in the mid-term.

Expand Down
43 changes: 43 additions & 0 deletions simapp/helpers/test_helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package helpers

import (
"math/rand"

"github.com/tendermint/tendermint/crypto"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/simulation"
)

// GenTx generates a signed mock transaction.
func GenTx(msgs []sdk.Msg, accnums []uint64, seq []uint64, priv ...crypto.PrivKey) auth.StdTx {
Copy link
Collaborator Author

@fedekunze fedekunze Aug 28, 2019

Choose a reason for hiding this comment

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

ideally, we should move all the contents from simapp/test_helpers.go to this file and update the keepers that use it, although that's out of scope from this PR. cc: @colin-axner

// Make the transaction free
fee := auth.StdFee{
Amount: sdk.NewCoins(sdk.NewInt64Coin("foocoin", 0)), // TODO: this should be the default bond denom
Gas: 100000,
}

sigs := make([]auth.StdSignature, len(priv))

// create a random length memo
seed := rand.Int63()
r := rand.New(rand.NewSource(seed))
fedekunze marked this conversation as resolved.
Show resolved Hide resolved

memo := simulation.RandStringOfLength(r, simulation.RandIntBetween(r, 0, 140))

for i, p := range priv {
// use a empty chainID for ease of testing
sig, err := p.Sign(auth.StdSignBytes("", accnums[i], seq[i], fee, msgs, memo))
if err != nil {
panic(err)
}

sigs[i] = auth.StdSignature{
PubKey: p.PubKey(),
Signature: sig,
}
}

return auth.NewStdTx(msgs, fee, sigs, memo)
}
54 changes: 27 additions & 27 deletions simapp/sim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@ import (
"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
authsimops "github.com/cosmos/cosmos-sdk/x/auth/simulation/operations"
banksimops "github.com/cosmos/cosmos-sdk/x/bank/simulation/operations"
authsim "github.com/cosmos/cosmos-sdk/x/auth/simulation"
banksim "github.com/cosmos/cosmos-sdk/x/bank/simulation"
distr "github.com/cosmos/cosmos-sdk/x/distribution"
distrsimops "github.com/cosmos/cosmos-sdk/x/distribution/simulation/operations"
distrsim "github.com/cosmos/cosmos-sdk/x/distribution/simulation"
"github.com/cosmos/cosmos-sdk/x/gov"
govsimops "github.com/cosmos/cosmos-sdk/x/gov/simulation/operations"
govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/cosmos/cosmos-sdk/x/params"
paramsimops "github.com/cosmos/cosmos-sdk/x/params/simulation/operations"
paramsim "github.com/cosmos/cosmos-sdk/x/params/simulation"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/slashing"
slashingsimops "github.com/cosmos/cosmos-sdk/x/slashing/simulation/operations"
slashingsim "github.com/cosmos/cosmos-sdk/x/slashing/simulation"
"github.com/cosmos/cosmos-sdk/x/staking"
stakingsimops "github.com/cosmos/cosmos-sdk/x/staking/simulation/operations"
stakingsim "github.com/cosmos/cosmos-sdk/x/staking/simulation"
"github.com/cosmos/cosmos-sdk/x/supply"
)

Expand Down Expand Up @@ -65,7 +65,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
authsimops.SimulateDeductFee(app.AccountKeeper, app.SupplyKeeper),
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
authsim.SimulateDeductFee(app.AccountKeeper, app.SupplyKeeper),
},
{
func(_ *rand.Rand) int {
Expand All @@ -76,7 +76,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
banksimops.SimulateMsgSend(app.AccountKeeper, app.BankKeeper),
banksim.SimulateMsgSend(app.AccountKeeper, app.BankKeeper),
},
{
func(_ *rand.Rand) int {
Expand All @@ -87,7 +87,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
banksimops.SimulateSingleInputMsgMultiSend(app.AccountKeeper, app.BankKeeper),
banksim.SimulateSingleInputMsgMultiSend(app.AccountKeeper, app.BankKeeper),
},
{
func(_ *rand.Rand) int {
Expand All @@ -98,7 +98,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
distrsimops.SimulateMsgSetWithdrawAddress(app.DistrKeeper),
distrsim.SimulateMsgSetWithdrawAddress(app.AccountKeeper, app.DistrKeeper),
},
{
func(_ *rand.Rand) int {
Expand All @@ -109,7 +109,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
distrsimops.SimulateMsgWithdrawDelegatorReward(app.DistrKeeper),
distrsim.SimulateMsgWithdrawDelegatorReward(app.AccountKeeper, app.DistrKeeper),
},
{
func(_ *rand.Rand) int {
Expand All @@ -120,7 +120,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
distrsimops.SimulateMsgWithdrawValidatorCommission(app.DistrKeeper),
distrsim.SimulateMsgWithdrawValidatorCommission(app.AccountKeeper, app.DistrKeeper),
},
{
func(_ *rand.Rand) int {
Expand All @@ -131,7 +131,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
govsimops.SimulateSubmittingVotingAndSlashingForProposal(app.GovKeeper, govsimops.SimulateTextProposalContent),
govsim.SimulateSubmittingVotingAndSlashingForProposal(app.AccountKeeper, app.GovKeeper, govsim.SimulateTextProposalContent),
},
{
func(_ *rand.Rand) int {
Expand All @@ -142,7 +142,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
govsimops.SimulateSubmittingVotingAndSlashingForProposal(app.GovKeeper, distrsimops.SimulateCommunityPoolSpendProposalContent(app.DistrKeeper)),
govsim.SimulateSubmittingVotingAndSlashingForProposal(app.AccountKeeper, app.GovKeeper, distrsim.SimulateCommunityPoolSpendProposalContent(app.DistrKeeper)),
},
{
func(_ *rand.Rand) int {
Expand All @@ -153,7 +153,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
govsimops.SimulateSubmittingVotingAndSlashingForProposal(app.GovKeeper, paramsimops.SimulateParamChangeProposalContent(paramChanges)),
govsim.SimulateSubmittingVotingAndSlashingForProposal(app.AccountKeeper, app.GovKeeper, paramsim.SimulateParamChangeProposalContent(paramChanges)),
},
{
func(_ *rand.Rand) int {
Expand All @@ -164,7 +164,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
govsimops.SimulateMsgDeposit(app.GovKeeper),
govsim.SimulateMsgDeposit(app.AccountKeeper, app.GovKeeper),
},
{
func(_ *rand.Rand) int {
Expand All @@ -175,7 +175,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
stakingsimops.SimulateMsgCreateValidator(app.AccountKeeper, app.StakingKeeper),
stakingsim.SimulateMsgCreateValidator(app.AccountKeeper, app.StakingKeeper),
},
{
func(_ *rand.Rand) int {
Expand All @@ -186,7 +186,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
stakingsimops.SimulateMsgEditValidator(app.StakingKeeper),
stakingsim.SimulateMsgEditValidator(app.AccountKeeper, app.StakingKeeper),
},
{
func(_ *rand.Rand) int {
Expand All @@ -197,7 +197,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
stakingsimops.SimulateMsgDelegate(app.AccountKeeper, app.StakingKeeper),
stakingsim.SimulateMsgDelegate(app.AccountKeeper, app.StakingKeeper),
},
{
func(_ *rand.Rand) int {
Expand All @@ -208,7 +208,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
stakingsimops.SimulateMsgUndelegate(app.AccountKeeper, app.StakingKeeper),
stakingsim.SimulateMsgUndelegate(app.AccountKeeper, app.StakingKeeper),
},
{
func(_ *rand.Rand) int {
Expand All @@ -219,7 +219,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
stakingsimops.SimulateMsgBeginRedelegate(app.AccountKeeper, app.StakingKeeper),
stakingsim.SimulateMsgBeginRedelegate(app.AccountKeeper, app.StakingKeeper),
},
{
func(_ *rand.Rand) int {
Expand All @@ -230,7 +230,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
})
return v
}(nil),
slashingsimops.SimulateMsgUnjail(app.SlashingKeeper),
slashingsim.SimulateMsgUnjail(app.AccountKeeper),
},
// {
// func(_ *rand.Rand) int {
Expand All @@ -241,7 +241,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
// })
// return v
// }(nil),
// nftsimops.SimulateMsgTransferNFT(app.NFTKeeper),
// nftsim.SimulateMsgTransferNFT(app.NFTKeeper),
// },
// {
// func(_ *rand.Rand) int {
Expand All @@ -252,7 +252,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
// })
// return v
// }(nil),
// nftsimops.SimulateMsgEditNFTMetadata(app.NFTKeeper),
// nftsim.SimulateMsgEditNFTMetadata(app.NFTKeeper),
// },
// {
// func(_ *rand.Rand) int {
Expand All @@ -263,7 +263,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
// })
// return v
// }(nil),
// nftsimops.SimulateMsgMintNFT(app.NFTKeeper),
// nftsim.SimulateMsgMintNFT(app.NFTKeeper),
// },
// {
// func(_ *rand.Rand) int {
Expand All @@ -274,7 +274,7 @@ func testAndRunTxs(app *SimApp, config simulation.Config) []simulation.WeightedO
// })
// return v
// }(nil),
// nftsimops.SimulateMsgBurnNFT(app.NFTKeeper),
// nftsim.SimulateMsgBurnNFT(app.NFTKeeper),
// },
}
}
Expand Down
32 changes: 3 additions & 29 deletions simapp/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

bam "github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/simapp/helpers"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/genaccounts"
Expand Down Expand Up @@ -103,33 +104,6 @@ func CheckBalance(t *testing.T, app *SimApp, addr sdk.AccAddress, exp sdk.Coins)
require.Equal(t, exp, res.GetCoins())
}

// GenTx generates a signed mock transaction.
func GenTx(msgs []sdk.Msg, accnums []uint64, seq []uint64, priv ...crypto.PrivKey) auth.StdTx {
// Make the transaction free
fee := auth.StdFee{
Amount: sdk.NewCoins(sdk.NewInt64Coin("foocoin", 0)),
Gas: 100000,
}

sigs := make([]auth.StdSignature, len(priv))
memo := "testmemotestmemo"

for i, p := range priv {
// use a empty chainID for ease of testing
sig, err := p.Sign(auth.StdSignBytes("", accnums[i], seq[i], fee, msgs, memo))
if err != nil {
panic(err)
}

sigs[i] = auth.StdSignature{
PubKey: p.PubKey(),
Signature: sig,
}
}

return auth.NewStdTx(msgs, fee, sigs, memo)
}

// SignCheckDeliver checks a generated signed transaction and simulates a
// block commitment with the given transaction. A test assertion is made using
// the parameter 'expPass' against the result. A corresponding result is
Expand All @@ -139,7 +113,7 @@ func SignCheckDeliver(
accNums, seq []uint64, expSimPass, expPass bool, priv ...crypto.PrivKey,
) sdk.Result {

tx := GenTx(msgs, accNums, seq, priv...)
tx := helpers.GenTx(msgs, accNums, seq, priv...)

txBytes, err := cdc.MarshalBinaryLengthPrefixed(tx)
require.Nil(t, err)
Expand Down Expand Up @@ -175,7 +149,7 @@ func SignCheckDeliver(
func GenSequenceOfTxs(msgs []sdk.Msg, accnums []uint64, initSeqNums []uint64, numToGenerate int, priv ...crypto.PrivKey) []auth.StdTx {
txs := make([]auth.StdTx, numToGenerate)
for i := 0; i < numToGenerate; i++ {
txs[i] = GenTx(msgs, accnums, initSeqNums, priv...)
txs[i] = helpers.GenTx(msgs, accnums, initSeqNums, priv...)
incrementAllSequenceNumbers(initSeqNums)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package operations
package simulation

import (
"errors"
Expand All @@ -8,13 +8,13 @@ import (

"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/auth/keeper"
"github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)

// SimulateDeductFee
func SimulateDeductFee(ak auth.AccountKeeper, supplyKeeper types.SupplyKeeper) simulation.Operation {
func SimulateDeductFee(ak keeper.AccountKeeper, supplyKeeper types.SupplyKeeper) simulation.Operation {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accs []simulation.Account) (
opMsg simulation.OperationMsg, fOps []simulation.FutureOperation, err error) {
Expand Down
Loading