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

feat(x/ecocredit): add basket simulations #769

Merged
merged 31 commits into from
Feb 23, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
3c4f955
wip: add simulations
aleem1314 Feb 14, 2022
449f5d0
feat: implement simulate msg-create-basket
aleem1314 Feb 14, 2022
b08d3cf
Merge branch 'release/v2.2.x' into aleem/basket-sims
aleem1314 Feb 15, 2022
83a23d2
feat: add put into basket sim
aleem1314 Feb 15, 2022
8abdf8b
wip: sims
aleem1314 Feb 15, 2022
a5bdfc3
wip: try fix sims
aleem1314 Feb 15, 2022
b7fa656
feat: add msg-take
aleem1314 Feb 15, 2022
1719045
chore: cleanup
aleem1314 Feb 15, 2022
d17301c
chore: inc basket sims gas
aleem1314 Feb 15, 2022
1b08beb
Merge branch 'release/v2.2.x' into aleem/basket-sims
aleem1314 Feb 16, 2022
c4ca68d
add logs
aleem1314 Feb 16, 2022
a15a783
fix error
aleem1314 Feb 16, 2022
b7f0d56
add basket fee check
aleem1314 Feb 16, 2022
ec8c8f9
try fix sims
aleem1314 Feb 17, 2022
adf93eb
Merge branch 'release/v3.0.x' into aleem/basket-sims
aaronc Feb 17, 2022
1996c2f
convert basket decimal to integer using string
aaronc Feb 17, 2022
d1c0eca
Merge branch 'release/v3.0.x' into aleem/basket-sims
aleem1314 Feb 18, 2022
eeb3525
cleanup
aleem1314 Feb 18, 2022
876e156
update app/app.go
aleem1314 Feb 18, 2022
74cbc4d
fix random amt issue
aleem1314 Feb 18, 2022
7d10eb4
fix sim error
aleem1314 Feb 18, 2022
116082e
Merge branch 'release/v3.0.x' into aleem/basket-sims
aleem1314 Feb 18, 2022
ec18dc2
chore: create helpers
aleem1314 Feb 18, 2022
ac7826f
Merge branch 'release/v3.0.x' into aleem/basket-sims
aleem1314 Feb 18, 2022
246ac8d
add date criteria
aleem1314 Feb 18, 2022
fdfa386
Merge branch 'release/v3.0.x' into aleem/basket-sims
robert-zaremba Feb 18, 2022
361a49a
Merge branch 'release/v3.0.x' into aleem/basket-sims
aleem1314 Feb 20, 2022
0e9c364
fix supply invariant
ryanchristo Feb 22, 2022
a5c9594
chore: review changes
aleem1314 Feb 23, 2022
df30c09
Merge branch 'release/v3.0.x' into aleem/basket-sims
aleem1314 Feb 23, 2022
c23a926
Merge branch 'release/v3.0.x' into aleem/basket-sims
robert-zaremba Feb 23, 2022
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
Prev Previous commit
Next Next commit
feat: add put into basket sim
  • Loading branch information
aleem1314 committed Feb 15, 2022
commit 83a23d2e9ef4d983ecff63bd60f640ceda23579a
18 changes: 10 additions & 8 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ import (

"github.com/regen-network/regen-ledger/types/module/server"
"github.com/regen-network/regen-ledger/x/ecocredit"
baskettypes "github.com/regen-network/regen-ledger/x/ecocredit/basket"
ecocreditmodule "github.com/regen-network/regen-ledger/x/ecocredit/module"

// unnamed import of statik for swagger UI support
Expand Down Expand Up @@ -139,14 +140,15 @@ var (

// module account permissions
maccPerms = map[string][]string{
authtypes.FeeCollectorName: nil,
distrtypes.ModuleName: nil,
minttypes.ModuleName: {authtypes.Minter},
stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking},
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
govtypes.ModuleName: {authtypes.Burner},
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
ecocredit.ModuleName: {authtypes.Burner},
authtypes.FeeCollectorName: nil,
distrtypes.ModuleName: nil,
minttypes.ModuleName: {authtypes.Minter},
stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking},
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
govtypes.ModuleName: {authtypes.Burner},
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
ecocredit.ModuleName: {authtypes.Burner},
baskettypes.BasketSubModuleName: {authtypes.Minter, authtypes.Burner},
}
)

Expand Down
2 changes: 1 addition & 1 deletion x/ecocredit/server/basket/put.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func (k Keeper) canBasketAcceptCredit(ctx context.Context, basket *basketv1.Bask
if err != nil {
return err
}
gotCreditType := res2.Info.CreditType.Name
gotCreditType := res2.Info.CreditType.Abbreviation
if requiredCreditType != gotCreditType {
return errInvalidReq.Wrapf("cannot use credit of type %s in a basket that requires credit type %s", gotCreditType, requiredCreditType)
}
Expand Down
204 changes: 192 additions & 12 deletions x/ecocredit/simulation/basket/operations.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
package basketsims

import (
"fmt"
"math/rand"
"strings"
"time"

gogotypes "github.com/gogo/protobuf/types"

"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/simapp/helpers"
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
sdk "github.com/cosmos/cosmos-sdk/types"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/simulation"

regentypes "github.com/regen-network/regen-ledger/types"
"github.com/regen-network/regen-ledger/types/math"
"github.com/regen-network/regen-ledger/x/ecocredit"
"github.com/regen-network/regen-ledger/x/ecocredit/basket"
)
Expand Down Expand Up @@ -122,23 +126,21 @@ func SimulateMsgCreate(ak ecocredit.AccountKeeper, bk ecocredit.BankKeeper,
return simtypes.NoOpMsg(ecocredit.ModuleName, TypeMsgCreate, "credit type not found"), nil, nil
}

var exponent uint32
if creditType.Precision <= 1 {
exponent = creditType.Precision
} else {
exponent = uint32(simtypes.RandIntBetween(r, 1, int(creditType.Precision)))
}
precision := int(creditType.Precision)
exponent := uint32(simtypes.RandIntBetween(r, precision, precision+5))

dateCriteria := randomDateCriteria(r)
dateCriteria = nil
aleem1314 marked this conversation as resolved.
Show resolved Hide resolved
msg := &basket.MsgCreate{
Name: simtypes.RandStringOfLength(r, simtypes.RandIntBetween(r, 2, 10)),
DisplayName: simtypes.RandStringOfLength(r, simtypes.RandIntBetween(r, 2, 10)),
Fee: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, int64(simtypes.RandIntBetween(r, 0, 5)))),
Name: simtypes.RandStringOfLength(r, simtypes.RandIntBetween(r, 3, 32)),
DisplayName: simtypes.RandStringOfLength(r, simtypes.RandIntBetween(r, 3, 32)),
Fee: params.BasketCreationFee,
DisableAutoRetire: r.Float32() < 0.5,
Curator: curator.Address.String(),
Exponent: exponent,
AllowedClasses: classIds,
CreditTypeName: creditType.Name,
DateCriteria: randomDateCriteria(r),
CreditTypeName: creditType.Abbreviation,
DateCriteria: dateCriteria,
}

txCtx := simulation.OperationInput{
Expand Down Expand Up @@ -190,8 +192,135 @@ func SimulateMsgPut(ak ecocredit.AccountKeeper, bk ecocredit.BankKeeper,
return func(
r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accs []simtypes.Account, chainID string,
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
owner, _ := simtypes.RandomAcc(r, accs)

ctx := regentypes.Context{Context: sdkCtx}
res, err := bsktQryClient.Baskets(ctx, &basket.QueryBasketsRequest{})
if err != nil {
return simtypes.NoOpMsg(ecocredit.ModuleName, TypeMsgPut, err.Error()), nil, err
}

baskets := res.Baskets
if len(baskets) == 0 {
return simtypes.NoOpMsg(ecocredit.ModuleName, TypeMsgPut, "no baskets"), nil, nil
}

return simtypes.NoOpMsg(ecocredit.ModuleName, TypeMsgPut, ""), nil, nil
classesRes, err := qryClient.Classes(ctx, &ecocredit.QueryClassesRequest{})
if err != nil {
return simtypes.NoOpMsg(ecocredit.ModuleName, TypeMsgPut, err.Error()), nil, err
}

classes := classesRes.Classes
if len(classes) == 0 {
return simtypes.NoOpMsg(ecocredit.ModuleName, TypeMsgPut, "no classes"), nil, nil
}

rBasket := baskets[r.Intn(len(baskets))]
var classInfoList []ecocredit.ClassInfo
max := 0

r.Shuffle(len(classes), func(i, j int) { classes[i], classes[j] = classes[j], classes[i] })
for _, class := range classes {
if class.CreditType.Abbreviation == rBasket.CreditTypeName {
classInfoList = append(classInfoList, *class)
if max == 2 {
break
}
max++
}
}

if len(classInfoList) == 0 {
return simtypes.NoOpMsg(ecocredit.ModuleName, TypeMsgPut, "different credit type"), nil, nil
}

var credits []*basket.BasketCredit
for _, info := range classInfoList {
batchesRes, err := qryClient.Batches(ctx, &ecocredit.QueryBatchesRequest{ClassId: info.ClassId})
if err != nil {
return simtypes.NoOpMsg(ecocredit.ModuleName, TypeMsgPut, err.Error()), nil, err
}

batches := batchesRes.Batches
if len(batches) != 0 {
for _, item := range batches {
balanceRes, err := qryClient.Balance(ctx, &ecocredit.QueryBalanceRequest{Account: owner.Address.String(), BatchDenom: item.BatchDenom})
if err != nil {
return simtypes.NoOpMsg(ecocredit.ModuleName, TypeMsgPut, err.Error()), nil, err
}

tradableAmount := balanceRes.TradableAmount
if tradableAmount != "0" {
d, err := math.NewPositiveDecFromString(tradableAmount)
if err != nil {
return simtypes.NoOpMsg(ecocredit.ModuleName, TypeMsgPut, err.Error()), nil, err
}

dInt, err := d.Int64()
if err != nil {
return simtypes.NoOpMsg(ecocredit.ModuleName, TypeMsgPut, err.Error()), nil, err
}

if dInt == 1 {
credits = append(credits, &basket.BasketCredit{
BatchDenom: item.BatchDenom,
Amount: "1",
})
} else {
amt := simtypes.RandIntBetween(r, 1, int(dInt))
credits = append(credits, &basket.BasketCredit{
BatchDenom: item.BatchDenom,
Amount: fmt.Sprintf("%d", amt),
})

}
}
}
}

}

if len(credits) == 0 {
return simtypes.NoOpMsg(ecocredit.ModuleName, TypeMsgPut, "no basket credits"), nil, nil
}

msg := &basket.MsgPut{
Owner: owner.Address.String(),
BasketDenom: rBasket.BasketDenom,
Credits: credits,
}
spendable := bk.SpendableCoins(sdkCtx, owner.Address)
fees, err := simtypes.RandomFees(r, sdkCtx, spendable)
if err != nil {
return simtypes.NoOpMsg(ecocredit.ModuleName, TypeMsgPut, "fee error"), nil, err
}

account := ak.GetAccount(sdkCtx, owner.Address)
txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
txGen,
[]sdk.Msg{msg},
fees,
helpers.DefaultGenTxGas,
chainID,
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
owner.PrivKey,
)
if err != nil {
return simtypes.NoOpMsg(ecocredit.ModuleName, TypeMsgPut, "unable to generate mock tx"), nil, err
}

_, _, err = app.Deliver(txGen.TxEncoder(), tx)
if err != nil {
if strings.Contains(err.Error(), "is not allowed in this basket") {
return simtypes.NoOpMsg(ecocredit.ModuleName, msg.Type(), "class is not allowed"), nil, nil
}

return simtypes.NoOpMsg(ecocredit.ModuleName, msg.Type(), "unable to deliver tx"), nil, err
}

return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil
}
}

Expand All @@ -215,10 +344,13 @@ func randomClasses(r *rand.Rand, ctx regentypes.Context, qryClient ecocredit.Que
classes := res.GetClasses()
if len(classes) == 0 {
return []string{}, nil
} else if len(classes) == 1 {
return []string{classes[0].ClassId}, nil
}

max := simtypes.RandIntBetween(r, 1, len(classes))

r.Shuffle(len(classes), func(i, j int) { classes[i], classes[j] = classes[j], classes[i] })
classIds := make([]string, max)
for i := 0; i < max; i++ {
classIds[i] = classes[i].ClassId
Expand All @@ -240,3 +372,51 @@ func randomCreditType(r *rand.Rand, ctx regentypes.Context, qryClient ecocredit.

return creditTypes[r.Intn(len(creditTypes))], nil
}

// GenAndDeliverTxWithRandFees generates a transaction with a random fee and delivers it.
func GenAndDeliverTxWithRandFees(txCtx simulation.OperationInput) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
account := txCtx.AccountKeeper.GetAccount(txCtx.Context, txCtx.SimAccount.Address)
spendable := txCtx.Bankkeeper.SpendableCoins(txCtx.Context, account.GetAddress())

var fees sdk.Coins
var err error

coins, hasNeg := spendable.SafeSub(txCtx.CoinsSpentInMsg)
if hasNeg {
return simtypes.NoOpMsg(txCtx.ModuleName, txCtx.MsgType, "message doesn't leave room for fees"), nil, err
}

fees, err = simtypes.RandomFees(txCtx.R, txCtx.Context, coins)
if err != nil {
return simtypes.NoOpMsg(txCtx.ModuleName, txCtx.MsgType, "unable to generate fees"), nil, err
}
return GenAndDeliverTx(txCtx, fees)
}

// GenAndDeliverTx generates a transactions and delivers it.
func GenAndDeliverTx(txCtx simulation.OperationInput, fees sdk.Coins) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
account := txCtx.AccountKeeper.GetAccount(txCtx.Context, txCtx.SimAccount.Address)
tx, err := helpers.GenTx(
txCtx.TxGen,
[]sdk.Msg{txCtx.Msg},
fees,
helpers.DefaultGenTxGas,
txCtx.Context.ChainID(),
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
txCtx.SimAccount.PrivKey,
)

if err != nil {
return simtypes.NoOpMsg(txCtx.ModuleName, txCtx.MsgType, "unable to generate mock tx"), nil, err
}

_, r1, err := txCtx.App.Deliver(txCtx.TxGen.TxEncoder(), tx)
fmt.Println(r1)
if err != nil {
return simtypes.NoOpMsg(txCtx.ModuleName, txCtx.MsgType, "unable to deliver tx"), nil, err
}

return simtypes.NewOperationMsg(txCtx.Msg, true, "", txCtx.Cdc), nil, nil

}