diff --git a/.github/workflows/e2e-compatibility-workflow-call.yaml b/.github/workflows/e2e-compatibility-workflow-call.yaml index bb46c68c4337..b52b461684c0 100644 --- a/.github/workflows/e2e-compatibility-workflow-call.yaml +++ b/.github/workflows/e2e-compatibility-workflow-call.yaml @@ -57,7 +57,7 @@ jobs: CHAIN_A_TAG: '${{ matrix.chain-a }}' CHAIN_B_TAG: '${{ matrix.chain-b }}' CHAIN_BINARY: 'simd' - RELAYER_TYPE: '${{ matrix.relayer-type }}' + RELAYER_ID: '${{ matrix.relayer-type }}' - name: Upload Diagnostics uses: actions/upload-artifact@v3 # we only want to upload logs on test failures. diff --git a/.github/workflows/e2e-test-workflow-call.yml b/.github/workflows/e2e-test-workflow-call.yml index 983270dd8966..f02e49c66e1c 100644 --- a/.github/workflows/e2e-test-workflow-call.yml +++ b/.github/workflows/e2e-test-workflow-call.yml @@ -166,7 +166,7 @@ jobs: CHAIN_B_TAG: '${{ inputs.chain-b-tag }}' RELAYER_IMAGE: '${{ inputs.relayer-image }}' RELAYER_TAG: '${{ inputs.relayer-tag }}' - RELAYER_TYPE: '${{ inputs.relayer-type }}' + RELAYER_ID: '${{ inputs.relayer-type }}' CHAIN_BINARY: '${{ inputs.chain-binary }}' CHAIN_UPGRADE_TAG: '${{ inputs.chain-upgrade-tag }}' CHAIN_UPGRADE_PLAN: '${{ inputs.upgrade-plan-name }}' diff --git a/.github/workflows/e2e-upgrade.yaml b/.github/workflows/e2e-upgrade.yaml index 87c3cc8cbe2a..6b540b59c80b 100644 --- a/.github/workflows/e2e-upgrade.yaml +++ b/.github/workflows/e2e-upgrade.yaml @@ -13,7 +13,7 @@ on: jobs: upgrade-v5-hermes: - uses: cosmos/ibc-go/.github/workflows/e2e-test-workflow-call.yml@main + uses: .github/workflows/e2e-test-workflow-call.yml with: chain-image: ghcr.io/cosmos/ibc-go-simd chain-binary: simd @@ -27,7 +27,7 @@ jobs: relayer-type: hermes upgrade-v7-hermes: - uses: cosmos/ibc-go/.github/workflows/e2e-test-workflow-call.yml@main + uses: .github/workflows/e2e-test-workflow-call.yml with: chain-image: ghcr.io/cosmos/ibc-go-simd chain-binary: simd @@ -41,7 +41,7 @@ jobs: relayer-type: hermes upgrade-v7_1-hermes: - uses: cosmos/ibc-go/.github/workflows/e2e-test-workflow-call.yml@main + uses: .github/workflows/e2e-test-workflow-call.yml with: chain-image: ghcr.io/cosmos/ibc-go-simd chain-binary: simd @@ -55,7 +55,7 @@ jobs: relayer-type: hermes upgrade-v8-hermes: - uses: cosmos/ibc-go/.github/workflows/e2e-test-workflow-call.yml@main + uses: .github/workflows/e2e-test-workflow-call.yml with: chain-image: ghcr.io/cosmos/ibc-go-simd chain-binary: simd @@ -69,7 +69,7 @@ jobs: relayer-type: hermes upgrade-v5-rly: - uses: cosmos/ibc-go/.github/workflows/e2e-test-workflow-call.yml@main + uses: .github/workflows/e2e-test-workflow-call.yml with: chain-image: ghcr.io/cosmos/ibc-go-simd chain-binary: simd @@ -85,7 +85,7 @@ jobs: relayer-tag: latest upgrade-v7-rly: - uses: cosmos/ibc-go/.github/workflows/e2e-test-workflow-call.yml@main + uses: .github/workflows/e2e-test-workflow-call.yml with: chain-image: ghcr.io/cosmos/ibc-go-simd chain-binary: simd @@ -101,7 +101,7 @@ jobs: relayer-tag: latest upgrade-v7_1-rly: - uses: cosmos/ibc-go/.github/workflows/e2e-test-workflow-call.yml@main + uses: .github/workflows/e2e-test-workflow-call.yml with: chain-image: ghcr.io/cosmos/ibc-go-simd chain-binary: simd @@ -117,7 +117,7 @@ jobs: relayer-tag: latest upgrade-v8-rly: - uses: cosmos/ibc-go/.github/workflows/e2e-test-workflow-call.yml@main + uses: .github/workflows/e2e-test-workflow-call.yml with: chain-image: ghcr.io/cosmos/ibc-go-simd chain-binary: simd diff --git a/e2e/README.md b/e2e/README.md index 278b99a359fd..46b4e1de2124 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -52,7 +52,7 @@ options specified in your config file. | CHAIN_B_TAG | The tag used for chain A | latest | | CHAIN_BINARY | The binary used in the container | simd | | RELAYER_TAG | The tag used for the relayer | main | -| RELAYER_TYPE | The type of relayer to use (rly/hermes) | rly | +| RELAYER_ID | The type of relayer to use (rly/hermes) | hermes | > Note: when running tests locally, **no images are pushed** to the `ghcr.io/cosmos/ibc-go-simd` registry. The images which are used only exist on your machine. diff --git a/e2e/relayer/relayer.go b/e2e/relayer/relayer.go index 5fc73bcc9bab..536fc452bbdf 100644 --- a/e2e/relayer/relayer.go +++ b/e2e/relayer/relayer.go @@ -25,8 +25,8 @@ const ( type Config struct { // Tag is the tag used for the relayer image. Tag string `yaml:"tag"` - // Type specifies the type of relayer that this is. - Type string `yaml:"type"` + // ID specifies the type of relayer that this is. + ID string `yaml:"id"` // Image is the image that should be used for the relayer. Image string `yaml:"image"` } @@ -34,13 +34,13 @@ type Config struct { // New returns an implementation of ibc.Relayer depending on the provided RelayerType. func New(t *testing.T, cfg Config, logger *zap.Logger, dockerClient *dockerclient.Client, network string) ibc.Relayer { t.Helper() - switch cfg.Type { + switch cfg.ID { case Rly: return newCosmosRelayer(t, cfg.Tag, logger, dockerClient, network, cfg.Image) case Hermes: return newHermesRelayer(t, cfg.Tag, logger, dockerClient, network, cfg.Image) default: - panic(fmt.Errorf("unknown relayer specified: %s", cfg.Type)) + panic(fmt.Errorf("unknown relayer specified: %s", cfg.ID)) } } @@ -49,10 +49,6 @@ func New(t *testing.T, cfg Config, logger *zap.Logger, dockerClient *dockerclien func newCosmosRelayer(t *testing.T, tag string, logger *zap.Logger, dockerClient *dockerclient.Client, network, relayerImage string) ibc.Relayer { t.Helper() - if relayerImage == "" { - relayerImage = RlyRelayerRepository - } - customImageOption := relayer.CustomDockerImage(relayerImage, tag, rlyRelayerUser) relayerProcessingOption := relayer.StartupFlags("-p", "events") // relayer processes via events @@ -67,10 +63,6 @@ func newCosmosRelayer(t *testing.T, tag string, logger *zap.Logger, dockerClient func newHermesRelayer(t *testing.T, tag string, logger *zap.Logger, dockerClient *dockerclient.Client, network, relayerImage string) ibc.Relayer { t.Helper() - if relayerImage == "" { - relayerImage = HermesRelayerRepository - } - customImageOption := relayer.CustomDockerImage(relayerImage, tag, hermesRelayerUser) relayerFactory := interchaintest.NewBuiltinRelayerFactory(ibc.Hermes, logger, customImageOption) diff --git a/e2e/sample.config.yaml b/e2e/sample.config.yaml index e7e185737acd..3dd3371208fe 100644 --- a/e2e/sample.config.yaml +++ b/e2e/sample.config.yaml @@ -20,10 +20,14 @@ chains: tag: main # override with CHAIN_B_TAG binary: simd # override with CHAIN_BINARY -relayer: - type: hermes # override with RELAYER_TYPE - image: ghcr.io/informalsystems/hermes # override with RELAYER_IMAGE - tag: "bef2f53" # override with RELAYER_TAG +activeRelayer: hermes # override with RELAYER_ID +relayers: + - id: hermes + image: ghcr.io/informalsystems/hermes + tag: "bef2f53" + - id: rly + image: ghcr.io/cosmos/relayer + tag: "latest" cometbft: logLevel: info diff --git a/e2e/tests/core/02-client/client_test.go b/e2e/tests/core/02-client/client_test.go index 383ebb9300ea..1591c684aac3 100644 --- a/e2e/tests/core/02-client/client_test.go +++ b/e2e/tests/core/02-client/client_test.go @@ -16,7 +16,7 @@ import ( test "github.com/strangelove-ventures/interchaintest/v8/testutil" testifysuite "github.com/stretchr/testify/suite" - "cosmossdk.io/x/upgrade/types" + upgradetypes "cosmossdk.io/x/upgrade/types" "github.com/cosmos/cosmos-sdk/client/grpc/cmtservice" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" @@ -85,6 +85,7 @@ func (s *ClientTestSuite) TestScheduleIBCUpgrade_Succeeds() { chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) const planHeight = int64(75) + const legacyPlanHeight = planHeight * 2 var newChainID string t.Run("execute proposal for MsgIBCSoftwareUpgrade", func(t *testing.T) { @@ -107,14 +108,14 @@ func (s *ClientTestSuite) TestScheduleIBCUpgrade_Succeeds() { scheduleUpgradeMsg, err := clienttypes.NewMsgIBCSoftwareUpgrade( authority.String(), - types.Plan{ + upgradetypes.Plan{ Name: "upgrade-client", Height: planHeight, }, upgradedClientState, ) s.Require().NoError(err) - s.ExecuteGovV1Proposal(ctx, scheduleUpgradeMsg, chainA, chainAWallet) + s.ExecuteAndPassGovV1Proposal(ctx, scheduleUpgradeMsg, chainA, chainAWallet) }) t.Run("check that IBC software upgrade has been scheduled successfully on chainA", func(t *testing.T) { @@ -132,6 +133,35 @@ func (s *ClientTestSuite) TestScheduleIBCUpgrade_Succeeds() { s.Require().Equal("upgrade-client", plan.Name) s.Require().Equal(planHeight, plan.Height) }) + + t.Run("ensure legacy proposal does not succeed", func(t *testing.T) { + + authority, err := s.QueryModuleAccountAddress(ctx, govtypes.ModuleName, chainA) + s.Require().NoError(err) + s.Require().NotNil(authority) + + clientState, err := s.QueryClientState(ctx, chainB, ibctesting.FirstClientID) + s.Require().NoError(err) + + originalChainID := clientState.(*ibctm.ClientState).ChainId + revisionNumber := clienttypes.ParseChainID(originalChainID) + // increment revision number even with new chain ID to prevent loss of misbehaviour detection support + newChainID, err = clienttypes.SetRevisionNumber(originalChainID, revisionNumber+1) + s.Require().NoError(err) + s.Require().NotEqual(originalChainID, newChainID) + + upgradedClientState := clientState.ZeroCustomFields().(*ibctm.ClientState) + upgradedClientState.ChainId = newChainID + + legacyUpgradeProposal, err := clienttypes.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, upgradetypes.Plan{ + Name: "upgrade-client-legacy", + Height: legacyPlanHeight, + }, upgradedClientState) + + s.Require().NoError(err) + txResp := s.ExecuteGovV1Beta1Proposal(ctx, chainA, chainAWallet, legacyUpgradeProposal) + s.AssertTxFailure(txResp, govtypes.ErrInvalidProposalContent) + }) } // TestRecoverClient_Succeeds tests that a governance proposal to recover a client using a MsgRecoverClient is successful. @@ -202,7 +232,7 @@ func (s *ClientTestSuite) TestRecoverClient_Succeeds() { s.Require().NoError(err) recoverClientMsg := clienttypes.NewMsgRecoverClient(authority.String(), subjectClientID, substituteClientID) s.Require().NotNil(recoverClientMsg) - s.ExecuteGovV1Proposal(ctx, recoverClientMsg, chainA, chainAWallet) + s.ExecuteAndPassGovV1Proposal(ctx, recoverClientMsg, chainA, chainAWallet) }) t.Run("check status of each client", func(t *testing.T) { @@ -353,7 +383,7 @@ func (s *ClientTestSuite) TestAllowedClientsParam() { s.Require().NotNil(authority) msg := clienttypes.NewMsgUpdateParams(authority.String(), clienttypes.NewParams(allowedClient)) - s.ExecuteGovV1Proposal(ctx, msg, chainA, chainAWallet) + s.ExecuteAndPassGovV1Proposal(ctx, msg, chainA, chainAWallet) } else { value, err := tmjson.Marshal([]string{allowedClient}) s.Require().NoError(err) @@ -362,7 +392,7 @@ func (s *ClientTestSuite) TestAllowedClientsParam() { } proposal := paramsproposaltypes.NewParameterChangeProposal(ibctesting.Title, ibctesting.Description, changes) - s.ExecuteGovV1Beta1Proposal(ctx, chainA, chainAWallet, proposal) + s.ExecuteAndPassGovV1Beta1Proposal(ctx, chainA, chainAWallet, proposal) } }) diff --git a/e2e/tests/core/03-connection/connection_test.go b/e2e/tests/core/03-connection/connection_test.go index 91e33d3fb075..39a6110008e4 100644 --- a/e2e/tests/core/03-connection/connection_test.go +++ b/e2e/tests/core/03-connection/connection_test.go @@ -90,14 +90,14 @@ func (s *ConnectionTestSuite) TestMaxExpectedTimePerBlockParam() { s.Require().NotNil(authority) msg := connectiontypes.NewMsgUpdateParams(authority.String(), connectiontypes.NewParams(delay)) - s.ExecuteGovV1Proposal(ctx, msg, chainA, chainAWallet) + s.ExecuteAndPassGovV1Proposal(ctx, msg, chainA, chainAWallet) } else { changes := []paramsproposaltypes.ParamChange{ paramsproposaltypes.NewParamChange(ibcexported.ModuleName, string(connectiontypes.KeyMaxExpectedTimePerBlock), fmt.Sprintf(`"%d"`, delay)), } proposal := paramsproposaltypes.NewParameterChangeProposal(ibctesting.Title, ibctesting.Description, changes) - s.ExecuteGovV1Beta1Proposal(ctx, chainA, chainAWallet, proposal) + s.ExecuteAndPassGovV1Beta1Proposal(ctx, chainA, chainAWallet, proposal) } }) diff --git a/e2e/tests/interchain_accounts/gov_test.go b/e2e/tests/interchain_accounts/gov_test.go index 75286f21d3d2..4c84901c292a 100644 --- a/e2e/tests/interchain_accounts/gov_test.go +++ b/e2e/tests/interchain_accounts/gov_test.go @@ -54,7 +54,7 @@ func (s *InterchainAccountsGovTestSuite) TestInterchainAccountsGovIntegration() t.Run("execute proposal for MsgRegisterInterchainAccount", func(t *testing.T) { version := icatypes.NewDefaultMetadataString(ibctesting.FirstConnectionID, ibctesting.FirstConnectionID) msgRegisterAccount := controllertypes.NewMsgRegisterInterchainAccount(ibctesting.FirstConnectionID, govModuleAddress.String(), version) - s.ExecuteGovV1Proposal(ctx, msgRegisterAccount, chainA, controllerAccount) + s.ExecuteAndPassGovV1Proposal(ctx, msgRegisterAccount, chainA, controllerAccount) }) t.Run("start relayer", func(t *testing.T) { @@ -104,7 +104,7 @@ func (s *InterchainAccountsGovTestSuite) TestInterchainAccountsGovIntegration() } msgSendTx := controllertypes.NewMsgSendTx(govModuleAddress.String(), ibctesting.FirstConnectionID, uint64(time.Hour.Nanoseconds()), packetData) - s.ExecuteGovV1Proposal(ctx, msgSendTx, chainA, controllerAccount) + s.ExecuteAndPassGovV1Proposal(ctx, msgSendTx, chainA, controllerAccount) }) t.Run("verify tokens transferred", func(t *testing.T) { diff --git a/e2e/tests/interchain_accounts/params_test.go b/e2e/tests/interchain_accounts/params_test.go index 5e2540c2ede7..2ecfe91c3f9f 100644 --- a/e2e/tests/interchain_accounts/params_test.go +++ b/e2e/tests/interchain_accounts/params_test.go @@ -76,14 +76,14 @@ func (s *InterchainAccountsParamsTestSuite) TestControllerEnabledParam() { Signer: authority.String(), Params: controllertypes.NewParams(false), } - s.ExecuteGovV1Proposal(ctx, &msg, chainA, controllerAccount) + s.ExecuteAndPassGovV1Proposal(ctx, &msg, chainA, controllerAccount) } else { changes := []paramsproposaltypes.ParamChange{ paramsproposaltypes.NewParamChange(controllertypes.StoreKey, string(controllertypes.KeyControllerEnabled), "false"), } proposal := paramsproposaltypes.NewParameterChangeProposal(ibctesting.Title, ibctesting.Description, changes) - s.ExecuteGovV1Beta1Proposal(ctx, chainA, controllerAccount, proposal) + s.ExecuteAndPassGovV1Beta1Proposal(ctx, chainA, controllerAccount, proposal) } }) @@ -133,14 +133,14 @@ func (s *InterchainAccountsParamsTestSuite) TestHostEnabledParam() { Signer: authority.String(), Params: hosttypes.NewParams(false, []string{hosttypes.AllowAllHostMsgs}), } - s.ExecuteGovV1Proposal(ctx, &msg, chainB, chainBUser) + s.ExecuteAndPassGovV1Proposal(ctx, &msg, chainB, chainBUser) } else { changes := []paramsproposaltypes.ParamChange{ paramsproposaltypes.NewParamChange(hosttypes.StoreKey, string(hosttypes.KeyHostEnabled), "false"), } proposal := paramsproposaltypes.NewParameterChangeProposal(ibctesting.Title, ibctesting.Description, changes) - s.ExecuteGovV1Beta1Proposal(ctx, chainB, chainBUser, proposal) + s.ExecuteAndPassGovV1Beta1Proposal(ctx, chainB, chainBUser, proposal) } }) diff --git a/e2e/tests/transfer/base_test.go b/e2e/tests/transfer/base_test.go index 8310e75d0acb..1330a4bba806 100644 --- a/e2e/tests/transfer/base_test.go +++ b/e2e/tests/transfer/base_test.go @@ -287,14 +287,14 @@ func (s *TransferTestSuite) TestSendEnabledParam() { t.Run("change send enabled parameter to disabled", func(t *testing.T) { if isSelfManagingParams { msg := transfertypes.NewMsgUpdateParams(govModuleAddress.String(), transfertypes.NewParams(false, true)) - s.ExecuteGovV1Proposal(ctx, msg, chainA, chainAWallet) + s.ExecuteAndPassGovV1Proposal(ctx, msg, chainA, chainAWallet) } else { changes := []paramsproposaltypes.ParamChange{ paramsproposaltypes.NewParamChange(transfertypes.StoreKey, string(transfertypes.KeySendEnabled), "false"), } proposal := paramsproposaltypes.NewParameterChangeProposal(ibctesting.Title, ibctesting.Description, changes) - s.ExecuteGovV1Beta1Proposal(ctx, chainA, chainAWallet, proposal) + s.ExecuteAndPassGovV1Beta1Proposal(ctx, chainA, chainAWallet, proposal) } }) @@ -378,14 +378,14 @@ func (s *TransferTestSuite) TestReceiveEnabledParam() { t.Run("change receive enabled parameter to disabled ", func(t *testing.T) { if isSelfManagingParams { msg := transfertypes.NewMsgUpdateParams(govModuleAddress.String(), transfertypes.NewParams(false, false)) - s.ExecuteGovV1Proposal(ctx, msg, chainA, chainAWallet) + s.ExecuteAndPassGovV1Proposal(ctx, msg, chainA, chainAWallet) } else { changes := []paramsproposaltypes.ParamChange{ paramsproposaltypes.NewParamChange(transfertypes.StoreKey, string(transfertypes.KeyReceiveEnabled), "false"), } proposal := paramsproposaltypes.NewParameterChangeProposal(ibctesting.Title, ibctesting.Description, changes) - s.ExecuteGovV1Beta1Proposal(ctx, chainA, chainAWallet, proposal) + s.ExecuteAndPassGovV1Beta1Proposal(ctx, chainA, chainAWallet, proposal) } }) diff --git a/e2e/tests/upgrades/upgrade_test.go b/e2e/tests/upgrades/upgrade_test.go index 76530d005205..86802adb2f71 100644 --- a/e2e/tests/upgrades/upgrade_test.go +++ b/e2e/tests/upgrades/upgrade_test.go @@ -61,7 +61,7 @@ func (s *UpgradeTestSuite) UpgradeChain(ctx context.Context, chain *cosmos.Cosmo } upgradeProposal := upgradetypes.NewSoftwareUpgradeProposal(fmt.Sprintf("upgrade from %s to %s", currentVersion, upgradeVersion), "upgrade chain E2E test", plan) - s.ExecuteGovV1Beta1Proposal(ctx, chain, wallet, upgradeProposal) + s.ExecuteAndPassGovV1Beta1Proposal(ctx, chain, wallet, upgradeProposal) height, err := chain.Height(ctx) s.Require().NoError(err, "error fetching height before upgrade") @@ -376,7 +376,7 @@ func (s *UpgradeTestSuite) TestV6ToV7ChainUpgrade() { // this restart is a temporary workaround to a limitation in hermes requiring a restart // in some cases after an upgrade. tc := testsuite.LoadConfig() - if tc.RelayerConfig.Type == e2erelayer.Hermes { + if tc.GetActiveRelayerConfig().ID == e2erelayer.Hermes { s.RestartRelayer(ctx, relayer) } @@ -563,7 +563,7 @@ func (s *UpgradeTestSuite) TestV7ToV8ChainUpgrade() { s.Require().NotNil(authority) msg := clienttypes.NewMsgUpdateParams(authority.String(), clienttypes.NewParams(exported.Tendermint, "some-client")) - s.ExecuteGovV1Proposal(ctx, msg, chainB, chainBWallet) + s.ExecuteAndPassGovV1Proposal(ctx, msg, chainB, chainBWallet) }) t.Run("query params", func(t *testing.T) { diff --git a/e2e/testsuite/grpc_query.go b/e2e/testsuite/grpc_query.go index 200713684481..38f2ab0e2b85 100644 --- a/e2e/testsuite/grpc_query.go +++ b/e2e/testsuite/grpc_query.go @@ -327,7 +327,6 @@ func (s *E2ETestSuite) GetValidatorSetByHeight(ctx context.Context, chain ibc.Ch // QueryModuleAccountAddress returns the sdk.AccAddress of a given module name. func (s *E2ETestSuite) QueryModuleAccountAddress(ctx context.Context, moduleName string, chain *cosmos.CosmosChain) (sdk.AccAddress, error) { authClient := s.GetChainGRCPClients(chain).AuthQueryClient - resp, err := authClient.ModuleAccountByName(ctx, &authtypes.QueryModuleAccountByNameRequest{ Name: moduleName, }) diff --git a/e2e/testsuite/testconfig.go b/e2e/testsuite/testconfig.go index 39d73eed36b5..6c213b6ebadb 100644 --- a/e2e/testsuite/testconfig.go +++ b/e2e/testsuite/testconfig.go @@ -35,13 +35,8 @@ const ( // ChainBTagEnv specifies the tag that Chain B will use. If unspecified // the value will default to the same value as Chain A. ChainBTagEnv = "CHAIN_B_TAG" - // RelayerTagEnv specifies the relayer version. Defaults to "main" - RelayerTagEnv = "RELAYER_TAG" - // RelayerImageEnv specifies the image that the relayer will use. If left unspecified, it will default - // to values set for hermesRelayerRepository or rlyRelayerRepository. - RelayerImageEnv = "RELAYER_IMAGE" - // RelayerTypeEnv specifies the type of relayer that should be used. - RelayerTypeEnv = "RELAYER_TYPE" + // RelayerIDEnv specifies the ID of the relayer to use. + RelayerIDEnv = "RELAYER_ID" // ChainBinaryEnv binary is the binary that will be used for both chains. ChainBinaryEnv = "CHAIN_BINARY" // ChainUpgradeTagEnv specifies the upgrade version tag @@ -78,8 +73,10 @@ func getChainImage(binary string) string { type TestConfig struct { // ChainConfigs holds configuration values related to the chains used in the tests. ChainConfigs []ChainConfig `yaml:"chains"` - // RelayerConfig holds configuration for the relayer to be used. - RelayerConfig relayer.Config `yaml:"relayer"` + // RelayerConfig holds all known relayer configurations that can be used in the tests. + RelayerConfigs []relayer.Config `yaml:"relayers"` + // ActiveRelayer specifies the relayer that will be used. It must match the ID of one of the entries in RelayerConfigs. + ActiveRelayer string `yaml:"activeRelayer"` // UpgradeConfig holds values used only for the upgrade tests. UpgradeConfig UpgradeConfig `yaml:"upgrade"` // CometBFTConfig holds values for configuring CometBFT. @@ -88,6 +85,86 @@ type TestConfig struct { DebugConfig DebugConfig `yaml:"debug"` } +// Validate validates the test configuration is valid for use within the tests. +// this should be called before using the configuration. +func (tc TestConfig) Validate() error { + if err := tc.validateChains(); err != nil { + return fmt.Errorf("invalid chain configuration: %w", err) + } + + if err := tc.validateRelayers(); err != nil { + return fmt.Errorf("invalid relayer configuration: %w", err) + } + return nil +} + +// validateChains validates the chain configurations. +func (tc TestConfig) validateChains() error { + for _, cfg := range tc.ChainConfigs { + if cfg.Binary == "" { + return fmt.Errorf("chain config missing binary: %+v", cfg) + } + if cfg.Image == "" { + return fmt.Errorf("chain config missing image: %+v", cfg) + } + if cfg.Tag == "" { + return fmt.Errorf("chain config missing tag: %+v", cfg) + } + + // TODO: validate chainID in https://github.com/cosmos/ibc-go/issues/4697 + // these are not passed in the CI at the moment. Defaults are used. + if !IsCI() { + if cfg.ChainID == "" { + return fmt.Errorf("chain config missing chainID: %+v", cfg) + } + } + + // TODO: validate number of nodes in https://github.com/cosmos/ibc-go/issues/4697 + // these are not passed in the CI at the moment. + if !IsCI() { + if cfg.NumValidators == 0 && cfg.NumFullNodes == 0 { + return fmt.Errorf("chain config missing number of validators or full nodes: %+v", cfg) + } + } + } + return nil +} + +// validateRelayers validates relayer configuration. +func (tc TestConfig) validateRelayers() error { + if len(tc.RelayerConfigs) < 1 { + return fmt.Errorf("no relayer configurations specified") + } + + for _, r := range tc.RelayerConfigs { + if r.ID == "" { + return fmt.Errorf("relayer config missing ID: %+v", r) + } + if r.Image == "" { + return fmt.Errorf("relayer config missing image: %+v", r) + } + if r.Tag == "" { + return fmt.Errorf("relayer config missing tag: %+v", r) + } + } + + if tc.GetActiveRelayerConfig() == nil { + return fmt.Errorf("active relayer %s not found in relayer configs: %+v", tc.ActiveRelayer, tc.RelayerConfigs) + } + + return nil +} + +// GetActiveRelayerConfig returns the currently specified relayer config. +func (tc TestConfig) GetActiveRelayerConfig() *relayer.Config { + for _, r := range tc.RelayerConfigs { + if r.ID == tc.ActiveRelayer { + return &r + } + } + return nil +} + // GetChainNumValidators returns the number of validators for the specific chain index. // default 1 func (tc TestConfig) GetChainNumValidators(idx int) int { @@ -151,10 +228,20 @@ type DebugConfig struct { // if any environment variables are specified, they will take precedence over the individual configuration // options. func LoadConfig() TestConfig { + tc := getConfig() + if err := tc.Validate(); err != nil { + panic(err) + } + return tc +} + +// getConfig returns the TestConfig with any environment variable overrides. +func getConfig() TestConfig { fileTc, foundFile := fromFile() if !foundFile { return fromEnv() } + return applyEnvironmentVariableOverrides(fileTc) } @@ -198,16 +285,8 @@ func applyEnvironmentVariableOverrides(fromFile TestConfig) TestConfig { } } - if os.Getenv(RelayerTagEnv) != "" { - fromFile.RelayerConfig.Tag = envTc.RelayerConfig.Tag - } - - if os.Getenv(RelayerTypeEnv) != "" { - fromFile.RelayerConfig.Type = envTc.RelayerConfig.Type - } - - if os.Getenv(RelayerImageEnv) != "" { - fromFile.RelayerConfig.Image = envTc.RelayerConfig.Image + if os.Getenv(RelayerIDEnv) != "" { + fromFile.ActiveRelayer = envTc.ActiveRelayer } if os.Getenv(ChainUpgradePlanEnv) != "" { @@ -224,9 +303,16 @@ func applyEnvironmentVariableOverrides(fromFile TestConfig) TestConfig { // fromEnv returns a TestConfig constructed from environment variables. func fromEnv() TestConfig { return TestConfig{ - ChainConfigs: getChainConfigsFromEnv(), - UpgradeConfig: getUpgradePlanConfigFromEnv(), - RelayerConfig: getRelayerConfigFromEnv(), + ChainConfigs: getChainConfigsFromEnv(), + UpgradeConfig: getUpgradePlanConfigFromEnv(), + ActiveRelayer: os.Getenv(RelayerIDEnv), + + // TODO: we can remove this, and specify these values in a config file for the CI + // in https://github.com/cosmos/ibc-go/issues/4697 + RelayerConfigs: []relayer.Config{ + getDefaultRlyRelayerConfig(), + getDefaultHermesRelayerConfig(), + }, CometBFTConfig: CometBFTConfig{LogLevel: "info"}, } } @@ -282,45 +368,22 @@ func getConfigFilePath() string { return path.Join(homeDir, defaultConfigFileName) } -// getRelayerConfigFromEnv returns the RelayerConfig from present environment variables. -func getRelayerConfigFromEnv() relayer.Config { - relayerType := strings.TrimSpace(os.Getenv(RelayerTypeEnv)) - if relayerType == "" { - relayerType = defaultRelayerType - } - - relayerConfig := getDefaultRlyRelayerConfig() - if relayerType == relayer.Hermes { - relayerConfig = getDefaultHermesRelayerConfig() - } - - relayerTag := strings.TrimSpace(os.Getenv(RelayerTagEnv)) - if relayerTag != "" { - relayerConfig.Tag = relayerTag - } - - relayerImage := strings.TrimSpace(os.Getenv(RelayerImageEnv)) - if relayerImage != "" { - relayerConfig.Image = relayerImage - } - - return relayerConfig -} - +// TODO: remove in https://github.com/cosmos/ibc-go/issues/4697 // getDefaultHermesRelayerConfig returns the default config for the hermes relayer. func getDefaultHermesRelayerConfig() relayer.Config { return relayer.Config{ Tag: defaultHermesTag, - Type: relayer.Hermes, + ID: relayer.Hermes, Image: relayer.HermesRelayerRepository, } } +// TODO: remove in https://github.com/cosmos/ibc-go/issues/4697 // getDefaultRlyRelayerConfig returns the default config for the golang relayer. func getDefaultRlyRelayerConfig() relayer.Config { return relayer.Config{ Tag: defaultRlyTag, - Type: relayer.Rly, + ID: relayer.Rly, Image: relayer.RlyRelayerRepository, } } diff --git a/e2e/testsuite/testsuite.go b/e2e/testsuite/testsuite.go index a4ec8b0f340e..47fc9d8e4415 100644 --- a/e2e/testsuite/testsuite.go +++ b/e2e/testsuite/testsuite.go @@ -91,7 +91,7 @@ func (s *E2ETestSuite) GetRelayerUsers(ctx context.Context, chainOpts ...ChainOp func (s *E2ETestSuite) SetupChainsRelayerAndChannel(ctx context.Context, channelOpts ...func(*ibc.CreateChannelOptions)) (ibc.Relayer, ibc.ChannelOutput) { chainA, chainB := s.GetChains() - r := relayer.New(s.T(), LoadConfig().RelayerConfig, s.logger, s.DockerClient, s.network) + r := relayer.New(s.T(), *LoadConfig().GetActiveRelayerConfig(), s.logger, s.DockerClient, s.network) pathName := s.generatePathName() diff --git a/e2e/testsuite/tx.go b/e2e/testsuite/tx.go index a248f4818975..068531f26f62 100644 --- a/e2e/testsuite/tx.go +++ b/e2e/testsuite/tx.go @@ -135,9 +135,9 @@ If this is a compatibility test, ensure that the fields are being sanitized in t return errorMsg } -// ExecuteGovV1Proposal submits a v1 governance proposal using the provided user and message and uses all validators +// ExecuteAndPassGovV1Proposal submits a v1 governance proposal using the provided user and message and uses all validators // to vote yes on the proposal. It ensures the proposal successfully passes. -func (s *E2ETestSuite) ExecuteGovV1Proposal(ctx context.Context, msg sdk.Msg, chain *cosmos.CosmosChain, user ibc.Wallet) { +func (s *E2ETestSuite) ExecuteAndPassGovV1Proposal(ctx context.Context, msg sdk.Msg, chain *cosmos.CosmosChain, user ibc.Wallet) { sender, err := sdk.AccAddressFromBech32(user.FormattedAddress()) s.Require().NoError(err) @@ -170,21 +170,15 @@ func (s *E2ETestSuite) ExecuteGovV1Proposal(ctx context.Context, msg sdk.Msg, ch s.Require().Equal(govtypesv1.StatusPassed, proposal.Status) } -// ExecuteGovV1Beta1Proposal submits the given v1beta1 governance proposal using the provided user and uses all validators to vote yes on the proposal. +// ExecuteAndPassGovV1Beta1Proposal submits the given v1beta1 governance proposal using the provided user and uses all validators to vote yes on the proposal. // It ensures the proposal successfully passes. -func (s *E2ETestSuite) ExecuteGovV1Beta1Proposal(ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, content govtypesv1beta1.Content) { +func (s *E2ETestSuite) ExecuteAndPassGovV1Beta1Proposal(ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, content govtypesv1beta1.Content) { proposalID := s.proposalIDs[chain.Config().ChainID] defer func() { s.proposalIDs[chain.Config().ChainID] = proposalID + 1 }() - sender, err := sdk.AccAddressFromBech32(user.FormattedAddress()) - s.Require().NoError(err) - - msgSubmitProposal, err := govtypesv1beta1.NewMsgSubmitProposal(content, sdk.NewCoins(sdk.NewCoin(chain.Config().Denom, govtypesv1beta1.DefaultMinDepositTokens)), sender) - s.Require().NoError(err) - - txResp := s.BroadcastMessages(ctx, chain, user, msgSubmitProposal) + txResp := s.ExecuteGovV1Beta1Proposal(ctx, chain, user, content) s.AssertTxSuccess(txResp) // TODO: replace with parsed proposal ID from MsgSubmitProposalResponse @@ -209,6 +203,17 @@ func (s *E2ETestSuite) ExecuteGovV1Beta1Proposal(ctx context.Context, chain *cos s.Require().Equal(govtypesv1beta1.StatusPassed, proposal.Status) } +// ExecuteGovV1Beta1Proposal submits a v1beta1 governance proposal using the provided content. +func (s *E2ETestSuite) ExecuteGovV1Beta1Proposal(ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, content govtypesv1beta1.Content) sdk.TxResponse { + sender, err := sdk.AccAddressFromBech32(user.FormattedAddress()) + s.Require().NoError(err) + + msgSubmitProposal, err := govtypesv1beta1.NewMsgSubmitProposal(content, sdk.NewCoins(sdk.NewCoin(chain.Config().Denom, govtypesv1beta1.DefaultMinDepositTokens)), sender) + s.Require().NoError(err) + + return s.BroadcastMessages(ctx, chain, user, msgSubmitProposal) +} + // Transfer broadcasts a MsgTransfer message. func (s *E2ETestSuite) Transfer(ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, portID, channelID string, token sdk.Coin, sender, receiver string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, memo string, diff --git a/modules/apps/29-fee/types/codec.go b/modules/apps/29-fee/types/codec.go index 51541f78b577..5d4dfbbcbd50 100644 --- a/modules/apps/29-fee/types/codec.go +++ b/modules/apps/29-fee/types/codec.go @@ -33,10 +33,10 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { var ( amino = codec.NewLegacyAmino() - // ModuleCdc references the global x/ibc-transfer module codec. Note, the codec + // ModuleCdc references the global x/ibc 29-fee module codec. Note, the codec // should ONLY be used in certain instances of tests and for JSON encoding. // - // The actual codec used for serialization should be provided to x/ibc transfer and + // The actual codec used for serialization should be provided to x/ibc 29-fee and // defined at the application level. ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) ) diff --git a/modules/core/03-connection/types/codec_test.go b/modules/core/03-connection/types/codec_test.go new file mode 100644 index 000000000000..ca1d5b7c7c28 --- /dev/null +++ b/modules/core/03-connection/types/codec_test.go @@ -0,0 +1,79 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + + ibc "github.com/cosmos/ibc-go/v8/modules/core" + "github.com/cosmos/ibc-go/v8/modules/core/03-connection/types" +) + +func TestCodecTypeRegistration(t *testing.T) { + testCases := []struct { + name string + typeURL string + expPass bool + }{ + { + "success: ConnectionEnd", + sdk.MsgTypeURL(&types.ConnectionEnd{}), + true, + }, + { + "success: Counterparty", + sdk.MsgTypeURL(&types.Counterparty{}), + true, + }, + { + "success: MsgConnectionOpenInit", + sdk.MsgTypeURL(&types.MsgConnectionOpenInit{}), + true, + }, + { + "success: MsgConnectionOpenTry", + sdk.MsgTypeURL(&types.MsgConnectionOpenTry{}), + true, + }, + { + "success: MsgConnectionOpenAck", + sdk.MsgTypeURL(&types.MsgConnectionOpenAck{}), + true, + }, + { + "success: MsgConnectionOpenConfirm", + sdk.MsgTypeURL(&types.MsgConnectionOpenConfirm{}), + true, + }, + { + "success: MsgUpdateParams", + sdk.MsgTypeURL(&types.MsgUpdateParams{}), + true, + }, + { + "type not registered on codec", + "ibc.invalid.MsgTypeURL", + false, + }, + } + + for _, tc := range testCases { + tc := tc + + t.Run(tc.name, func(t *testing.T) { + encodingCfg := moduletestutil.MakeTestEncodingConfig(ibc.AppModuleBasic{}) + msg, err := encodingCfg.Codec.InterfaceRegistry().Resolve(tc.typeURL) + + if tc.expPass { + require.NotNil(t, msg) + require.NoError(t, err) + } else { + require.Nil(t, msg) + require.Error(t, err) + } + }) + } +} diff --git a/modules/core/04-channel/types/codec_test.go b/modules/core/04-channel/types/codec_test.go new file mode 100644 index 000000000000..9122a95df0ae --- /dev/null +++ b/modules/core/04-channel/types/codec_test.go @@ -0,0 +1,109 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + + ibc "github.com/cosmos/ibc-go/v8/modules/core" + "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" +) + +func TestCodecTypeRegistration(t *testing.T) { + testCases := []struct { + name string + typeURL string + expPass bool + }{ + { + "success: Channel", + sdk.MsgTypeURL(&types.Channel{}), + true, + }, + { + "success: Counterparty", + sdk.MsgTypeURL(&types.Counterparty{}), + true, + }, + { + "success: Packet", + sdk.MsgTypeURL(&types.Packet{}), + true, + }, + { + "success: MsgChannelOpenInit", + sdk.MsgTypeURL(&types.MsgChannelOpenInit{}), + true, + }, + { + "success: MsgChannelOpenTry", + sdk.MsgTypeURL(&types.MsgChannelOpenTry{}), + true, + }, + { + "success: MsgChannelOpenAck", + sdk.MsgTypeURL(&types.MsgChannelOpenAck{}), + true, + }, + { + "success: MsgChannelOpenConfirm", + sdk.MsgTypeURL(&types.MsgChannelOpenConfirm{}), + true, + }, + { + "success: MsgChannelCloseInit", + sdk.MsgTypeURL(&types.MsgChannelCloseInit{}), + true, + }, + { + "success: MsgChannelCloseConfirm", + sdk.MsgTypeURL(&types.MsgChannelCloseConfirm{}), + true, + }, + { + "success: MsgRecvPacket", + sdk.MsgTypeURL(&types.MsgRecvPacket{}), + true, + }, + { + "success: MsgAcknowledgement", + sdk.MsgTypeURL(&types.MsgAcknowledgement{}), + true, + }, + { + "success: MsgTimeout", + sdk.MsgTypeURL(&types.MsgTimeout{}), + true, + }, + { + "success: MsgTimeoutOnClose", + sdk.MsgTypeURL(&types.MsgTimeoutOnClose{}), + true, + }, + { + "type not registered on codec", + "ibc.invalid.MsgTypeURL", + false, + }, + } + + for _, tc := range testCases { + tc := tc + + t.Run(tc.name, func(t *testing.T) { + encodingCfg := moduletestutil.MakeTestEncodingConfig(ibc.AppModuleBasic{}) + msg, err := encodingCfg.Codec.InterfaceRegistry().Resolve(tc.typeURL) + + if tc.expPass { + require.NotNil(t, msg) + require.NoError(t, err) + } else { + require.Nil(t, msg) + require.Error(t, err) + } + }) + } +} diff --git a/modules/core/23-commitment/types/codec_test.go b/modules/core/23-commitment/types/codec_test.go new file mode 100644 index 000000000000..88dc430b997d --- /dev/null +++ b/modules/core/23-commitment/types/codec_test.go @@ -0,0 +1,60 @@ +package types_test + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + + ibc "github.com/cosmos/ibc-go/v8/modules/core" + "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" +) + +func (suite *MerkleTestSuite) TestCodecTypeRegistration() { + testCases := []struct { + name string + typeURL string + expPass bool + }{ + { + "success: MerkleRoot", + sdk.MsgTypeURL(&types.MerkleRoot{}), + true, + }, + { + "success: MerklePrefix", + sdk.MsgTypeURL(&types.MerklePrefix{}), + true, + }, + { + "success: MerklePath", + sdk.MsgTypeURL(&types.MerklePath{}), + true, + }, + { + "success: MerkleProof", + sdk.MsgTypeURL(&types.MerkleProof{}), + true, + }, + { + "type not registered on codec", + "ibc.invalid.MsgTypeURL", + false, + }, + } + + for _, tc := range testCases { + tc := tc + + suite.Run(tc.name, func() { + encodingCfg := moduletestutil.MakeTestEncodingConfig(ibc.AppModuleBasic{}) + msg, err := encodingCfg.Codec.InterfaceRegistry().Resolve(tc.typeURL) + + if tc.expPass { + suite.Require().NotNil(msg) + suite.Require().NoError(err) + } else { + suite.Require().Nil(msg) + suite.Require().Error(err) + } + }) + } +} diff --git a/modules/light-clients/06-solomachine/codec_test.go b/modules/light-clients/06-solomachine/codec_test.go new file mode 100644 index 000000000000..966ad2365baf --- /dev/null +++ b/modules/light-clients/06-solomachine/codec_test.go @@ -0,0 +1,63 @@ +package solomachine_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + + solomachine "github.com/cosmos/ibc-go/v8/modules/light-clients/06-solomachine" +) + +func TestCodecTypeRegistration(t *testing.T) { + testCases := []struct { + name string + typeURL string + expPass bool + }{ + { + "success: ClientState", + sdk.MsgTypeURL(&solomachine.ClientState{}), + true, + }, + { + "success: ConsensusState", + sdk.MsgTypeURL(&solomachine.ConsensusState{}), + true, + }, + { + "success: Header", + sdk.MsgTypeURL(&solomachine.Header{}), + true, + }, + { + "success: Misbehaviour", + sdk.MsgTypeURL(&solomachine.Misbehaviour{}), + true, + }, + { + "type not registered on codec", + "ibc.invalid.MsgTypeURL", + false, + }, + } + + for _, tc := range testCases { + tc := tc + + t.Run(tc.name, func(t *testing.T) { + encodingCfg := moduletestutil.MakeTestEncodingConfig(solomachine.AppModuleBasic{}) + msg, err := encodingCfg.Codec.InterfaceRegistry().Resolve(tc.typeURL) + + if tc.expPass { + require.NotNil(t, msg) + require.NoError(t, err) + } else { + require.Nil(t, msg) + require.Error(t, err) + } + }) + } +} diff --git a/modules/light-clients/07-tendermint/codec_test.go b/modules/light-clients/07-tendermint/codec_test.go new file mode 100644 index 000000000000..f139e0ac39f0 --- /dev/null +++ b/modules/light-clients/07-tendermint/codec_test.go @@ -0,0 +1,63 @@ +package tendermint_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + + tendermint "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" +) + +func TestCodecTypeRegistration(t *testing.T) { + testCases := []struct { + name string + typeURL string + expPass bool + }{ + { + "success: ClientState", + sdk.MsgTypeURL(&tendermint.ClientState{}), + true, + }, + { + "success: ConsensusState", + sdk.MsgTypeURL(&tendermint.ConsensusState{}), + true, + }, + { + "success: Header", + sdk.MsgTypeURL(&tendermint.Header{}), + true, + }, + { + "success: Misbehaviour", + sdk.MsgTypeURL(&tendermint.Misbehaviour{}), + true, + }, + { + "type not registered on codec", + "ibc.invalid.MsgTypeURL", + false, + }, + } + + for _, tc := range testCases { + tc := tc + + t.Run(tc.name, func(t *testing.T) { + encodingCfg := moduletestutil.MakeTestEncodingConfig(tendermint.AppModuleBasic{}) + msg, err := encodingCfg.Codec.InterfaceRegistry().Resolve(tc.typeURL) + + if tc.expPass { + require.NotNil(t, msg) + require.NoError(t, err) + } else { + require.Nil(t, msg) + require.Error(t, err) + } + }) + } +} diff --git a/modules/light-clients/09-localhost/codec_test.go b/modules/light-clients/09-localhost/codec_test.go new file mode 100644 index 000000000000..5b90faf2160e --- /dev/null +++ b/modules/light-clients/09-localhost/codec_test.go @@ -0,0 +1,49 @@ +package localhost_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + + ibc "github.com/cosmos/ibc-go/v8/modules/core" + localhost "github.com/cosmos/ibc-go/v8/modules/light-clients/09-localhost" +) + +func TestCodecTypeRegistration(t *testing.T) { + testCases := []struct { + name string + typeURL string + expPass bool + }{ + { + "success: ClientState", + sdk.MsgTypeURL(&localhost.ClientState{}), + true, + }, + { + "type not registered on codec", + "ibc.invalid.MsgTypeURL", + false, + }, + } + + for _, tc := range testCases { + tc := tc + + t.Run(tc.name, func(t *testing.T) { + encodingCfg := moduletestutil.MakeTestEncodingConfig(ibc.AppModuleBasic{}) + msg, err := encodingCfg.Codec.InterfaceRegistry().Resolve(tc.typeURL) + + if tc.expPass { + require.NotNil(t, msg) + require.NoError(t, err) + } else { + require.Nil(t, msg) + require.Error(t, err) + } + }) + } +}