From 5e216c64585d5cac995977ccaad43846ee9cdd40 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 17 Oct 2022 17:44:41 +0200 Subject: [PATCH] IBC rate limiting: Testing helpers (#2941) (#2960) * test helpers for cosmwasm contracts * added helpers for ibctesting * comments (cherry picked from commit 8a19d8b3edb53c18c2607750ac8e9b5b3b37e71b) Co-authored-by: Nicolas Lara --- app/modules.go | 21 ++++++++ tests/e2e/configurer/chain/chain.go | 4 +- tests/e2e/configurer/chain/commands.go | 75 ++++++++++++++++++++++++++ tests/e2e/configurer/chain/queries.go | 27 ++++++++++ tests/e2e/containers/containers.go | 12 +++-- 5 files changed, 134 insertions(+), 5 deletions(-) diff --git a/app/modules.go b/app/modules.go index 3f9fe96c020..6bcb8b1fcc0 100644 --- a/app/modules.go +++ b/app/modules.go @@ -2,9 +2,13 @@ package app import ( "github.com/CosmWasm/wasmd/x/wasm" + "github.com/cosmos/cosmos-sdk/client" + capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" ibctransfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" ibc "github.com/cosmos/ibc-go/v3/modules/core" ibchost "github.com/cosmos/ibc-go/v3/modules/core/24-host" + ibckeeper "github.com/cosmos/ibc-go/v3/modules/core/keeper" ica "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts" icatypes "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/types" @@ -245,3 +249,20 @@ func (app *OsmosisApp) GetAccountKeeper() simtypes.AccountKeeper { func (app *OsmosisApp) GetBankKeeper() simtypes.BankKeeper { return app.AppKeepers.BankKeeper } + +// Required for ibctesting +func (app *OsmosisApp) GetStakingKeeper() stakingkeeper.Keeper { + return *app.AppKeepers.StakingKeeper // Dereferencing the pointer +} + +func (app *OsmosisApp) GetIBCKeeper() *ibckeeper.Keeper { + return app.AppKeepers.IBCKeeper // This is a *ibckeeper.Keeper +} + +func (app *OsmosisApp) GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper { + return app.AppKeepers.ScopedIBCKeeper +} + +func (app *OsmosisApp) GetTxConfig() client.TxConfig { + return MakeEncodingConfig().TxConfig +} diff --git a/tests/e2e/configurer/chain/chain.go b/tests/e2e/configurer/chain/chain.go index c8a055d2b90..e9e55a55c87 100644 --- a/tests/e2e/configurer/chain/chain.go +++ b/tests/e2e/configurer/chain/chain.go @@ -29,6 +29,8 @@ type Config struct { LatestLockNumber int NodeConfigs []*NodeConfig + LatestCodeId int + t *testing.T containerManager *containers.Manager } @@ -151,7 +153,7 @@ func (c *Config) SendIBC(dstChain *Config, recipient string, token sdk.Coin) { if ibcCoin.Len() == 1 { tokenPre := balancesDstPre.AmountOfNoDenomValidation(ibcCoin[0].Denom) tokenPost := balancesDstPost.AmountOfNoDenomValidation(ibcCoin[0].Denom) - resPre := initialization.OsmoToken.Amount + resPre := token.Amount resPost := tokenPost.Sub(tokenPre) return resPost.Uint64() == resPre.Uint64() } else { diff --git a/tests/e2e/configurer/chain/commands.go b/tests/e2e/configurer/chain/commands.go index 3cd74af4790..ee070b4b754 100644 --- a/tests/e2e/configurer/chain/commands.go +++ b/tests/e2e/configurer/chain/commands.go @@ -1,7 +1,9 @@ package chain import ( + "encoding/json" "fmt" + "os" "regexp" "strconv" "strings" @@ -36,6 +38,79 @@ func (n *NodeConfig) CreatePool(poolFile, from string) uint64 { return poolID } +func (n *NodeConfig) StoreWasmCode(wasmFile, from string) { + n.LogActionF("storing wasm code from file %s", wasmFile) + cmd := []string{"osmosisd", "tx", "wasm", "store", wasmFile, fmt.Sprintf("--from=%s", from), "--gas=auto", "--gas-prices=0.1uosmo", "--gas-adjustment=1.3"} + _, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd) + require.NoError(n.t, err) + n.LogActionF("successfully stored") +} + +func (n *NodeConfig) InstantiateWasmContract(codeId, initMsg, from string) { + n.LogActionF("instantiating wasm contract %s with %s", codeId, initMsg) + cmd := []string{"osmosisd", "tx", "wasm", "instantiate", codeId, initMsg, fmt.Sprintf("--from=%s", from), "--no-admin", "--label=ratelimit"} + n.LogActionF(strings.Join(cmd, " ")) + _, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd) + require.NoError(n.t, err) + n.LogActionF("successfully initialized") +} + +func (n *NodeConfig) WasmExecute(contract, execMsg, from string) { + n.LogActionF("executing %s on wasm contract %s from %s", execMsg, contract, from) + cmd := []string{"osmosisd", "tx", "wasm", "execute", contract, execMsg, fmt.Sprintf("--from=%s", from)} + n.LogActionF(strings.Join(cmd, " ")) + _, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd) + require.NoError(n.t, err) + n.LogActionF("successfully executed") +} + +// QueryParams extracts the params for a given subspace and key. This is done generically via json to avoid having to +// specify the QueryParamResponse type (which may not exist for all params). +func (n *NodeConfig) QueryParams(subspace, key string, result any) { + cmd := []string{"osmosisd", "query", "params", "subspace", subspace, key, "--output=json"} + + out, _, err := n.containerManager.ExecCmd(n.t, n.Name, cmd, "") + require.NoError(n.t, err) + + err = json.Unmarshal(out.Bytes(), &result) + require.NoError(n.t, err) +} + +func (n *NodeConfig) SubmitParamChangeProposal(proposalJson, from string) { + n.LogActionF("submitting param change proposal %s", proposalJson) + // ToDo: Is there a better way to do this? + wd, err := os.Getwd() + require.NoError(n.t, err) + localProposalFile := wd + "/scripts/param_change_proposal.json" + f, err := os.Create(localProposalFile) + require.NoError(n.t, err) + _, err = f.WriteString(proposalJson) + require.NoError(n.t, err) + err = f.Close() + require.NoError(n.t, err) + + cmd := []string{"osmosisd", "tx", "gov", "submit-proposal", "param-change", "/osmosis/param_change_proposal.json", fmt.Sprintf("--from=%s", from)} + + _, _, err = n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd) + require.NoError(n.t, err) + + err = os.Remove(localProposalFile) + require.NoError(n.t, err) + + n.LogActionF("successfully submitted param change proposal") +} + +func (n *NodeConfig) FailIBCTransfer(from, recipient, amount string) { + n.LogActionF("IBC sending %s from %s to %s", amount, from, recipient) + + cmd := []string{"osmosisd", "tx", "ibc-transfer", "transfer", "transfer", "channel-0", recipient, amount, fmt.Sprintf("--from=%s", from)} + + _, _, err := n.containerManager.ExecTxCmdWithSuccessString(n.t, n.chainId, n.Name, cmd, "rate limit exceeded") + require.NoError(n.t, err) + + n.LogActionF("Failed to send IBC transfer (as expected)") +} + // SwapExactAmountIn swaps tokenInCoin to get at least tokenOutMinAmountInt of the other token's pool out. // swapRoutePoolIds is the comma separated list of pool ids to swap through. // swapRouteDenoms is the comma separated list of denoms to swap through. diff --git a/tests/e2e/configurer/chain/queries.go b/tests/e2e/configurer/chain/queries.go index 498b4aa1181..8a3118db9dd 100644 --- a/tests/e2e/configurer/chain/queries.go +++ b/tests/e2e/configurer/chain/queries.go @@ -9,6 +9,8 @@ import ( "strconv" "time" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" @@ -83,6 +85,31 @@ func (n *NodeConfig) QueryBalances(address string) (sdk.Coins, error) { return balancesResp.GetBalances(), nil } +func (n *NodeConfig) QueryTotalSupply() (sdk.Coins, error) { + bz, err := n.QueryGRPCGateway("cosmos/bank/v1beta1/supply") + require.NoError(n.t, err) + + var supplyResp banktypes.QueryTotalSupplyResponse + if err := util.Cdc.UnmarshalJSON(bz, &supplyResp); err != nil { + return sdk.Coins{}, err + } + return supplyResp.GetSupply(), nil +} + +func (n *NodeConfig) QueryContractsFromId(codeId int) ([]string, error) { + path := fmt.Sprintf("/cosmwasm/wasm/v1/code/%d/contracts", codeId) + bz, err := n.QueryGRPCGateway(path) + + require.NoError(n.t, err) + + var contractsResponse wasmtypes.QueryContractsByCodeResponse + if err := util.Cdc.UnmarshalJSON(bz, &contractsResponse); err != nil { + return nil, err + } + + return contractsResponse.Contracts, nil +} + func (n *NodeConfig) QueryPropTally(proposalNumber int) (sdk.Int, sdk.Int, sdk.Int, sdk.Int, error) { path := fmt.Sprintf("cosmos/gov/v1beta1/proposals/%d/tally", proposalNumber) bz, err := n.QueryGRPCGateway(path) diff --git a/tests/e2e/containers/containers.go b/tests/e2e/containers/containers.go index 68f990e2ed8..1bee32bdff6 100644 --- a/tests/e2e/containers/containers.go +++ b/tests/e2e/containers/containers.go @@ -53,13 +53,17 @@ func NewManager(isUpgrade bool, isFork bool, isDebugLogEnabled bool) (docker *Ma return docker, nil } -// ExecTxCmd Runs ExecCmd, with flags for txs added. -// namely adding flags `--chain-id={chain-id} -b=block --yes --keyring-backend=test "--log_format=json"`, -// and searching for `code: 0` +// ExecTxCmd Runs ExecTxCmdWithSuccessString searching for `code: 0` func (m *Manager) ExecTxCmd(t *testing.T, chainId string, containerName string, command []string) (bytes.Buffer, bytes.Buffer, error) { + return m.ExecTxCmdWithSuccessString(t, chainId, containerName, command, "code: 0") +} + +// ExecTxCmdWithSuccessString Runs ExecCmd, with flags for txs added. +// namely adding flags `--chain-id={chain-id} -b=block --yes --keyring-backend=test "--log_format=json"`, +// and searching for `successStr` +func (m *Manager) ExecTxCmdWithSuccessString(t *testing.T, chainId string, containerName string, command []string, successStr string) (bytes.Buffer, bytes.Buffer, error) { allTxArgs := []string{fmt.Sprintf("--chain-id=%s", chainId), "-b=block", "--yes", "--keyring-backend=test", "--log_format=json"} txCommand := append(command, allTxArgs...) - successStr := "code: 0" return m.ExecCmd(t, containerName, txCommand, successStr) }