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

simulation: Use a simulation.Account struct #2384

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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 PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ BREAKING CHANGES
* [types] [\#2119](https://github.com/cosmos/cosmos-sdk/issues/2119) Parsed error messages and ABCI log errors to make them more human readable.
* [simulation] Rename TestAndRunTx to Operation [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153)
* [simulation] Remove log and testing.TB from Operation and Invariants, in favor of using errors \#2282
* [simulation] Remove usage of keys and addrs in the types, in favor of simulation.Account \#2384
* [tools] Removed gocyclo [#2211](https://github.com/cosmos/cosmos-sdk/issues/2211)
* [baseapp] Remove `SetTxDecoder` in favor of requiring the decoder be set in baseapp initialization. [#1441](https://github.com/cosmos/cosmos-sdk/issues/1441)
* [baseapp] [\#1921](https://github.com/cosmos/cosmos-sdk/issues/1921) Add minimumFees field to BaseApp.
Expand Down
9 changes: 4 additions & 5 deletions cmd/gaia/app/sim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (

"github.com/stretchr/testify/require"

"github.com/tendermint/tendermint/crypto"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"

Expand Down Expand Up @@ -42,14 +41,14 @@ func init() {
flag.BoolVar(&commit, "SimulationCommit", false, "Have the simulation commit")
}

func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage {
func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
var genesisAccounts []GenesisAccount

// Randomly generate some genesis accounts
for _, acc := range accs {
coins := sdk.Coins{sdk.Coin{"steak", sdk.NewInt(100)}}
genesisAccounts = append(genesisAccounts, GenesisAccount{
Address: acc,
Address: acc.Address,
Coins: coins,
})
}
Expand All @@ -61,10 +60,10 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json
// XXX Try different numbers of initially bonded validators
numInitiallyBonded := int64(50)
for i := 0; i < int(numInitiallyBonded); i++ {
validator := stake.NewValidator(sdk.ValAddress(accs[i]), keys[i].PubKey(), stake.Description{})
validator := stake.NewValidator(sdk.ValAddress(accs[i].Address), accs[i].PubKey, stake.Description{})
validator.Tokens = sdk.NewDec(100)
validator.DelegatorShares = sdk.NewDec(100)
delegation := stake.Delegation{accs[i], sdk.ValAddress(accs[i]), sdk.NewDec(100), 0}
delegation := stake.Delegation{accs[i].Address, sdk.ValAddress(accs[i].Address), sdk.NewDec(100), 0}
validators = append(validators, validator)
delegations = append(delegations, delegation)
}
Expand Down
21 changes: 10 additions & 11 deletions x/bank/simulation/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,18 @@ import (
// SimulateSingleInputMsgSend tests and runs a single msg send, with one input and one output, where both
// accounts already exist.
func SimulateSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOps []simulation.FutureOperation, err error) {
fromKey := simulation.RandomKey(r, keys)
fromAddr := sdk.AccAddress(fromKey.PubKey().Address())
toKey := simulation.RandomKey(r, keys)
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 !fromKey.Equals(toKey) {
if !fromAcc.PubKey.Equals(toAcc.PubKey) {
break
}
toKey = simulation.RandomKey(r, keys)
toAcc = simulation.RandomAcc(r, accs)
}
toAddr := sdk.AccAddress(toKey.PubKey().Address())
initFromCoins := mapper.GetAccount(ctx, fromAddr).GetCoins()
toAddr := toAcc.Address
initFromCoins := mapper.GetAccount(ctx, fromAcc.Address).GetCoins()

if len(initFromCoins) == 0 {
return "skipping, no coins at all", nil, nil
Expand All @@ -43,18 +42,18 @@ func SimulateSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation
}

action = fmt.Sprintf("%s is sending %s %s to %s",
fromAddr.String(),
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(fromAddr, coins)},
Inputs: []bank.Input{bank.NewInput(fromAcc.Address, coins)},
Outputs: []bank.Output{bank.NewOutput(toAddr, coins)},
}
goErr = sendAndVerifyMsgSend(app, mapper, msg, ctx, []crypto.PrivKey{fromKey})
goErr = sendAndVerifyMsgSend(app, mapper, msg, ctx, []crypto.PrivKey{fromAcc.PrivKey})
if goErr != nil {
return "", nil, goErr
}
Expand Down
6 changes: 2 additions & 4 deletions x/bank/simulation/sim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"math/rand"
"testing"

"github.com/tendermint/tendermint/crypto"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/mock"
Expand All @@ -26,8 +24,8 @@ func TestBankWithRandomMessages(t *testing.T) {
panic(err)
}

appStateFn := func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage {
mock.RandomSetGenesis(r, mapp, accs, []string{"stake"})
appStateFn := func(r *rand.Rand, accs []simulation.Account) json.RawMessage {
simulation.RandomSetGenesis(r, mapp, accs, []string{"stake"})
return json.RawMessage("{}")
}

Expand Down
41 changes: 18 additions & 23 deletions x/gov/simulation/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (
"math/rand"
"time"

"github.com/tendermint/tendermint/crypto"

"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov"
Expand Down Expand Up @@ -45,9 +43,9 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe
})
statePercentageArray := []float64{1, .9, .75, .4, .15, 0}
curNumVotesState := 1
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, 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) {
// 1) submit proposal now
sender := simulation.RandomKey(r, keys)
sender := simulation.RandomAcc(r, accs)
msg, err := simulationCreateMsgSubmitProposal(r, sender)
if err != nil {
return "", nil, err
Expand All @@ -61,16 +59,16 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe
// 2) Schedule operations for votes
// 2.1) first pick a number of people to vote.
curNumVotesState = numVotesTransitionMatrix.NextState(r, curNumVotesState)
numVotes := int(math.Ceil(float64(len(keys)) * statePercentageArray[curNumVotesState]))
numVotes := int(math.Ceil(float64(len(accs)) * statePercentageArray[curNumVotesState]))
// 2.2) select who votes and when
whoVotes := r.Perm(len(keys))
whoVotes := r.Perm(len(accs))
// didntVote := whoVotes[numVotes:]
whoVotes = whoVotes[:numVotes]
votingPeriod := k.GetVotingProcedure(ctx).VotingPeriod
fops := make([]simulation.FutureOperation, numVotes+1)
for i := 0; i < numVotes; i++ {
whenVote := ctx.BlockHeader().Time.Add(time.Duration(r.Int63n(int64(votingPeriod.Seconds()))) * time.Second)
fops[i] = simulation.FutureOperation{BlockTime: whenVote, Op: operationSimulateMsgVote(k, sk, keys[whoVotes[i]], proposalID)}
fops[i] = simulation.FutureOperation{BlockTime: whenVote, Op: operationSimulateMsgVote(k, sk, accs[whoVotes[i]], proposalID)}
}
// 3) Make an operation to ensure slashes were done correctly. (Really should be a future invariant)
// TODO: Find a way to check if a validator was slashed other than just checking their balance a block
Expand All @@ -84,8 +82,8 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe
// Note: Currently doesn't ensure that the proposal txt is in JSON form
func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operation {
handler := gov.NewHandler(k)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOps []simulation.FutureOperation, err error) {
sender := simulation.RandomKey(r, keys)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOps []simulation.FutureOperation, err error) {
sender := simulation.RandomAcc(r, accs)
msg, err := simulationCreateMsgSubmitProposal(r, sender)
if err != nil {
return "", nil, err
Expand All @@ -111,14 +109,13 @@ func simulateHandleMsgSubmitProposal(msg gov.MsgSubmitProposal, sk stake.Keeper,
return
}

func simulationCreateMsgSubmitProposal(r *rand.Rand, sender crypto.PrivKey) (msg gov.MsgSubmitProposal, err error) {
addr := sdk.AccAddress(sender.PubKey().Address())
func simulationCreateMsgSubmitProposal(r *rand.Rand, sender simulation.Account) (msg gov.MsgSubmitProposal, err error) {
deposit := randomDeposit(r)
msg = gov.NewMsgSubmitProposal(
simulation.RandStringOfLength(r, 5),
simulation.RandStringOfLength(r, 5),
gov.ProposalTypeText,
addr,
sender.Address,
deposit,
)
if msg.ValidateBasic() != nil {
Expand All @@ -129,15 +126,14 @@ func simulationCreateMsgSubmitProposal(r *rand.Rand, sender crypto.PrivKey) (msg

// SimulateMsgDeposit
func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
key := simulation.RandomKey(r, keys)
addr := sdk.AccAddress(key.PubKey().Address())
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
acc := simulation.RandomAcc(r, accs)
proposalID, ok := randomProposalID(r, k, ctx)
if !ok {
return "no-operation", nil, nil
}
deposit := randomDeposit(r)
msg := gov.NewMsgDeposit(addr, proposalID, deposit)
msg := gov.NewMsgDeposit(acc.Address, proposalID, deposit)
if msg.ValidateBasic() != nil {
return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
}
Expand All @@ -159,14 +155,14 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation {
// SimulateMsgVote
// nolint: unparam
func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation {
return operationSimulateMsgVote(k, sk, nil, -1)
return operationSimulateMsgVote(k, sk, simulation.Account{}, -1)
}

// nolint: unparam
func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey, proposalID int64) simulation.Operation {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
if key == nil {
key = simulation.RandomKey(r, keys)
func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, acc simulation.Account, proposalID int64) simulation.Operation {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
if acc.Equals(simulation.Account{}) {
acc = simulation.RandomAcc(r, accs)
}

var ok bool
Expand All @@ -177,10 +173,9 @@ func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey,
return "no-operation", nil, nil
}
}
addr := sdk.AccAddress(key.PubKey().Address())
option := randomVotingOption(r)

msg := gov.NewMsgVote(addr, proposalID, option)
msg := gov.NewMsgVote(acc.Address, proposalID, option)
if msg.ValidateBasic() != nil {
return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
}
Expand Down
7 changes: 3 additions & 4 deletions x/gov/simulation/sim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"testing"

abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/bank"
Expand Down Expand Up @@ -43,12 +42,12 @@ func TestGovWithRandomMessages(t *testing.T) {
panic(err)
}

appStateFn := func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage {
mock.RandomSetGenesis(r, mapp, accs, []string{"stake"})
appStateFn := func(r *rand.Rand, accs []simulation.Account) json.RawMessage {
simulation.RandomSetGenesis(r, mapp, accs, []string{"stake"})
return json.RawMessage("{}")
}

setup := func(r *rand.Rand, privKeys []crypto.PrivKey) {
setup := func(r *rand.Rand, accs []simulation.Account) {
ctx := mapp.NewContext(false, abci.Header{})
stake.InitGenesis(ctx, stakeKeeper, stake.DefaultGenesisState())
gov.InitGenesis(ctx, govKeeper, gov.DefaultGenesisState())
Expand Down
38 changes: 18 additions & 20 deletions x/mock/simulation/random_simulate_blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,32 @@ import (
"time"

abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto"
tmtypes "github.com/tendermint/tendermint/types"

"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/mock"
)

// Simulate tests application by sending random messages.
func Simulate(t *testing.T, app *baseapp.BaseApp,
appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage,
appStateFn func(r *rand.Rand, accs []Account) json.RawMessage,
ops []WeightedOperation, setups []RandSetup,
invariants []Invariant, numBlocks int, blockSize int, commit bool) error {

time := time.Now().UnixNano()
return SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize, commit)
}

func initChain(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress, setups []RandSetup, app *baseapp.BaseApp,
appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage) (validators map[string]mockValidator) {
res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, keys, accs)})
func initChain(r *rand.Rand, accounts []Account, setups []RandSetup, app *baseapp.BaseApp,
appStateFn func(r *rand.Rand, accounts []Account) json.RawMessage) (validators map[string]mockValidator) {
res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, accounts)})
validators = make(map[string]mockValidator)
for _, validator := range res.Validators {
validators[string(validator.Address)] = mockValidator{validator, GetMemberOfInitialState(r, initialLivenessWeightings)}
}

for i := 0; i < len(setups); i++ {
setups[i](r, keys)
setups[i](r, accounts)
}

return
Expand All @@ -56,7 +54,7 @@ func randTimestamp(r *rand.Rand) time.Time {
// SimulateFromSeed tests an application by running the provided
// operations, testing the provided invariants, but using the provided seed.
func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage,
appStateFn func(r *rand.Rand, accs []Account) json.RawMessage,
seed int64, ops []WeightedOperation, setups []RandSetup, invariants []Invariant,
numBlocks int, blockSize int, commit bool) (simError error) {

Expand All @@ -69,15 +67,15 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
fmt.Printf("Starting the simulation from time %v, unixtime %v\n", timestamp.UTC().Format(time.UnixDate), timestamp.Unix())
timeDiff := maxTimePerBlock - minTimePerBlock

keys, accs := mock.GeneratePrivKeyAddressPairsFromRand(r, numKeys)
accs := RandomAccounts(r, numKeys)

// Setup event stats
events := make(map[string]uint)
event := func(what string) {
events[what]++
}

validators := initChain(r, keys, accs, setups, app, appStateFn)
validators := initChain(r, accs, setups, app, appStateFn)

header := abci.Header{Height: 0, Time: timestamp}
opCount := 0
Expand Down Expand Up @@ -139,10 +137,10 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
thisBlockSize := getBlockSize(r, blockSize)

// Run queued operations. Ignores blocksize if blocksize is too small
numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), tb, r, app, ctx, keys, logWriter, displayLogs, event)
numQueuedTimeOpsRan := runQueuedTimeOperations(timeOperationQueue, header.Time, tb, r, app, ctx, keys, logWriter, displayLogs, event)
numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), tb, r, app, ctx, accs, logWriter, displayLogs, event)
numQueuedTimeOpsRan := runQueuedTimeOperations(timeOperationQueue, header.Time, tb, r, app, ctx, accs, logWriter, displayLogs, event)
thisBlockSize = thisBlockSize - numQueuedOpsRan - numQueuedTimeOpsRan
operations := blockSimulator(thisBlockSize, r, app, ctx, keys, header, logWriter)
operations := blockSimulator(thisBlockSize, r, app, ctx, accs, header, logWriter)
opCount += operations + numQueuedOpsRan + numQueuedTimeOpsRan

res := app.EndBlock(abci.RequestEndBlock{})
Expand Down Expand Up @@ -176,7 +174,7 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
// Returns a function to simulate blocks. Written like this to avoid constant parameters being passed everytime, to minimize
// memory overhead
func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event func(string), invariants []Invariant, ops []WeightedOperation, operationQueue map[int][]Operation, timeOperationQueue []FutureOperation, totalNumBlocks int, displayLogs func()) func(
blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, header abci.Header, logWriter func(string)) (opCount int) {
blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accounts []Account, header abci.Header, logWriter func(string)) (opCount int) {
totalOpWeight := 0
for i := 0; i < len(ops); i++ {
totalOpWeight += ops[i].Weight
Expand All @@ -193,9 +191,9 @@ func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event f
return ops[0].Op
}
return func(blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
keys []crypto.PrivKey, header abci.Header, logWriter func(string)) (opCount int) {
accounts []Account, header abci.Header, logWriter func(string)) (opCount int) {
for j := 0; j < blocksize; j++ {
logUpdate, futureOps, err := selectOp(r)(r, app, ctx, keys, event)
logUpdate, futureOps, err := selectOp(r)(r, app, ctx, accounts, event)
if err != nil {
displayLogs()
tb.Fatalf("error on operation %d within block %d, %v", header.Height, opCount, err)
Expand Down Expand Up @@ -264,14 +262,14 @@ func queueOperations(queuedOperations map[int][]Operation, queuedTimeOperations

// nolint: errcheck
func runQueuedOperations(queueOperations map[int][]Operation, height int, tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
privKeys []crypto.PrivKey, logWriter func(string), displayLogs func(), event func(string)) (numOpsRan int) {
accounts []Account, logWriter func(string), displayLogs func(), event func(string)) (numOpsRan int) {
if queuedOps, ok := queueOperations[height]; ok {
numOps := len(queuedOps)
for i := 0; i < numOps; i++ {
// For now, queued operations cannot queue more operations.
// If a need arises for us to support queued messages to queue more messages, this can
// be changed.
logUpdate, _, err := queuedOps[i](r, app, ctx, privKeys, event)
logUpdate, _, err := queuedOps[i](r, app, ctx, accounts, event)
logWriter(logUpdate)
if err != nil {
displayLogs()
Expand All @@ -285,14 +283,14 @@ func runQueuedOperations(queueOperations map[int][]Operation, height int, tb tes
}

func runQueuedTimeOperations(queueOperations []FutureOperation, currentTime time.Time, tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
privKeys []crypto.PrivKey, logWriter func(string), displayLogs func(), event func(string)) (numOpsRan int) {
accounts []Account, logWriter func(string), displayLogs func(), event func(string)) (numOpsRan int) {

numOpsRan = 0
for len(queueOperations) > 0 && currentTime.After(queueOperations[0].BlockTime) {
// For now, queued operations cannot queue more operations.
// If a need arises for us to support queued messages to queue more messages, this can
// be changed.
logUpdate, _, err := queueOperations[0].Op(r, app, ctx, privKeys, event)
logUpdate, _, err := queueOperations[0].Op(r, app, ctx, accounts, event)
logWriter(logUpdate)
if err != nil {
displayLogs()
Expand Down
Loading