/
operations.go
138 lines (114 loc) · 4.53 KB
/
operations.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package simulation
// DONTCOVER
import (
"math/rand"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/simapp/helpers"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmicbet/ledger/app/params"
"github.com/cosmicbet/ledger/x/wta/keeper"
"github.com/cosmicbet/ledger/x/wta/types"
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/codec"
sim "github.com/cosmos/cosmos-sdk/x/simulation"
)
// Simulation operation weights constants
const (
OpWeightBuyTickets = "op_weight_buy_tickets"
DefaultGasValue = 200000
)
// WeightedOperations returns all the operations from the module with their respective weights
func WeightedOperations(
appParams simtypes.AppParams, cdc codec.JSONMarshaler,
k keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper,
) sim.WeightedOperations {
var weightBuyTickets int
appParams.GetOrGenerate(cdc, OpWeightBuyTickets, &weightBuyTickets, nil,
func(_ *rand.Rand) {
weightBuyTickets = params.DefaultWeightMsgBuyTickets
},
)
return sim.WeightedOperations{
sim.NewWeightedOperation(
weightBuyTickets,
SimulateMsgBuyTickets(k, ak, bk),
),
}
}
// SimulateMsgBuyTickets generates a random types.MsgBuyTickets and sends it to the chain.
func SimulateMsgBuyTickets(k keeper.Keeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper) simtypes.Operation {
return func(
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accounts []simtypes.Account, chainID string,
) (OperationMsg simtypes.OperationMsg, futureOps []simtypes.FutureOperation, err error) {
// Get random message data and build the message
acc, ticketsQuantity, ticketsCost, skip := randomBuyTicketsData(r, ctx, accounts, k, bk)
if skip {
return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, "skipping after generating data"), nil, nil
}
msg := types.NewMsgBuyTickets(ticketsQuantity, acc.Address.String())
// Send the message
err = sendMsgBuyTickets(r, app, ak, bk, msg, ticketsCost, ctx, chainID, []cryptotypes.PrivKey{acc.PrivKey})
if err != nil {
return simtypes.NoOpMsg(types.RouterKey, types.ModuleName, ""), nil, err
}
return simtypes.NewOperationMsg(msg, true, ""), nil, nil
}
}
// randomBuyTicketsData generates random parameters that can be used to create a types.MsgBuyTickets.
// It returns a random amount of tickets to buy, as well as the account that should buy them and
// the overall cost of the operation
func randomBuyTicketsData(
r *rand.Rand, ctx sdk.Context, accounts []simtypes.Account, k keeper.Keeper, bk bankkeeper.Keeper,
) (account simtypes.Account, ticketsAmt uint32, ticketsCost sdk.Coin, skip bool) {
// Get a random account
account, _ = simtypes.RandomAcc(r, accounts)
// Get a random number of tickets (min 1, max 10 tickets)
ticketsAmt = uint32(r.Int31n(10)) + 1
// Compute the ticket cost based on the params
ticketParams := k.GetTicketParams(ctx)
ticketsCost = sdk.NewCoin(ticketParams.Price.Denom, ticketParams.Price.Amount.MulRaw(int64(ticketsAmt)))
// Make sure the account has enough balance to pay for the tickets
balance := bk.SpendableCoins(ctx, account.Address)
if balance.IsZero() || sdk.NewCoins(ticketsCost).IsAnyGT(balance) {
return simtypes.Account{}, 0, sdk.Coin{}, true
}
return account, ticketsAmt, ticketsCost, false
}
// sendMsgBuyTickets sends a transaction with a types.MsgBuyTickets from a provided random profile.
func sendMsgBuyTickets(
r *rand.Rand, app *baseapp.BaseApp, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper,
msg *types.MsgBuyTickets, ticketsCost sdk.Coin, ctx sdk.Context, chainID string, privkeys []cryptotypes.PrivKey,
) error {
addr, _ := sdk.AccAddressFromBech32(msg.Buyer)
account := ak.GetAccount(ctx, addr)
// Compute the amount of fees that the account can spend based on the amount of money it will spend on tickets
coins := bk.SpendableCoins(ctx, account.GetAddress())
fees, err := simtypes.RandomFees(r, ctx, coins.Sub(sdk.NewCoins(ticketsCost)))
if err != nil {
return err
}
txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
txGen,
[]sdk.Msg{msg},
fees,
DefaultGasValue,
chainID,
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
privkeys...,
)
if err != nil {
return err
}
_, _, err = app.Deliver(txGen.TxEncoder(), tx)
if err != nil {
return err
}
return nil
}