From 9410b6287c8890a9ce21b011d72347c9a669b70c Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Tue, 2 Oct 2018 05:01:18 -0700 Subject: [PATCH] Merge PR #2425: simulation: Make bank testing auth configurable --- PENDING.md | 1 + cmd/gaia/app/sim_test.go | 2 +- x/bank/simulation/msgs.go | 124 ++++++++++++++++++++++------------ x/bank/simulation/sim_test.go | 5 +- 4 files changed, 85 insertions(+), 47 deletions(-) diff --git a/PENDING.md b/PENDING.md index 7458a110a..f36d4fd3e 100644 --- a/PENDING.md +++ b/PENDING.md @@ -138,6 +138,7 @@ IMPROVEMENTS * [simulation] Make logs not just pure strings, speeding it up by a large factor at greater block heights \#2282 * [simulation] Add a concept of weighting the operations \#2303 * [simulation] Logs get written to file if large, and also get printed on panics \#2285 + * [simulation] Bank simulations now makes testing auth configurable \#2425 * [gaiad] \#1992 Add optional flag to `gaiad testnet` to make config directory of daemon (default `gaiad`) and cli (default `gaiacli`) configurable * [x/stake] Add stake `Queriers` for Gaia-lite endpoints. This increases the staking endpoints performance by reusing the staking `keeper` logic for queries. [#2249](https://github.com/cosmos/cosmos-sdk/pull/2149) * [store] [\#2017](https://github.com/cosmos/cosmos-sdk/issues/2017) Refactor diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 6097b5a08..db08d872f 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -90,7 +90,7 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage { func testAndRunTxs(app *GaiaApp) []simulation.WeightedOperation { return []simulation.WeightedOperation{ - {100, banksim.SimulateSingleInputMsgSend(app.accountMapper)}, + {100, banksim.SingleInputSendMsg(app.accountMapper, app.bankKeeper)}, {5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, app.stakeKeeper)}, {100, govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper)}, {100, stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper)}, diff --git a/x/bank/simulation/msgs.go b/x/bank/simulation/msgs.go index 0b8ec3026..0a253235e 100644 --- a/x/bank/simulation/msgs.go +++ b/x/bank/simulation/msgs.go @@ -15,47 +15,36 @@ import ( "github.com/tendermint/tendermint/crypto" ) -// SimulateSingleInputMsgSend tests and runs a single msg send, with one input and one output, where both +// SingleInputSendTx tests and runs a single msg send w/ auth, with one input and one output, where both // accounts already exist. -func SimulateSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation { +func SingleInputSendTx(mapper auth.AccountMapper) simulation.Operation { return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOps []simulation.FutureOperation, err error) { - fromAcc := simulation.RandomAcc(r, accs) - toAcc := simulation.RandomAcc(r, accs) - // Disallow sending money to yourself - for { - if !fromAcc.PubKey.Equals(toAcc.PubKey) { - break - } - toAcc = simulation.RandomAcc(r, accs) + fromAcc, action, msg, abort := createSingleInputSendMsg(r, ctx, accs, mapper) + if abort { + return action, nil, nil } - toAddr := toAcc.Address - initFromCoins := mapper.GetAccount(ctx, fromAcc.Address).GetCoins() - - if len(initFromCoins) == 0 { - return "skipping, no coins at all", nil, nil + err = sendAndVerifyMsgSend(app, mapper, msg, ctx, []crypto.PrivKey{fromAcc.PrivKey}, nil) + if err != nil { + return "", nil, err } + event("bank/sendAndVerifyTxSend/ok") - denomIndex := r.Intn(len(initFromCoins)) - amt, goErr := randPositiveInt(r, initFromCoins[denomIndex].Amount) - if goErr != nil { - return "skipping bank send due to account having no coins of denomination " + initFromCoins[denomIndex].Denom, nil, nil + return action, nil, nil + } +} + +// SingleInputSendMsg tests and runs a single msg send, with one input and one output, where both +// accounts already exist. +func SingleInputSendMsg(mapper auth.AccountMapper, bk bank.Keeper) simulation.Operation { + handler := bank.NewHandler(bk) + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOps []simulation.FutureOperation, err error) { + fromAcc, action, msg, abort := createSingleInputSendMsg(r, ctx, accs, mapper) + if abort { + return action, nil, nil } - - action = fmt.Sprintf("%s is sending %s %s to %s", - fromAcc.Address.String(), - amt.String(), - initFromCoins[denomIndex].Denom, - toAddr.String(), - ) - - coins := sdk.Coins{{initFromCoins[denomIndex].Denom, amt}} - var msg = bank.MsgSend{ - Inputs: []bank.Input{bank.NewInput(fromAcc.Address, coins)}, - Outputs: []bank.Output{bank.NewOutput(toAddr, coins)}, - } - goErr = sendAndVerifyMsgSend(app, mapper, msg, ctx, []crypto.PrivKey{fromAcc.PrivKey}) - if goErr != nil { - return "", nil, goErr + err = sendAndVerifyMsgSend(app, mapper, msg, ctx, []crypto.PrivKey{fromAcc.PrivKey}, handler) + if err != nil { + return "", nil, err } event("bank/sendAndVerifyMsgSend/ok") @@ -63,8 +52,47 @@ func SimulateSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation } } +func createSingleInputSendMsg(r *rand.Rand, ctx sdk.Context, accs []simulation.Account, mapper auth.AccountMapper) (fromAcc simulation.Account, action string, msg bank.MsgSend, abort bool) { + fromAcc = simulation.RandomAcc(r, accs) + toAcc := simulation.RandomAcc(r, accs) + // Disallow sending money to yourself + for { + if !fromAcc.PubKey.Equals(toAcc.PubKey) { + break + } + toAcc = simulation.RandomAcc(r, accs) + } + toAddr := toAcc.Address + initFromCoins := mapper.GetAccount(ctx, fromAcc.Address).GetCoins() + + if len(initFromCoins) == 0 { + return fromAcc, "skipping, no coins at all", msg, true + } + + denomIndex := r.Intn(len(initFromCoins)) + amt, goErr := randPositiveInt(r, initFromCoins[denomIndex].Amount) + if goErr != nil { + return fromAcc, "skipping bank send due to account having no coins of denomination " + initFromCoins[denomIndex].Denom, msg, true + } + + action = fmt.Sprintf("%s is sending %s %s to %s", + fromAcc.Address.String(), + amt.String(), + initFromCoins[denomIndex].Denom, + toAddr.String(), + ) + + coins := sdk.Coins{{initFromCoins[denomIndex].Denom, amt}} + msg = bank.MsgSend{ + Inputs: []bank.Input{bank.NewInput(fromAcc.Address, coins)}, + Outputs: []bank.Output{bank.NewOutput(toAddr, coins)}, + } + return +} + // Sends and verifies the transition of a msg send. This fails if there are repeated inputs or outputs -func sendAndVerifyMsgSend(app *baseapp.BaseApp, mapper auth.AccountMapper, msg bank.MsgSend, ctx sdk.Context, privkeys []crypto.PrivKey) error { +// pass in handler as nil to handle txs, otherwise handle msgs +func sendAndVerifyMsgSend(app *baseapp.BaseApp, mapper auth.AccountMapper, msg bank.MsgSend, ctx sdk.Context, privkeys []crypto.PrivKey, handler sdk.Handler) error { initialInputAddrCoins := make([]sdk.Coins, len(msg.Inputs)) initialOutputAddrCoins := make([]sdk.Coins, len(msg.Outputs)) AccountNumbers := make([]int64, len(msg.Inputs)) @@ -80,14 +108,22 @@ func sendAndVerifyMsgSend(app *baseapp.BaseApp, mapper auth.AccountMapper, msg b acc := mapper.GetAccount(ctx, msg.Outputs[i].Address) initialOutputAddrCoins[i] = acc.GetCoins() } - tx := mock.GenTx([]sdk.Msg{msg}, - AccountNumbers, - SequenceNumbers, - privkeys...) - res := app.Deliver(tx) - if !res.IsOK() { - // TODO: Do this in a more 'canonical' way - return fmt.Errorf("Deliver failed %v", res) + if handler != nil { + res := handler(ctx, msg) + if !res.IsOK() { + // TODO: Do this in a more 'canonical' way + return fmt.Errorf("handling msg failed %v", res) + } + } else { + tx := mock.GenTx([]sdk.Msg{msg}, + AccountNumbers, + SequenceNumbers, + privkeys...) + res := app.Deliver(tx) + if !res.IsOK() { + // TODO: Do this in a more 'canonical' way + return fmt.Errorf("Deliver failed %v", res) + } } for i := 0; i < len(msg.Inputs); i++ { diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index 819289845..ce3877a62 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -32,14 +32,15 @@ func TestBankWithRandomMessages(t *testing.T) { simulation.Simulate( t, mapp.BaseApp, appStateFn, []simulation.WeightedOperation{ - {1, SimulateSingleInputMsgSend(mapper)}, + {1, SingleInputSendTx(mapper)}, + {1, SingleInputSendMsg(mapper, bankKeeper)}, }, []simulation.RandSetup{}, []simulation.Invariant{ NonnegativeBalanceInvariant(mapper), TotalCoinsInvariant(mapper, func() sdk.Coins { return mapp.TotalCoinsSupply }), }, - 30, 30, + 30, 60, false, ) }