diff --git a/testutil/sample/observer.go b/testutil/sample/observer.go index d80314851f..c6ade5b58f 100644 --- a/testutil/sample/observer.go +++ b/testutil/sample/observer.go @@ -123,15 +123,15 @@ func ChainParamsFromRand(r *rand.Rand, chainID int64) *types.ChainParams { ChainId: chainID, ConfirmationCount: r.Uint64(), - GasPriceTicker: Uint64InRange(1, 300), - InboundTicker: Uint64InRange(1, 300), - OutboundTicker: Uint64InRange(1, 300), - WatchUtxoTicker: Uint64InRange(1, 300), - ZetaTokenContractAddress: EthAddress().String(), - ConnectorContractAddress: EthAddress().String(), - Erc20CustodyContractAddress: EthAddress().String(), - OutboundScheduleInterval: Int64InRange(1, 100), - OutboundScheduleLookahead: Int64InRange(1, 500), + GasPriceTicker: Uint64InRangeFromRand(r, 1, 300), + InboundTicker: Uint64InRangeFromRand(r, 1, 300), + OutboundTicker: Uint64InRangeFromRand(r, 1, 300), + WatchUtxoTicker: Uint64InRangeFromRand(r, 1, 300), + ZetaTokenContractAddress: EthAddressFromRand(r).String(), + ConnectorContractAddress: EthAddressFromRand(r).String(), + Erc20CustodyContractAddress: EthAddressFromRand(r).String(), + OutboundScheduleInterval: Int64InRangeFromRand(r, 1, 100), + OutboundScheduleLookahead: Int64InRangeFromRand(r, 1, 500), BallotThreshold: fiftyPercent, MinObserverDelegation: sdk.NewDec(r.Int63()), IsSupported: true, diff --git a/testutil/sample/sample.go b/testutil/sample/sample.go index 3f0390ddad..c9f416a088 100644 --- a/testutil/sample/sample.go +++ b/testutil/sample/sample.go @@ -93,12 +93,22 @@ func Uint64InRange(low, high uint64) uint64 { return r.Uint64()%(high-low) + low } +// Uint64InRange returns a sample uint64 in the given ranges +func Uint64InRangeFromRand(r *rand.Rand, low, high uint64) uint64 { + return r.Uint64()%(high-low) + low +} + // Int64InRange returns a sample int64 in the given ranges func Int64InRange(low, high int64) int64 { r := newRandFromSeed(low) return r.Int63()%(high-low) + low } +// Int64InRangeFromRand returns a sample int64 in the given ranges +func Int64InRangeFromRand(r *rand.Rand, low, high int64) int64 { + return r.Int63()%(high-low) + low +} + func UintInRange(low, high uint64) sdkmath.Uint { u := Uint64InRange(low, high) return sdkmath.NewUint(u) diff --git a/x/observer/simulation/operation_remove_chain_params.go b/x/observer/simulation/operation_remove_chain_params.go new file mode 100644 index 0000000000..875d693e58 --- /dev/null +++ b/x/observer/simulation/operation_remove_chain_params.go @@ -0,0 +1,73 @@ +package simulation + +import ( + "math/rand" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + "github.com/zeta-chain/node/x/observer/keeper" + "github.com/zeta-chain/node/x/observer/types" +) + +// SimulateMsgRemoveChainParams generates a MsgRemoveChainParams and delivers it. +func SimulateMsgRemoveChainParams(k keeper.Keeper) simtypes.Operation { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accounts []simtypes.Account, _ string, + ) (OperationMsg simtypes.OperationMsg, futureOps []simtypes.FutureOperation, err error) { + policyAccount, err := GetPolicyAccount(ctx, k.GetAuthorityKeeper(), accounts) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgRemoveChainParams, err.Error()), nil, nil + } + + authAccount := k.GetAuthKeeper().GetAccount(ctx, policyAccount.Address) + spendable := k.GetBankKeeper().SpendableCoins(ctx, authAccount.GetAddress()) + + supportedChains := k.GetSupportedChains(ctx) + if len(supportedChains) == 0 { + return simtypes.NoOpMsg( + types.ModuleName, + types.TypeMsgRemoveChainParams, + "no supported chains found", + ), nil, nil + } + + randomChainId := int64(0) + // remove zeta chain from the supported chains + for { + c := supportedChains[r.Intn(len(supportedChains))] + if !c.IsZetaChain() { + randomChainId = c.ChainId + break + } + } + + msg := types.MsgRemoveChainParams{ + Creator: policyAccount.Address.String(), + ChainId: randomChainId, + } + + err = msg.ValidateBasic() + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, msg.Type(), err.Error()), nil, err + } + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: nil, + Msg: &msg, + MsgType: msg.Type(), + Context: ctx, + SimAccount: policyAccount, + AccountKeeper: k.GetAuthKeeper(), + Bankkeeper: k.GetBankKeeper(), + ModuleName: types.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} diff --git a/x/observer/simulation/operation_reset_chain_nonces.go b/x/observer/simulation/operation_reset_chain_nonces.go new file mode 100644 index 0000000000..372107cb39 --- /dev/null +++ b/x/observer/simulation/operation_reset_chain_nonces.go @@ -0,0 +1,74 @@ +package simulation + +import ( + "fmt" + "math/rand" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + "github.com/zeta-chain/node/x/observer/keeper" + "github.com/zeta-chain/node/x/observer/types" +) + +// SimulateMsgResetChainNonces generates a MsgResetChainNonces and delivers it. +func SimulateMsgResetChainNonces(k keeper.Keeper) simtypes.Operation { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accounts []simtypes.Account, _ string, + ) (OperationMsg simtypes.OperationMsg, futureOps []simtypes.FutureOperation, err error) { + policyAccount, err := GetPolicyAccount(ctx, k.GetAuthorityKeeper(), accounts) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgResetChainNonces, err.Error()), nil, nil + } + + authAccount := k.GetAuthKeeper().GetAccount(ctx, policyAccount.Address) + spendable := k.GetBankKeeper().SpendableCoins(ctx, authAccount.GetAddress()) + + randomChain, err := GetExternalChain(ctx, k, r, 100) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgResetChainNonces, err.Error()), nil, fmt.Errorf("error getting external chain") + } + + tss, found := k.GetTSS(ctx) + if !found { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgResetChainNonces, "TSS not found"), nil, fmt.Errorf("TSS not found") + } + pendingNonces, found := k.GetPendingNonces(ctx, tss.TssPubkey, randomChain.ChainId) + if !found { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgResetChainNonces, "Pending nonces not found"), nil, + fmt.Errorf("pending nonces not found for chain %d %s", randomChain.ChainId, randomChain.ChainName) + } + + nonceIncrement := int64(r.Intn(100-1)) + 1 + + msg := types.MsgResetChainNonces{ + Creator: policyAccount.Address.String(), + ChainId: randomChain.ChainId, + ChainNonceHigh: pendingNonces.NonceHigh + nonceIncrement, + ChainNonceLow: pendingNonces.NonceLow + nonceIncrement, + } + + err = msg.ValidateBasic() + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, msg.Type(), err.Error()), nil, err + } + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: nil, + Msg: &msg, + MsgType: msg.Type(), + Context: ctx, + SimAccount: policyAccount, + AccountKeeper: k.GetAuthKeeper(), + Bankkeeper: k.GetBankKeeper(), + ModuleName: types.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} diff --git a/x/observer/simulation/operation_update_chain_params.go b/x/observer/simulation/operation_update_chain_params.go index c921a6b4f3..33cf899562 100644 --- a/x/observer/simulation/operation_update_chain_params.go +++ b/x/observer/simulation/operation_update_chain_params.go @@ -25,28 +25,12 @@ func SimulateMsgUpdateChainParams(k keeper.Keeper) simtypes.Operation { authAccount := k.GetAuthKeeper().GetAccount(ctx, policyAccount.Address) spendable := k.GetBankKeeper().SpendableCoins(ctx, authAccount.GetAddress()) - supportedChains := k.GetSupportedChains(ctx) - if len(supportedChains) == 0 { - return simtypes.NoOpMsg( - types.ModuleName, - types.TypeMsgUpdateChainParams, - "no supported chains found", - ), nil, nil - } - - randomChainId := int64(0) - // remove zeta chain from the supported chains - for { - c := supportedChains[r.Intn(len(supportedChains))] - if !c.IsZetaChain() { - randomChainId = c.ChainId - break - } + randomChain, err := GetExternalChain(ctx, k, r, 100) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgUpdateChainParams, err.Error()), nil, nil } - // pick a random chain from the supported chains - - cp := sample.ChainParamsFromRand(r, randomChainId) + cp := sample.ChainParamsFromRand(r, randomChain.ChainId) msg := types.MsgUpdateChainParams{ Creator: policyAccount.Address.String(), diff --git a/x/observer/simulation/operation_update_keygen.go b/x/observer/simulation/operation_update_keygen.go index 71a2f96b13..8c6ce84d89 100644 --- a/x/observer/simulation/operation_update_keygen.go +++ b/x/observer/simulation/operation_update_keygen.go @@ -31,9 +31,9 @@ func SimulateMsgUpdateKeygen(k keeper.Keeper) simtypes.Operation { k.SetKeygen(ctx, kg) } - blockHeighMin := ctx.BlockHeight() + 11 - blockHeighMax := ctx.BlockHeight() + 1000 - keygenBlockHeight := int64(r.Intn(int(blockHeighMax-blockHeighMin))) + blockHeighMin + blockHeightMin := ctx.BlockHeight() + 11 + blockHeightMax := ctx.BlockHeight() + 1000 + keygenBlockHeight := int64(r.Intn(int(blockHeightMax-blockHeightMin))) + blockHeightMin msg := types.MsgUpdateKeygen{ Creator: policyAccount.Address.String(), diff --git a/x/observer/simulation/operations.go b/x/observer/simulation/operations.go index 4e1d08f3a9..d137de17c6 100644 --- a/x/observer/simulation/operations.go +++ b/x/observer/simulation/operations.go @@ -8,6 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/simulation" + "github.com/zeta-chain/node/pkg/chains" "github.com/zeta-chain/node/x/observer/types" "github.com/zeta-chain/node/x/observer/keeper" @@ -42,7 +43,7 @@ const ( DefaultWeightMsgTypeMsgUpdateObserver = 10 DefaultWeightMsgTypeMsgUpdateChainParams = 10 DefaultWeightMsgTypeMsgRemoveChainParams = 10 - DefaultWeightMsgTypeMsgResetChainNonces = 10 + DefaultWeightMsgTypeMsgResetChainNonces = 5 DefaultWeightMsgTypeMsgUpdateGasPriceIncreaseFlags = 10 DefaultWeightMsgTypeMsgAddObserver = 10 ) @@ -129,11 +130,21 @@ func WeightedOperations( weightMsgTypeMsgUpdateKeygen, SimulateMsgUpdateKeygen(k), ), - + // simulation.NewWeightedOperation( weightMsgTypeMsgUpdateChainParams, SimulateMsgUpdateChainParams(k), ), + // + //simulation.NewWeightedOperation( + // weightMsgTypeMsgRemoveChainParams, + // SimulateMsgRemoveChainParams(k), + //), + + simulation.NewWeightedOperation( + weightMsgTypeMsgResetChainNonces, + SimulateMsgResetChainNonces(k), + ), } } @@ -158,3 +169,18 @@ func GetPolicyAccount(ctx sdk.Context, k types.AuthorityKeeper, accounts []simty } return simAccount, nil } + +func GetExternalChain(ctx sdk.Context, k keeper.Keeper, r *rand.Rand, retryCount int) (chains.Chain, error) { + supportedChains := k.GetSupportedChains(ctx) + if len(supportedChains) == 0 { + return chains.Chain{}, fmt.Errorf("no supported chains found") + } + // remove zeta chain from the supported chains + for i := 0; i < retryCount; i++ { + c := supportedChains[r.Intn(len(supportedChains))] + if !c.IsZetaChain() { + return c, nil + } + } + return chains.Chain{}, fmt.Errorf("no external chain found") +}