diff --git a/.github/compatibility-test-matrices/release-v4.3.x/transfer-chain-a.json b/.github/compatibility-test-matrices/release-v4.3.x/transfer-chain-a.json index f4eaf8dff12..d800d545f2d 100644 --- a/.github/compatibility-test-matrices/release-v4.3.x/transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v4.3.x/transfer-chain-a.json @@ -1,6 +1,6 @@ { "chain-a": ["release-v4.3.x"], - "chain-b": ["release-v4.3.x", "v6.1.0", "v5.2.0", "4.2.0", "v4.1.1", "v3.4.0", "v3.3.1", "v2.5.0", "v2.4.2"], + "chain-b": ["release-v4.3.x", "v6.1.0", "v5.2.0", "v4.2.0", "v4.1.1", "v3.4.0", "v3.3.1", "v2.5.0", "v2.4.2"], "entrypoint": ["TestTransferTestSuite"], "test": [ "TestMsgTransfer_Succeeds_Nonincentivized", diff --git a/.github/compatibility-test-matrices/release-v4.3.x/transfer-chain-b.json b/.github/compatibility-test-matrices/release-v4.3.x/transfer-chain-b.json index 3f1931c21bc..b74bdca5249 100644 --- a/.github/compatibility-test-matrices/release-v4.3.x/transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v4.3.x/transfer-chain-b.json @@ -1,5 +1,5 @@ { - "chain-a": ["release-v4.3.x", "v6.1.0", "v5.2.0", "4.2.0", "v4.1.1", "v3.4.0", "v3.3.1", "v2.5.0", "v2.4.2"], + "chain-a": ["release-v4.3.x", "v6.1.0", "v5.2.0", "v4.2.0", "v4.1.1", "v3.4.0", "v3.3.1", "v2.5.0", "v2.4.2"], "chain-b": ["release-v4.3.x"], "entrypoint": ["TestTransferTestSuite"], "test": [ diff --git a/.github/compatibility-test-matrices/release-v7.0.x/transfer-authz-chain-a.json b/.github/compatibility-test-matrices/release-v7.0.x/transfer-authz-chain-a.json new file mode 100644 index 00000000000..7fca8e7535f --- /dev/null +++ b/.github/compatibility-test-matrices/release-v7.0.x/transfer-authz-chain-a.json @@ -0,0 +1,15 @@ +{ + "chain-a": ["release-v7.0.x"], + "chain-b": ["release-v7.0.x", "v6.1.0", "v5.2.0", "v4.2.0", "v4.1.1", "v3.4.0", "v3.3.1", "v2.5.0", "v2.4.2"], + "entrypoint": ["TestTransferTestSuite"], + "test": [ + "TestMsgTransfer_Succeeds_Nonincentivized", + "TestMsgTransfer_Fails_InvalidAddress", + "TestMsgTransfer_Timeout_Nonincentivized", + "TestMsgTransfer_WithMemo", + "TestSendEnabledParam", + "TestReceiveEnabledParam" + ], + "chain-binary": ["simd"], + "chain-image": ["ghcr.io/cosmos/ibc-go-simd"] +} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1487a58e44c..c87e3bca3ee 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -58,4 +58,4 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} build-args: | - IBC_GO_VERSION="${{ github.ref_name }}" + IBC_GO_VERSION=${{ github.ref_name }} diff --git a/e2e/semverutil/semver.go b/e2e/semverutil/semver.go index c630a1b2dad..a210289bad4 100644 --- a/e2e/semverutil/semver.go +++ b/e2e/semverutil/semver.go @@ -1,6 +1,8 @@ package semverutil import ( + "strings" + "golang.org/x/mod/semver" ) @@ -16,6 +18,17 @@ type FeatureReleases struct { // This is true if the version is greater than or equal to the major version it was released in // or is greater than or equal to the list of minor releases it was included in. func (fr FeatureReleases) IsSupported(versionStr string) bool { + + // in our compatibility tests, our images are in the format of "release-v1.0.x". We want to actually look at + // the "1.0.x" part but we also need this to be a valid version. We can change it to "1.0.0" + // TODO: change the way we provide the ibc-go version. This should be done in a more flexible way such + // as docker labels/metadata instead of the tag, as this will only work for our versioning scheme. + const releasePrefix = "release-" + if strings.HasPrefix(versionStr, releasePrefix) { + versionStr = versionStr[len(releasePrefix):] + versionStr = strings.ReplaceAll(versionStr, "x", "0") + } + // assume any non-semantic version formatted version supports the feature // this will be useful during development of the e2e test with the new feature if !semver.IsValid(versionStr) { diff --git a/e2e/testconfig/testconfig.go b/e2e/testconfig/testconfig.go index fcd7e262caf..6c96c5942ba 100644 --- a/e2e/testconfig/testconfig.go +++ b/e2e/testconfig/testconfig.go @@ -9,11 +9,13 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module/testutil" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" - gogoproto "github.com/cosmos/gogoproto/proto" "github.com/strangelove-ventures/interchaintest/v7/ibc" + tmjson "github.com/tendermint/tendermint/libs/json" + tmtypes "github.com/tendermint/tendermint/types" "github.com/cosmos/ibc-go/e2e/semverutil" "github.com/cosmos/ibc-go/e2e/testvalues" @@ -165,6 +167,7 @@ func DefaultChainOptions() ChainOptions { // newDefaultSimappConfig creates an ibc configuration for simd. func newDefaultSimappConfig(cc ChainConfig, name, chainID, denom string) ibc.ChainConfig { + return ibc.ChainConfig{ Type: "cosmos", Name: name, @@ -183,33 +186,66 @@ func newDefaultSimappConfig(cc ChainConfig, name, chainID, denom string) ibc.Cha GasAdjustment: 1.3, TrustingPeriod: "508h", NoHostMount: false, - ModifyGenesis: defaultModifyGenesis(), + ModifyGenesis: getGenesisModificationFunction(cc), } } +// getGenesisModificationFunction returns a genesis modification function that handles the GenesisState type +// correctly depending on if the govv1beta1 gov module is used or if govv1 is being used. +func getGenesisModificationFunction(cc ChainConfig) func(ibc.ChainConfig, []byte) ([]byte, error) { + version := cc.Tag + + if govGenesisFeatureReleases.IsSupported(version) { + return defaultGovv1ModifyGenesis() + } + + return defaultGovv1Beta1ModifyGenesis() +} + // govGenesisFeatureReleases represents the releases the governance module genesis // was upgraded from v1beta1 to v1. var govGenesisFeatureReleases = semverutil.FeatureReleases{ MajorVersion: "v7", } -// defaultModifyGenesis will only modify governance params to ensure the voting period and minimum deposit +// defaultGovv1ModifyGenesis will only modify governance params to ensure the voting period and minimum deposit // are functional for e2e testing purposes. -// Note: this function intentionally does not use the type defined here https://github.com/tendermint/tendermint/blob/v0.37.0-rc2/types/genesis.go#L38-L46 -// and uses a map[string]interface{} instead. -// This approach prevents the field block.TimeIotaMs from being lost which happened when using the GenesisDoc type from tendermint version v0.37.0. -// ibctest performs the following steps when creating the genesis.json file for chains. -// - 1. Let the chain binary create its own genesis file. -// - 2. Apply any provided functions to modify the bytes of the file. -// - 3. Overwrite the file with the new contents. -// This is a problem because when the tendermint types change, marshalling into the type will cause us to lose -// values if the types have changed in between the version of the chain in the test and the version of tendermint -// imported by the e2e tests. -// By using a raw map[string]interface{} we preserve the values unknown to the e2e tests and can still change -// the values we care about. -// TODO: handle these genesis modifications in a way which is type safe and does not require us to rely on -// map[string]interface{} -func defaultModifyGenesis() func(ibc.ChainConfig, []byte) ([]byte, error) { +func defaultGovv1ModifyGenesis() func(ibc.ChainConfig, []byte) ([]byte, error) { + return func(chainConfig ibc.ChainConfig, genbz []byte) ([]byte, error) { + genDoc, err := tmtypes.GenesisDocFromJSON(genbz) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal genesis bytes into genesis doc: %w", err) + } + + var appState genutiltypes.AppMap + if err := json.Unmarshal(genDoc.AppState, &appState); err != nil { + return nil, fmt.Errorf("failed to unmarshal genesis bytes into app state: %w", err) + } + + govGenBz, err := modifyGovAppState(chainConfig, appState[govtypes.ModuleName]) + if err != nil { + return nil, err + } + + appState[govtypes.ModuleName] = govGenBz + + genDoc.AppState, err = json.Marshal(appState) + if err != nil { + return nil, err + } + + bz, err := tmjson.MarshalIndent(genDoc, "", " ") + if err != nil { + return nil, err + } + + return bz, nil + } +} + +// defaultGovv1Beta1ModifyGenesis will only modify governance params to ensure the voting period and minimum deposit +// // are functional for e2e testing purposes. +func defaultGovv1Beta1ModifyGenesis() func(ibc.ChainConfig, []byte) ([]byte, error) { const appStateKey = "app_state" return func(chainConfig ibc.ChainConfig, genbz []byte) ([]byte, error) { genesisDocMap := map[string]interface{}{} @@ -228,7 +264,7 @@ func defaultModifyGenesis() func(ibc.ChainConfig, []byte) ([]byte, error) { return nil, fmt.Errorf("failed to extract gov genesis bytes: %s", err) } - govModuleGenesisBytes, err := modifyGovAppState(chainConfig, govModuleBytes) + govModuleGenesisBytes, err := modifyGovv1Beta1AppState(chainConfig, govModuleBytes) if err != nil { return nil, err } @@ -251,41 +287,50 @@ func defaultModifyGenesis() func(ibc.ChainConfig, []byte) ([]byte, error) { } } -// modifyGovAppState takes the existing gov app state and marshals it to either a govv1 GenesisState -// or a govv1beta1 GenesisState depending on the simapp version. +// modifyGovAppState takes the existing gov app state and marshals it to a govv1 GenesisState. func modifyGovAppState(chainConfig ibc.ChainConfig, govAppState []byte) ([]byte, error) { cfg := testutil.MakeTestEncodingConfig() cdc := codec.NewProtoCodec(cfg.InterfaceRegistry) govv1.RegisterInterfaces(cfg.InterfaceRegistry) - govv1beta1.RegisterInterfaces(cfg.InterfaceRegistry) - shouldUseGovV1 := govGenesisFeatureReleases.IsSupported(chainConfig.Images[0].Version) - - var govGenesisState gogoproto.Message - if shouldUseGovV1 { - govGenesisState = &govv1.GenesisState{} - } else { - govGenesisState = &govv1beta1.GenesisState{} - } + govGenesisState := &govv1.GenesisState{} if err := cdc.UnmarshalJSON(govAppState, govGenesisState); err != nil { return nil, fmt.Errorf("failed to unmarshal genesis bytes into gov genesis state: %w", err) } - switch v := govGenesisState.(type) { - case *govv1.GenesisState: - if v.Params == nil { - v.Params = &govv1.Params{} - } - // set correct minimum deposit using configured denom - v.Params.MinDeposit = sdk.NewCoins(sdk.NewCoin(chainConfig.Denom, govv1beta1.DefaultMinDepositTokens)) - vp := testvalues.VotingPeriod - v.Params.VotingPeriod = &vp - case *govv1beta1.GenesisState: - v.DepositParams.MinDeposit = sdk.NewCoins(sdk.NewCoin(chainConfig.Denom, govv1beta1.DefaultMinDepositTokens)) - v.VotingParams.VotingPeriod = testvalues.VotingPeriod + if govGenesisState.Params == nil { + govGenesisState.Params = &govv1.Params{} + } + + govGenesisState.Params.MinDeposit = sdk.NewCoins(sdk.NewCoin(chainConfig.Denom, govv1beta1.DefaultMinDepositTokens)) + vp := testvalues.VotingPeriod + govGenesisState.Params.VotingPeriod = &vp + + govGenBz, err := cdc.MarshalJSON(govGenesisState) + if err != nil { + return nil, fmt.Errorf("failed to marshal gov genesis state: %w", err) } + + return govGenBz, nil +} + +// modifyGovv1Beta1AppState takes the existing gov app state and marshals it to a govv1beta1 GenesisState. +func modifyGovv1Beta1AppState(chainConfig ibc.ChainConfig, govAppState []byte) ([]byte, error) { + cfg := testutil.MakeTestEncodingConfig() + + cdc := codec.NewProtoCodec(cfg.InterfaceRegistry) + govv1beta1.RegisterInterfaces(cfg.InterfaceRegistry) + + govGenesisState := &govv1beta1.GenesisState{} + if err := cdc.UnmarshalJSON(govAppState, govGenesisState); err != nil { + return nil, fmt.Errorf("failed to unmarshal genesis bytes into govv1beta1 genesis state: %w", err) + } + + govGenesisState.DepositParams.MinDeposit = sdk.NewCoins(sdk.NewCoin(chainConfig.Denom, govv1beta1.DefaultMinDepositTokens)) + govGenesisState.VotingParams.VotingPeriod = testvalues.VotingPeriod + govGenBz, err := cdc.MarshalJSON(govGenesisState) if err != nil { return nil, fmt.Errorf("failed to marshal gov genesis state: %w", err) diff --git a/e2e/testsuite/testsuite.go b/e2e/testsuite/testsuite.go index 05fb56232ba..23558bae5e4 100644 --- a/e2e/testsuite/testsuite.go +++ b/e2e/testsuite/testsuite.go @@ -32,6 +32,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "github.com/cosmos/ibc-go/e2e/semverutil" "github.com/cosmos/ibc-go/e2e/testconfig" "github.com/cosmos/ibc-go/e2e/testvalues" controllertypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/controller/types" @@ -496,6 +497,11 @@ func (s *E2ETestSuite) ExecuteGovProposal(ctx context.Context, chain *cosmos.Cos s.Require().Equal(govtypesv1beta1.StatusPassed, proposal.Status) } +// govv1ProposalTitleAndSummary represents the releases that support the new title and summary fields. +var govv1ProposalTitleAndSummary = semverutil.FeatureReleases{ + MajorVersion: "v7", +} + // ExecuteGovProposalV1 submits a 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) ExecuteGovProposalV1(ctx context.Context, msg sdk.Msg, chain *cosmos.CosmosChain, user ibc.Wallet, proposalID uint64) { @@ -506,6 +512,11 @@ func (s *E2ETestSuite) ExecuteGovProposalV1(ctx context.Context, msg sdk.Msg, ch msgSubmitProposal, err := govtypesv1.NewMsgSubmitProposal(msgs, sdk.NewCoins(sdk.NewCoin(chain.Config().Denom, govtypesv1.DefaultMinDepositTokens)), sender.String(), "", fmt.Sprintf("e2e gov proposal: %d", proposalID), fmt.Sprintf("executing gov proposal %d", proposalID)) s.Require().NoError(err) + if !govv1ProposalTitleAndSummary.IsSupported(chain.Nodes()[0].Image.Version) { + msgSubmitProposal.Title = "" + msgSubmitProposal.Summary = "" + } + resp, err := s.BroadcastMessages(ctx, chain, user, msgSubmitProposal) s.AssertValidTxResponse(resp) s.Require().NoError(err)