diff --git a/.github/workflows/callbacks.yml b/.github/workflows/callbacks.yml index ba5deb99eac..36574a9d368 100644 --- a/.github/workflows/callbacks.yml +++ b/.github/workflows/callbacks.yml @@ -16,7 +16,7 @@ jobs: with: go-version: '1.21' - uses: actions/checkout@v4 - - uses: golangci/golangci-lint-action@v5.3.0 + - uses: golangci/golangci-lint-action@v6.0.1 with: version: v1.57.2 args: --timeout 5m diff --git a/.github/workflows/e2emodule.yml b/.github/workflows/e2emodule.yml index 5b03d2b7d4a..782de0bc1ab 100644 --- a/.github/workflows/e2emodule.yml +++ b/.github/workflows/e2emodule.yml @@ -14,7 +14,7 @@ jobs: with: go-version: '1.21' - uses: actions/checkout@v4 - - uses: golangci/golangci-lint-action@v5.3.0 + - uses: golangci/golangci-lint-action@v6.0.1 with: version: v1.57.2 args: --timeout 5m diff --git a/.github/workflows/golangci-feature.yml b/.github/workflows/golangci-feature.yml index f769b7384f3..ed629b6789c 100644 --- a/.github/workflows/golangci-feature.yml +++ b/.github/workflows/golangci-feature.yml @@ -25,7 +25,7 @@ jobs: go-version: '1.21' - uses: actions/checkout@v4 - name: golangci-lint - uses: golangci/golangci-lint-action@v5.3.0 + uses: golangci/golangci-lint-action@v6.0.1 with: version: v1.57.2 args: --timeout 10m diff --git a/.github/workflows/golangci.yml b/.github/workflows/golangci.yml index f24bb6f2abd..fb45c2b0fd6 100644 --- a/.github/workflows/golangci.yml +++ b/.github/workflows/golangci.yml @@ -20,7 +20,7 @@ jobs: go-version: '1.21' - uses: actions/checkout@v4 - name: golangci-lint - uses: golangci/golangci-lint-action@v5.3.0 + uses: golangci/golangci-lint-action@v6.0.1 with: version: v1.57.2 args: --timeout 10m diff --git a/.github/workflows/wasm-client.yml b/.github/workflows/wasm-client.yml index 800b7757ed0..884bd4d33a7 100644 --- a/.github/workflows/wasm-client.yml +++ b/.github/workflows/wasm-client.yml @@ -16,7 +16,7 @@ jobs: with: go-version: '1.21' - uses: actions/checkout@v4 - - uses: golangci/golangci-lint-action@v5.3.0 + - uses: golangci/golangci-lint-action@v6.0.1 with: version: v1.57.2 args: --timeout 10m diff --git a/CHANGELOG.md b/CHANGELOG.md index 34a61ca83da..ddd5a2a6210 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements * (apps/27-interchain-accounts) [\#5533](https://github.com/cosmos/ibc-go/pull/5533) ICA host sets the host connection ID on `OnChanOpenTry`, so that ICA controller implementations are not obliged to set the value on `OnChanOpenInit` if they are not able. +* (core/02-client, core/03-connection, apps/27-interchain-accounts) [\#6256](https://github.com/cosmos/ibc-go/pull/6256) Add length checking of array fields in messages. * (apps/27-interchain-accounts, apps/tranfer, apps/29-fee) [\#6253](https://github.com/cosmos/ibc-go/pull/6253) Allow channel handshake to succeed if fee middleware is wired up on one side, but not the other. ### Features @@ -68,6 +69,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes * (apps/27-interchain-accounts) [\#6167](https://github.com/cosmos/ibc-go/pull/6167) Fixed an edge case bug where migrating params for a pre-existing ica module which implemented controller functionality only could panic when migrating params for newly added host, and align controller param migration with host. +* (app/29-fee) [\#6255](https://github.com/cosmos/ibc-go/pull/6255) Delete refunded fees from state if some fee(s) cannot be refunded on channel closure. ## [v8.2.0](https://github.com/cosmos/ibc-go/releases/tag/v8.2.0) - 2024-04-05 diff --git a/e2e/go.mod b/e2e/go.mod index c6d207ba292..5938c61a4c4 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -28,7 +28,7 @@ require ( cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v1.1.6 // indirect cloud.google.com/go/storage v1.36.0 // indirect - cosmossdk.io/api v0.7.4 // indirect + cosmossdk.io/api v0.7.5 // indirect cosmossdk.io/client/v2 v2.0.0-beta.1 // indirect cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/core v0.11.0 // indirect @@ -242,7 +242,7 @@ require ( google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect - google.golang.org/protobuf v1.34.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/e2e/go.sum b/e2e/go.sum index f3752830089..60810d55a61 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -184,8 +184,8 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/api v0.7.4 h1:sPo8wKwCty1lht8kgL3J7YL1voJywP3YWuA5JKkBz30= -cosmossdk.io/api v0.7.4/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= +cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= cosmossdk.io/client/v2 v2.0.0-beta.1 h1:XkHh1lhrLYIT9zKl7cIOXUXg2hdhtjTPBUfqERNA1/Q= cosmossdk.io/client/v2 v2.0.0-beta.1/go.mod h1:JEUSu9moNZQ4kU3ir1DKD5eU4bllmAexrGWjmb9k8qU= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= @@ -1749,8 +1749,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= -google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/go.mod b/go.mod index e4352f51ace..98eecc76171 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ go 1.21 module github.com/cosmos/ibc-go/v8 require ( - cosmossdk.io/api v0.7.4 + cosmossdk.io/api v0.7.5 cosmossdk.io/client/v2 v2.0.0-beta.1 cosmossdk.io/core v0.11.0 cosmossdk.io/errors v1.0.1 @@ -32,7 +32,7 @@ require ( github.com/stretchr/testify v1.9.0 google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de google.golang.org/grpc v1.63.2 - google.golang.org/protobuf v1.34.0 + google.golang.org/protobuf v1.34.1 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index d58148a5502..ce10cfe9eb8 100644 --- a/go.sum +++ b/go.sum @@ -184,8 +184,8 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/api v0.7.4 h1:sPo8wKwCty1lht8kgL3J7YL1voJywP3YWuA5JKkBz30= -cosmossdk.io/api v0.7.4/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= +cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= cosmossdk.io/client/v2 v2.0.0-beta.1 h1:XkHh1lhrLYIT9zKl7cIOXUXg2hdhtjTPBUfqERNA1/Q= cosmossdk.io/client/v2 v2.0.0-beta.1/go.mod h1:JEUSu9moNZQ4kU3ir1DKD5eU4bllmAexrGWjmb9k8qU= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= @@ -1664,8 +1664,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= -google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/modules/apps/27-interchain-accounts/controller/keeper/migrations.go b/modules/apps/27-interchain-accounts/controller/keeper/migrations.go index 77f62a73c5d..3e36f809a14 100644 --- a/modules/apps/27-interchain-accounts/controller/keeper/migrations.go +++ b/modules/apps/27-interchain-accounts/controller/keeper/migrations.go @@ -29,24 +29,23 @@ func NewMigrator(k *Keeper) Migrator { // are owned by the controller submodule and ibc. func (m Migrator) AssertChannelCapabilityMigrations(ctx sdk.Context) error { if m.keeper != nil { - logger := m.keeper.Logger(ctx) filteredChannels := m.keeper.channelKeeper.GetAllChannelsWithPortPrefix(ctx, icatypes.ControllerPortPrefix) for _, ch := range filteredChannels { name := host.ChannelCapabilityPath(ch.PortId, ch.ChannelId) capability, found := m.keeper.scopedKeeper.GetCapability(ctx, name) if !found { - logger.Error(fmt.Sprintf("failed to find capability: %s", name)) + m.keeper.Logger(ctx).Error(fmt.Sprintf("failed to find capability: %s", name)) return errorsmod.Wrapf(capabilitytypes.ErrCapabilityNotFound, "failed to find capability: %s", name) } isAuthenticated := m.keeper.scopedKeeper.AuthenticateCapability(ctx, capability, name) if !isAuthenticated { - logger.Error(fmt.Sprintf("expected capability owner: %s", controllertypes.SubModuleName)) + m.keeper.Logger(ctx).Error(fmt.Sprintf("expected capability owner: %s", controllertypes.SubModuleName)) return errorsmod.Wrapf(capabilitytypes.ErrCapabilityNotOwned, "expected capability owner: %s", controllertypes.SubModuleName) } m.keeper.SetMiddlewareEnabled(ctx, ch.PortId, ch.ConnectionHops[0]) - logger.Info("successfully migrated channel capability", "name", name) + m.keeper.Logger(ctx).Info("successfully migrated channel capability", "name", name) } } return nil diff --git a/modules/apps/27-interchain-accounts/host/ibc_module.go b/modules/apps/27-interchain-accounts/host/ibc_module.go index b5163393f67..3829a4c9acd 100644 --- a/modules/apps/27-interchain-accounts/host/ibc_module.go +++ b/modules/apps/27-interchain-accounts/host/ibc_module.go @@ -116,9 +116,8 @@ func (im IBCModule) OnRecvPacket( packet channeltypes.Packet, _ sdk.AccAddress, ) ibcexported.Acknowledgement { - logger := im.keeper.Logger(ctx) if !im.keeper.GetParams(ctx).HostEnabled { - logger.Info("host submodule is disabled") + im.keeper.Logger(ctx).Info("host submodule is disabled") keeper.EmitHostDisabledEvent(ctx, packet) return channeltypes.NewErrorAcknowledgement(types.ErrHostSubModuleDisabled) } @@ -127,9 +126,9 @@ func (im IBCModule) OnRecvPacket( ack := channeltypes.NewResultAcknowledgement(txResponse) if err != nil { ack = channeltypes.NewErrorAcknowledgement(err) - logger.Error(fmt.Sprintf("%s sequence %d", err.Error(), packet.Sequence)) + im.keeper.Logger(ctx).Error(fmt.Sprintf("%s sequence %d", err.Error(), packet.Sequence)) } else { - logger.Info("successfully handled packet", "sequence", packet.Sequence) + im.keeper.Logger(ctx).Info("successfully handled packet", "sequence", packet.Sequence) } // Emit an event indicating a successful or failed acknowledgement. diff --git a/modules/apps/27-interchain-accounts/host/keeper/handshake.go b/modules/apps/27-interchain-accounts/host/keeper/handshake.go index 2ec9dc8afbd..0613b8f32cf 100644 --- a/modules/apps/27-interchain-accounts/host/keeper/handshake.go +++ b/modules/apps/27-interchain-accounts/host/keeper/handshake.go @@ -30,7 +30,6 @@ func (k Keeper) OnChanOpenTry( counterparty channeltypes.Counterparty, counterpartyVersion string, ) (string, error) { - logger := k.Logger(ctx) if portID != icatypes.HostPortID { return "", errorsmod.Wrapf(icatypes.ErrInvalidHostPort, "expected %s, got %s", icatypes.HostPortID, portID) } @@ -43,7 +42,7 @@ func (k Keeper) OnChanOpenTry( return "", errorsmod.Wrapf(err, "failed to retrieve connection %s", connectionHops[0]) } - logger.Debug("counterparty version is invalid, proposing default metadata") + k.Logger(ctx).Debug("counterparty version is invalid, proposing default metadata") metadata = icatypes.NewDefaultMetadata(connection.Counterparty.ConnectionId, connectionHops[0]) } diff --git a/modules/apps/27-interchain-accounts/host/types/params.go b/modules/apps/27-interchain-accounts/host/types/params.go index 5c47fe65487..cb2fd40fa29 100644 --- a/modules/apps/27-interchain-accounts/host/types/params.go +++ b/modules/apps/27-interchain-accounts/host/types/params.go @@ -9,6 +9,8 @@ import ( const ( // DefaultHostEnabled is the default value for the host param (set to true) DefaultHostEnabled = true + // Maximum length of the allowlist + MaxAllowListLength = 500 ) // NewParams creates a new parameter configuration for the host submodule @@ -30,6 +32,10 @@ func (p Params) Validate() error { } func validateAllowlist(allowMsgs []string) error { + if len(allowMsgs) > MaxAllowListLength { + return fmt.Errorf("allow list length must not exceed %d items", MaxAllowListLength) + } + if slices.Contains(allowMsgs, AllowAllHostMsgs) && len(allowMsgs) > 1 { return fmt.Errorf("allow list must have only one element because the allow all host messages wildcard (%s) is present", AllowAllHostMsgs) } diff --git a/modules/apps/27-interchain-accounts/host/types/params_test.go b/modules/apps/27-interchain-accounts/host/types/params_test.go index 9cd7b46bc45..bc443707ba4 100644 --- a/modules/apps/27-interchain-accounts/host/types/params_test.go +++ b/modules/apps/27-interchain-accounts/host/types/params_test.go @@ -14,4 +14,5 @@ func TestValidateParams(t *testing.T) { require.Error(t, types.NewParams(true, []string{""}).Validate()) require.Error(t, types.NewParams(true, []string{" "}).Validate()) require.Error(t, types.NewParams(true, []string{"*", "/cosmos.bank.v1beta1.MsgSend"}).Validate()) + require.Error(t, types.NewParams(true, make([]string, types.MaxAllowListLength+1)).Validate()) } diff --git a/modules/apps/29-fee/keeper/escrow.go b/modules/apps/29-fee/keeper/escrow.go index c3bb9c8fefa..1ebbeb95caa 100644 --- a/modules/apps/29-fee/keeper/escrow.go +++ b/modules/apps/29-fee/keeper/escrow.go @@ -189,7 +189,7 @@ func (k Keeper) RefundFeesOnChannelClosure(ctx sdk.Context, portID, channelID st cacheCtx, writeFn := ctx.CacheContext() for _, identifiedPacketFee := range identifiedPacketFees { - var failedToSendCoins bool + var unRefundedFees []types.PacketFee for _, packetFee := range identifiedPacketFee.PacketFees { if !k.EscrowAccountHasBalance(cacheCtx, packetFee.Fee.Total()) { @@ -207,18 +207,22 @@ func (k Keeper) RefundFeesOnChannelClosure(ctx sdk.Context, portID, channelID st refundAddr, err := sdk.AccAddressFromBech32(packetFee.RefundAddress) if err != nil { - failedToSendCoins = true + unRefundedFees = append(unRefundedFees, packetFee) continue } // refund all fees to refund address if err = k.bankKeeper.SendCoinsFromModuleToAccount(cacheCtx, types.ModuleName, refundAddr, packetFee.Fee.Total()); err != nil { - failedToSendCoins = true + unRefundedFees = append(unRefundedFees, packetFee) continue } } - if !failedToSendCoins { + if len(unRefundedFees) > 0 { + // update packet fees to keep only the unrefunded fees + packetFees := types.NewPacketFees(unRefundedFees) + k.SetFeesInEscrow(cacheCtx, identifiedPacketFee.PacketId, packetFees) + } else { k.DeleteFeesInEscrow(cacheCtx, identifiedPacketFee.PacketId) } } diff --git a/modules/apps/29-fee/keeper/escrow_test.go b/modules/apps/29-fee/keeper/escrow_test.go index f0d6233d23f..8aa0840784c 100644 --- a/modules/apps/29-fee/keeper/escrow_test.go +++ b/modules/apps/29-fee/keeper/escrow_test.go @@ -395,19 +395,17 @@ func (suite *KeeperTestSuite) TestDistributePacketFeesOnTimeout() { func (suite *KeeperTestSuite) TestRefundFeesOnChannelClosure() { var ( - expIdentifiedPacketFees []types.IdentifiedPacketFees - expEscrowBal sdk.Coins - expRefundBal sdk.Coins - refundAcc sdk.AccAddress - fee types.Fee - locked bool - expectEscrowFeesToBeDeleted bool + expIdentifiedPacketFees []types.IdentifiedPacketFees + expEscrowBal sdk.Coins + expRefundBal sdk.Coins + refundAcc sdk.AccAddress + fee types.Fee ) testCases := []struct { name string malleate func() - expPass bool + locked bool }{ { "success", func() { @@ -415,16 +413,13 @@ func (suite *KeeperTestSuite) TestRefundFeesOnChannelClosure() { // store the fee in state & update escrow account balance packetID := channeltypes.NewPacketID(suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, uint64(i)) packetFees := types.NewPacketFees([]types.PacketFee{types.NewPacketFee(fee, refundAcc.String(), nil)}) - identifiedPacketFees := types.NewIdentifiedPacketFees(packetID, packetFees.PacketFees) suite.chainA.GetSimApp().IBCFeeKeeper.SetFeesInEscrow(suite.chainA.GetContext(), packetID, packetFees) err := suite.chainA.GetSimApp().BankKeeper.SendCoinsFromAccountToModule(suite.chainA.GetContext(), refundAcc, types.ModuleName, fee.Total()) suite.Require().NoError(err) - - expIdentifiedPacketFees = append(expIdentifiedPacketFees, identifiedPacketFees) } - }, true, + }, false, }, { "success with undistributed packet fees on a different channel", func() { @@ -432,14 +427,10 @@ func (suite *KeeperTestSuite) TestRefundFeesOnChannelClosure() { // store the fee in state & update escrow account balance packetID := channeltypes.NewPacketID(suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, uint64(i)) packetFees := types.NewPacketFees([]types.PacketFee{types.NewPacketFee(fee, refundAcc.String(), nil)}) - identifiedPacketFees := types.NewIdentifiedPacketFees(packetID, packetFees.PacketFees) - suite.chainA.GetSimApp().IBCFeeKeeper.SetFeesInEscrow(suite.chainA.GetContext(), packetID, packetFees) err := suite.chainA.GetSimApp().BankKeeper.SendCoinsFromAccountToModule(suite.chainA.GetContext(), refundAcc, types.ModuleName, fee.Total()) suite.Require().NoError(err) - - expIdentifiedPacketFees = append(expIdentifiedPacketFees, identifiedPacketFees) } // set packet fee for a different channel @@ -453,12 +444,10 @@ func (suite *KeeperTestSuite) TestRefundFeesOnChannelClosure() { expEscrowBal = fee.Total() expRefundBal = expRefundBal.Sub(fee.Total()...) - }, true, + }, false, }, { "escrow account empty, module should become locked", func() { - locked = true - // store the fee in state without updating escrow account balance packetID := channeltypes.NewPacketID(suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, uint64(1)) packetFees := types.NewPacketFees([]types.PacketFee{types.NewPacketFee(fee, refundAcc.String(), nil)}) @@ -467,13 +456,10 @@ func (suite *KeeperTestSuite) TestRefundFeesOnChannelClosure() { suite.chainA.GetSimApp().IBCFeeKeeper.SetFeesInEscrow(suite.chainA.GetContext(), packetID, packetFees) expIdentifiedPacketFees = []types.IdentifiedPacketFees{identifiedPacketFees} - }, - true, + }, true, }, { "escrow account goes negative on second packet, module should become locked", func() { - locked = true - // store 2 fees in state packetID1 := channeltypes.NewPacketID(suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, uint64(1)) packetID2 := channeltypes.NewPacketID(suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, uint64(2)) @@ -494,42 +480,46 @@ func (suite *KeeperTestSuite) TestRefundFeesOnChannelClosure() { { "invalid refund acc address", func() { // store the fee in state & update escrow account balance - expectEscrowFeesToBeDeleted = false packetID := channeltypes.NewPacketID(suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, uint64(1)) - packetFees := types.NewPacketFees([]types.PacketFee{types.NewPacketFee(fee, "invalid refund address", nil)}) - identifiedPacketFees := types.NewIdentifiedPacketFees(packetID, packetFees.PacketFees) - + packetFees := types.NewPacketFees([]types.PacketFee{ + types.NewPacketFee(fee, refundAcc.String(), nil), // this packet fee will be refunded, and will be deleted from state + types.NewPacketFee(fee, "invalid refund address", nil), + }) suite.chainA.GetSimApp().IBCFeeKeeper.SetFeesInEscrow(suite.chainA.GetContext(), packetID, packetFees) - err := suite.chainA.GetSimApp().BankKeeper.SendCoinsFromAccountToModule(suite.chainA.GetContext(), refundAcc, types.ModuleName, fee.Total()) + // escrow twice the fee amount to account for the packet to have been incentivized twice + err := suite.chainA.GetSimApp().BankKeeper.SendCoinsFromAccountToModule(suite.chainA.GetContext(), refundAcc, types.ModuleName, fee.Total().MulInt(sdkmath.NewInt(2))) suite.Require().NoError(err) - expIdentifiedPacketFees = []types.IdentifiedPacketFees{identifiedPacketFees} + // only the first packet fee should be refunded, the second should remain in state + expIdentifiedPacketFees = []types.IdentifiedPacketFees{types.NewIdentifiedPacketFees(packetID, packetFees.PacketFees[1:])} expEscrowBal = fee.Total() expRefundBal = expRefundBal.Sub(fee.Total()...) - }, true, + }, false, }, { "distributing to blocked address is skipped", func() { - expectEscrowFeesToBeDeleted = false blockedAddr := suite.chainA.GetSimApp().AccountKeeper.GetModuleAccount(suite.chainA.GetContext(), transfertypes.ModuleName).GetAddress().String() // store the fee in state & update escrow account balance packetID := channeltypes.NewPacketID(suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, uint64(1)) - packetFees := types.NewPacketFees([]types.PacketFee{types.NewPacketFee(fee, blockedAddr, nil)}) - identifiedPacketFees := types.NewIdentifiedPacketFees(packetID, packetFees.PacketFees) - + packetFees := types.NewPacketFees([]types.PacketFee{ + types.NewPacketFee(fee, refundAcc.String(), nil), // this packet fee will be refunded, and will be deleted from state + types.NewPacketFee(fee, blockedAddr, nil), + }) suite.chainA.GetSimApp().IBCFeeKeeper.SetFeesInEscrow(suite.chainA.GetContext(), packetID, packetFees) - err := suite.chainA.GetSimApp().BankKeeper.SendCoinsFromAccountToModule(suite.chainA.GetContext(), refundAcc, types.ModuleName, fee.Total()) + // escrow twice the fee amount to account for the packet to have been incentivized twice + err := suite.chainA.GetSimApp().BankKeeper.SendCoinsFromAccountToModule(suite.chainA.GetContext(), refundAcc, types.ModuleName, fee.Total().MulInt(sdkmath.NewInt(2))) suite.Require().NoError(err) - expIdentifiedPacketFees = []types.IdentifiedPacketFees{identifiedPacketFees} + // only the first packet fee should be refunded, the second should remain in state + expIdentifiedPacketFees = []types.IdentifiedPacketFees{types.NewIdentifiedPacketFees(packetID, packetFees.PacketFees[1:])} expEscrowBal = fee.Total() expRefundBal = expRefundBal.Sub(fee.Total()...) - }, true, + }, false, }, } @@ -539,10 +529,8 @@ func (suite *KeeperTestSuite) TestRefundFeesOnChannelClosure() { suite.Run(tc.name, func() { suite.SetupTest() // reset suite.path.Setup() // setup channel - expIdentifiedPacketFees = []types.IdentifiedPacketFees{} + expIdentifiedPacketFees = []types.IdentifiedPacketFees(nil) expEscrowBal = sdk.Coins{} - locked = false - expectEscrowFeesToBeDeleted = true // setup refundAcc = suite.chainA.SenderAccount.GetAddress() @@ -565,32 +553,22 @@ func (suite *KeeperTestSuite) TestRefundFeesOnChannelClosure() { originalEscrowBal := suite.chainA.GetSimApp().BankKeeper.GetAllBalances(suite.chainA.GetContext(), moduleAcc) err := suite.chainA.GetSimApp().IBCFeeKeeper.RefundFeesOnChannelClosure(suite.chainA.GetContext(), suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID) + suite.Require().NoError(err) // refundAcc balance after RefundFeesOnChannelClosure refundBal := suite.chainA.GetSimApp().BankKeeper.GetAllBalances(suite.chainA.GetContext(), refundAcc) escrowBal := suite.chainA.GetSimApp().BankKeeper.GetAllBalances(suite.chainA.GetContext(), moduleAcc) - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } + suite.Require().Equal(tc.locked, suite.chainA.GetSimApp().IBCFeeKeeper.IsLocked(suite.chainA.GetContext())) + suite.Require().Equal(expIdentifiedPacketFees, suite.chainA.GetSimApp().IBCFeeKeeper.GetIdentifiedPacketFeesForChannel(suite.chainA.GetContext(), suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID)) - suite.Require().Equal(locked, suite.chainA.GetSimApp().IBCFeeKeeper.IsLocked(suite.chainA.GetContext())) - - if locked || !tc.expPass { + if tc.locked { // refund account and escrow account balances should remain unchanged suite.Require().Equal(originalRefundBal, refundBal) suite.Require().Equal(originalEscrowBal, escrowBal) - - // ensure none of the fees were deleted - suite.Require().Equal(expIdentifiedPacketFees, suite.chainA.GetSimApp().IBCFeeKeeper.GetIdentifiedPacketFeesForChannel(suite.chainA.GetContext(), suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID)) } else { suite.Require().Equal(expEscrowBal, escrowBal) // escrow balance should be empty suite.Require().Equal(expRefundBal, refundBal) // all packets should have been refunded - - // all fees in escrow should be deleted if expected for this channel - suite.Require().Equal(expectEscrowFeesToBeDeleted, len(suite.chainA.GetSimApp().IBCFeeKeeper.GetIdentifiedPacketFeesForChannel(suite.chainA.GetContext(), suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID)) == 0) } }) } diff --git a/modules/apps/callbacks/go.mod b/modules/apps/callbacks/go.mod index 863552939b3..11a6ce7d3b7 100644 --- a/modules/apps/callbacks/go.mod +++ b/modules/apps/callbacks/go.mod @@ -9,7 +9,7 @@ replace github.com/cosmos/ibc-go/v8 => ../../../ replace github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 require ( - cosmossdk.io/api v0.7.4 + cosmossdk.io/api v0.7.5 cosmossdk.io/client/v2 v2.0.0-beta.1 cosmossdk.io/core v0.11.0 cosmossdk.io/errors v1.0.1 @@ -196,7 +196,7 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect google.golang.org/grpc v1.63.2 // indirect - google.golang.org/protobuf v1.34.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/apps/callbacks/go.sum b/modules/apps/callbacks/go.sum index d58148a5502..ce10cfe9eb8 100644 --- a/modules/apps/callbacks/go.sum +++ b/modules/apps/callbacks/go.sum @@ -184,8 +184,8 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/api v0.7.4 h1:sPo8wKwCty1lht8kgL3J7YL1voJywP3YWuA5JKkBz30= -cosmossdk.io/api v0.7.4/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= +cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= cosmossdk.io/client/v2 v2.0.0-beta.1 h1:XkHh1lhrLYIT9zKl7cIOXUXg2hdhtjTPBUfqERNA1/Q= cosmossdk.io/client/v2 v2.0.0-beta.1/go.mod h1:JEUSu9moNZQ4kU3ir1DKD5eU4bllmAexrGWjmb9k8qU= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= @@ -1664,8 +1664,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= -google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/modules/apps/transfer/ibc_module.go b/modules/apps/transfer/ibc_module.go index 1424260f178..7e312b7b869 100644 --- a/modules/apps/transfer/ibc_module.go +++ b/modules/apps/transfer/ibc_module.go @@ -180,14 +180,13 @@ func (im IBCModule) OnRecvPacket( packet channeltypes.Packet, relayer sdk.AccAddress, ) ibcexported.Acknowledgement { - logger := im.keeper.Logger(ctx) ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) var data types.FungibleTokenPacketData var ackErr error if err := json.Unmarshal(packet.GetData(), &data); err != nil { ackErr = errorsmod.Wrapf(ibcerrors.ErrInvalidType, "cannot unmarshal ICS-20 transfer packet data") - logger.Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), packet.Sequence)) + im.keeper.Logger(ctx).Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), packet.Sequence)) ack = channeltypes.NewErrorAcknowledgement(ackErr) } @@ -198,9 +197,9 @@ func (im IBCModule) OnRecvPacket( if err != nil { ack = channeltypes.NewErrorAcknowledgement(err) ackErr = err - logger.Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), packet.Sequence)) + im.keeper.Logger(ctx).Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), packet.Sequence)) } else { - logger.Info("successfully handled ICS-20 packet", "sequence", packet.Sequence) + im.keeper.Logger(ctx).Info("successfully handled ICS-20 packet", "sequence", packet.Sequence) } } diff --git a/modules/apps/transfer/keeper/keeper.go b/modules/apps/transfer/keeper/keeper.go index 0ec4dac6abf..6ee9ee7edfe 100644 --- a/modules/apps/transfer/keeper/keeper.go +++ b/modules/apps/transfer/keeper/keeper.go @@ -105,7 +105,7 @@ func (k Keeper) hasCapability(ctx sdk.Context, portID string) bool { return ok } -// BindPort defines a wrapper function for the ort Keeper's function in +// BindPort defines a wrapper function for the port Keeper's function in // order to expose it to module's InitGenesis function func (k Keeper) BindPort(ctx sdk.Context, portID string) error { capability := k.portKeeper.BindPort(ctx, portID) diff --git a/modules/apps/transfer/simulation/genesis.go b/modules/apps/transfer/simulation/genesis.go index fded62be9a2..6887ec48bf1 100644 --- a/modules/apps/transfer/simulation/genesis.go +++ b/modules/apps/transfer/simulation/genesis.go @@ -15,8 +15,8 @@ import ( // Simulation parameter constants const port = "port_id" -// RadomEnabled randomized send or receive enabled param with 75% prob of being true. -func RadomEnabled(r *rand.Rand) bool { +// RandomEnabled randomized send or receive enabled param with 75% prob of being true. +func RandomEnabled(r *rand.Rand) bool { return r.Int63n(101) <= 75 } @@ -31,13 +31,13 @@ func RandomizedGenState(simState *module.SimulationState) { var sendEnabled bool simState.AppParams.GetOrGenerate( string(types.KeySendEnabled), &sendEnabled, simState.Rand, - func(r *rand.Rand) { sendEnabled = RadomEnabled(r) }, + func(r *rand.Rand) { sendEnabled = RandomEnabled(r) }, ) var receiveEnabled bool simState.AppParams.GetOrGenerate( string(types.KeyReceiveEnabled), &receiveEnabled, simState.Rand, - func(r *rand.Rand) { receiveEnabled = RadomEnabled(r) }, + func(r *rand.Rand) { receiveEnabled = RandomEnabled(r) }, ) transferGenesis := types.GenesisState{ diff --git a/modules/capability/go.mod b/modules/capability/go.mod index a1ebd56f413..a66ed1f3b01 100644 --- a/modules/capability/go.mod +++ b/modules/capability/go.mod @@ -20,7 +20,7 @@ require ( ) require ( - cosmossdk.io/api v0.7.4 // indirect + cosmossdk.io/api v0.7.5 // indirect cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect cosmossdk.io/x/tx v0.13.2 // indirect diff --git a/modules/capability/go.sum b/modules/capability/go.sum index ab4a2d16eb6..e88d7001d27 100644 --- a/modules/capability/go.sum +++ b/modules/capability/go.sum @@ -2,6 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/api v0.7.4 h1:sPo8wKwCty1lht8kgL3J7YL1voJywP3YWuA5JKkBz30= cosmossdk.io/api v0.7.4/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= +cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= cosmossdk.io/core v0.11.0 h1:vtIafqUi+1ZNAE/oxLOQQ7Oek2n4S48SWLG8h/+wdbo= @@ -111,8 +113,6 @@ github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cometbft/cometbft v0.38.6 h1:QSgpCzrGWJ2KUq1qpw+FCfASRpE27T6LQbfEHscdyOk= -github.com/cometbft/cometbft v0.38.6/go.mod h1:8rSPxzUJYquCN8uuBgbUHOMg2KAwvr7CyUw+6ukO4nw= github.com/cometbft/cometbft v0.38.7 h1:ULhIOJ9+LgSy6nLekhq9ae3juX3NnQUMMPyVdhZV6Hk= github.com/cometbft/cometbft v0.38.7/go.mod h1:HIyf811dFMI73IE0F7RrnY/Fr+d1+HuJAgtkEpQjCMY= github.com/cometbft/cometbft-db v0.9.1 h1:MIhVX5ja5bXNHF8EYrThkG9F7r9kSfv8BX4LWaxWJ4M= diff --git a/modules/core/02-client/types/params.go b/modules/core/02-client/types/params.go index da5ce32ff46..35001ea5cd9 100644 --- a/modules/core/02-client/types/params.go +++ b/modules/core/02-client/types/params.go @@ -6,6 +6,9 @@ import ( "strings" ) +// Maximum length of the allowed clients list +const MaxAllowedClientsLength = 200 + // DefaultAllowedClients are the default clients for the AllowedClients parameter. // By default it allows all client types. var DefaultAllowedClients = []string{AllowAllClients} @@ -46,6 +49,10 @@ func (p Params) IsAllowedClient(clientType string) bool { // validateClients checks that the given clients are not blank and there are no duplicates. // If AllowAllClients wildcard (*) is used, then there should no other client types in the allow list func validateClients(clients []string) error { + if len(clients) > MaxAllowedClientsLength { + return fmt.Errorf("allowed clients length must not exceed %d items", MaxAllowedClientsLength) + } + if slices.Contains(clients, AllowAllClients) && len(clients) > 1 { return fmt.Errorf("allow list must have only one element because the allow all clients wildcard (%s) is present", AllowAllClients) } diff --git a/modules/core/02-client/types/params_test.go b/modules/core/02-client/types/params_test.go index 347b913450f..7a80749b375 100644 --- a/modules/core/02-client/types/params_test.go +++ b/modules/core/02-client/types/params_test.go @@ -40,6 +40,7 @@ func TestValidateParams(t *testing.T) { {"blank client", NewParams(" "), false}, {"duplicate clients", NewParams(exported.Tendermint, exported.Tendermint), false}, {"allow all clients plus valid client", NewParams(AllowAllClients, exported.Tendermint), false}, + {"too many allowed clients", NewParams(make([]string, MaxAllowedClientsLength+1)...), false}, } for _, tc := range testCases { diff --git a/modules/core/03-connection/types/msgs.go b/modules/core/03-connection/types/msgs.go index 5b927af7347..43a45807ca6 100644 --- a/modules/core/03-connection/types/msgs.go +++ b/modules/core/03-connection/types/msgs.go @@ -129,6 +129,9 @@ func (msg MsgConnectionOpenTry) ValidateBasic() error { if len(msg.CounterpartyVersions) == 0 { return errorsmod.Wrap(ibcerrors.ErrInvalidVersion, "empty counterparty versions") } + if len(msg.CounterpartyVersions) > MaxCounterpartyVersionsLength { + return errorsmod.Wrapf(ibcerrors.ErrInvalidVersion, "counterparty versions must not exceed %d items", MaxCounterpartyVersionsLength) + } for i, version := range msg.CounterpartyVersions { if err := ValidateVersion(version); err != nil { return errorsmod.Wrapf(err, "basic validation failed on version with index %d", i) diff --git a/modules/core/03-connection/types/msgs_test.go b/modules/core/03-connection/types/msgs_test.go index 9106e3aa15f..e02b79db071 100644 --- a/modules/core/03-connection/types/msgs_test.go +++ b/modules/core/03-connection/types/msgs_test.go @@ -159,8 +159,10 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() { {"empty proofConsensus", types.NewMsgConnectionOpenTry("clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, emptyProof, clientHeight, clientHeight, signer), false}, {"invalid consensusHeight", types.NewMsgConnectionOpenTry("clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clienttypes.ZeroHeight(), signer), false}, {"empty singer", types.NewMsgConnectionOpenTry("clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ""), false}, - {"success", types.NewMsgConnectionOpenTry("clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), true}, {"invalid version", types.NewMsgConnectionOpenTry("clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{{}}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, + {"too many counterparty versions", types.NewMsgConnectionOpenTry("clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, make([]*types.Version, types.MaxCounterpartyVersionsLength+1), 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, + {"too many features in counterparty version", types.NewMsgConnectionOpenTry("clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{{"v1", make([]string, types.MaxFeaturesLength+1)}}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, + {"success", types.NewMsgConnectionOpenTry("clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), true}, } for _, tc := range testCases { diff --git a/modules/core/03-connection/types/version.go b/modules/core/03-connection/types/version.go index 00aadcb8682..c30c709277e 100644 --- a/modules/core/03-connection/types/version.go +++ b/modules/core/03-connection/types/version.go @@ -27,6 +27,11 @@ var ( allowNilFeatureSet = map[string]bool{ DefaultIBCVersionIdentifier: false, } + + // MaxVersionsLength is the maximum number of versions that can be supported + MaxCounterpartyVersionsLength = 100 + // MaxFeaturesLength is the maximum number of features that can be supported + MaxFeaturesLength = 100 ) // NewVersion returns a new instance of Version. @@ -56,6 +61,9 @@ func ValidateVersion(version *Version) error { if strings.TrimSpace(version.Identifier) == "" { return errorsmod.Wrap(ErrInvalidVersion, "version identifier cannot be blank") } + if len(version.Features) > MaxFeaturesLength { + return errorsmod.Wrapf(ErrInvalidVersion, "features length must not exceed %d items", MaxFeaturesLength) + } for i, feature := range version.Features { if strings.TrimSpace(feature) == "" { return errorsmod.Wrapf(ErrInvalidVersion, "feature cannot be blank, index %d", i) diff --git a/modules/light-clients/07-tendermint/migrations/migrations.go b/modules/light-clients/07-tendermint/migrations/migrations.go index 7eb6e91b1f2..eb80c602a46 100644 --- a/modules/light-clients/07-tendermint/migrations/migrations.go +++ b/modules/light-clients/07-tendermint/migrations/migrations.go @@ -40,8 +40,7 @@ func PruneExpiredConsensusStates(ctx sdk.Context, cdc codec.BinaryCodec, clientK totalPruned += ibctm.PruneAllExpiredConsensusStates(ctx, clientStore, cdc, tmClientState) } - clientLogger := clientKeeper.Logger(ctx) - clientLogger.Info("pruned expired tendermint consensus states", "total", totalPruned) + clientKeeper.Logger(ctx).Info("pruned expired tendermint consensus states", "total", totalPruned) return totalPruned, nil } diff --git a/modules/light-clients/08-wasm/go.mod b/modules/light-clients/08-wasm/go.mod index af3031e8d2a..7655ed57ba5 100644 --- a/modules/light-clients/08-wasm/go.mod +++ b/modules/light-clients/08-wasm/go.mod @@ -7,7 +7,7 @@ replace github.com/cosmos/ibc-go/v8 => ../../../ replace github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 require ( - cosmossdk.io/api v0.7.4 + cosmossdk.io/api v0.7.5 cosmossdk.io/client/v2 v2.0.0-beta.1 cosmossdk.io/collections v0.4.0 cosmossdk.io/core v0.11.0 @@ -195,7 +195,7 @@ require ( google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect - google.golang.org/protobuf v1.34.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/light-clients/08-wasm/go.sum b/modules/light-clients/08-wasm/go.sum index 1002e5c96fb..ae2a531382f 100644 --- a/modules/light-clients/08-wasm/go.sum +++ b/modules/light-clients/08-wasm/go.sum @@ -184,8 +184,8 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/api v0.7.4 h1:sPo8wKwCty1lht8kgL3J7YL1voJywP3YWuA5JKkBz30= -cosmossdk.io/api v0.7.4/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= +cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= cosmossdk.io/client/v2 v2.0.0-beta.1 h1:XkHh1lhrLYIT9zKl7cIOXUXg2hdhtjTPBUfqERNA1/Q= cosmossdk.io/client/v2 v2.0.0-beta.1/go.mod h1:JEUSu9moNZQ4kU3ir1DKD5eU4bllmAexrGWjmb9k8qU= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= @@ -1666,8 +1666,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= -google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=