Merge PR #2425: simulation: Make bank testing auth configurable
This commit is contained in:
parent
a3b31c7a6b
commit
9410b6287c
|
@ -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] 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] Add a concept of weighting the operations \#2303
|
||||||
* [simulation] Logs get written to file if large, and also get printed on panics \#2285
|
* [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
|
* [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)
|
* [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
|
* [store] [\#2017](https://github.com/cosmos/cosmos-sdk/issues/2017) Refactor
|
||||||
|
|
|
@ -90,7 +90,7 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
|
||||||
|
|
||||||
func testAndRunTxs(app *GaiaApp) []simulation.WeightedOperation {
|
func testAndRunTxs(app *GaiaApp) []simulation.WeightedOperation {
|
||||||
return []simulation.WeightedOperation{
|
return []simulation.WeightedOperation{
|
||||||
{100, banksim.SimulateSingleInputMsgSend(app.accountMapper)},
|
{100, banksim.SingleInputSendMsg(app.accountMapper, app.bankKeeper)},
|
||||||
{5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, app.stakeKeeper)},
|
{5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper, app.stakeKeeper)},
|
||||||
{100, govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper)},
|
{100, govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper)},
|
||||||
{100, stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper)},
|
{100, stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper)},
|
||||||
|
|
|
@ -15,47 +15,36 @@ import (
|
||||||
"github.com/tendermint/tendermint/crypto"
|
"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.
|
// 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) {
|
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)
|
fromAcc, action, msg, abort := createSingleInputSendMsg(r, ctx, accs, mapper)
|
||||||
toAcc := simulation.RandomAcc(r, accs)
|
if abort {
|
||||||
// Disallow sending money to yourself
|
return action, nil, nil
|
||||||
for {
|
|
||||||
if !fromAcc.PubKey.Equals(toAcc.PubKey) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
toAcc = simulation.RandomAcc(r, accs)
|
|
||||||
}
|
}
|
||||||
toAddr := toAcc.Address
|
err = sendAndVerifyMsgSend(app, mapper, msg, ctx, []crypto.PrivKey{fromAcc.PrivKey}, nil)
|
||||||
initFromCoins := mapper.GetAccount(ctx, fromAcc.Address).GetCoins()
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
if len(initFromCoins) == 0 {
|
|
||||||
return "skipping, no coins at all", nil, nil
|
|
||||||
}
|
}
|
||||||
|
event("bank/sendAndVerifyTxSend/ok")
|
||||||
|
|
||||||
denomIndex := r.Intn(len(initFromCoins))
|
return action, nil, nil
|
||||||
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
|
|
||||||
|
// 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
|
||||||
}
|
}
|
||||||
|
err = sendAndVerifyMsgSend(app, mapper, msg, ctx, []crypto.PrivKey{fromAcc.PrivKey}, handler)
|
||||||
action = fmt.Sprintf("%s is sending %s %s to %s",
|
if err != nil {
|
||||||
fromAcc.Address.String(),
|
return "", nil, err
|
||||||
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
|
|
||||||
}
|
}
|
||||||
event("bank/sendAndVerifyMsgSend/ok")
|
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
|
// 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))
|
initialInputAddrCoins := make([]sdk.Coins, len(msg.Inputs))
|
||||||
initialOutputAddrCoins := make([]sdk.Coins, len(msg.Outputs))
|
initialOutputAddrCoins := make([]sdk.Coins, len(msg.Outputs))
|
||||||
AccountNumbers := make([]int64, len(msg.Inputs))
|
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)
|
acc := mapper.GetAccount(ctx, msg.Outputs[i].Address)
|
||||||
initialOutputAddrCoins[i] = acc.GetCoins()
|
initialOutputAddrCoins[i] = acc.GetCoins()
|
||||||
}
|
}
|
||||||
tx := mock.GenTx([]sdk.Msg{msg},
|
if handler != nil {
|
||||||
AccountNumbers,
|
res := handler(ctx, msg)
|
||||||
SequenceNumbers,
|
if !res.IsOK() {
|
||||||
privkeys...)
|
// TODO: Do this in a more 'canonical' way
|
||||||
res := app.Deliver(tx)
|
return fmt.Errorf("handling msg failed %v", res)
|
||||||
if !res.IsOK() {
|
}
|
||||||
// TODO: Do this in a more 'canonical' way
|
} else {
|
||||||
return fmt.Errorf("Deliver failed %v", res)
|
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++ {
|
for i := 0; i < len(msg.Inputs); i++ {
|
||||||
|
|
|
@ -32,14 +32,15 @@ func TestBankWithRandomMessages(t *testing.T) {
|
||||||
simulation.Simulate(
|
simulation.Simulate(
|
||||||
t, mapp.BaseApp, appStateFn,
|
t, mapp.BaseApp, appStateFn,
|
||||||
[]simulation.WeightedOperation{
|
[]simulation.WeightedOperation{
|
||||||
{1, SimulateSingleInputMsgSend(mapper)},
|
{1, SingleInputSendTx(mapper)},
|
||||||
|
{1, SingleInputSendMsg(mapper, bankKeeper)},
|
||||||
},
|
},
|
||||||
[]simulation.RandSetup{},
|
[]simulation.RandSetup{},
|
||||||
[]simulation.Invariant{
|
[]simulation.Invariant{
|
||||||
NonnegativeBalanceInvariant(mapper),
|
NonnegativeBalanceInvariant(mapper),
|
||||||
TotalCoinsInvariant(mapper, func() sdk.Coins { return mapp.TotalCoinsSupply }),
|
TotalCoinsInvariant(mapper, func() sdk.Coins { return mapp.TotalCoinsSupply }),
|
||||||
},
|
},
|
||||||
30, 30,
|
30, 60,
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue