Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/e2e-upgrade.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ jobs:
upgrade-plan: v10,
test: TestV8ToV10ChainUpgrade_Localhost
},
{
tag: v10.3.0,
upgrade-plan: v11,
test: TestV10ToV11ChainUpgrade
},
]
steps:
- uses: actions/checkout@v5
Expand Down
2 changes: 2 additions & 0 deletions e2e/ci-e2e-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,7 @@ upgrades:
tag: "v8.1.0"
- planName: "v10"
tag: "v10.3.0"
- planName: "v11"
tag: "v11.0.0"
- planName: "ibcwasm-v8"
tag: "v8.0.0-e2e-upgrade"
95 changes: 95 additions & 0 deletions e2e/tests/upgrades/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,101 @@ func (s *UpgradeTestSuite) TestV8ToV10ChainUpgrade_Localhost() {
})
}

// TestV10ToV11ChainUpgrade will test that an upgrade from a v10 ibc-go binary to a v11 ibc-go binary is successful
// and that the v11 migration properly migrates the channel store to support IBC v2 for all OPEN UNORDERED channels.
func (s *UpgradeTestSuite) TestV10ToV11ChainUpgrade() {
t := s.T()
testCfg := testsuite.LoadConfig()
ctx := context.Background()

testName := t.Name()

chainA, chainB := s.GetChains()

s.CreatePaths(ibc.DefaultClientOpts(), s.TransferChannelOptions(), testName)
relayer := s.GetRelayerForTest(testName)
channelA := s.GetChannelBetweenChains(testName, chainA, chainB)

chainADenom := chainA.Config().Denom
chainBDenom := chainB.Config().Denom

chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)
chainAAddress := chainAWallet.FormattedAddress()

chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount)
chainBAddress := chainBWallet.FormattedAddress()

chainAIBCToken := testsuite.GetIBCToken(chainBDenom, channelA.PortID, channelA.ChannelID)
chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID)

s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks")

t.Run("start relayer", func(t *testing.T) {
s.StartRelayer(relayer, testName)
})

t.Run("transfer native tokens from chainA to chainB", func(t *testing.T) {
transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "")
s.AssertTxSuccess(transferTxResp)

s.AssertPacketRelayed(ctx, chainA, channelA.PortID, channelA.ChannelID, 1)

actualBalance, err := query.Balance(ctx, chainB, chainBAddress, chainBIBCToken.IBCDenom())
s.Require().NoError(err)

expected := testvalues.IBCTransferAmount
s.Require().Equal(expected, actualBalance.Int64())
})

t.Run("transfer native tokens from chainB to chainA", func(t *testing.T) {
transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, testvalues.DefaultTransferAmount(chainBDenom), chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA.(*cosmos.CosmosChain)), 0, "")
s.AssertTxSuccess(transferTxResp)

s.AssertPacketRelayed(ctx, chainA, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, 1)

actualBalance, err := query.Balance(ctx, chainA, chainAAddress, chainAIBCToken.IBCDenom())
s.Require().NoError(err)

expected := testvalues.IBCTransferAmount
s.Require().Equal(expected, actualBalance.Int64())
})

s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA), "failed to wait for blocks")

t.Run("stop relayer", func(t *testing.T) {
s.StopRelayer(ctx, relayer)
})

t.Run("upgrade chain", func(t *testing.T) {
govProposalWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)
s.UpgradeChain(ctx, chainA.(*cosmos.CosmosChain), govProposalWallet, testCfg.GetUpgradeConfig().PlanName, testCfg.ChainConfigs[0].Tag, testCfg.GetUpgradeConfig().Tag)
})

t.Run("start relayer", func(t *testing.T) {
s.StartRelayer(relayer, testName)
})

t.Run("query denoms after upgrade", func(t *testing.T) {
resp, err := query.TransferDenoms(ctx, chainA)
s.Require().NoError(err)
s.Require().Len(resp.Denoms, 1)
s.Require().Equal(chainAIBCToken, resp.Denoms[0])
})

t.Run("IBC token transfer from chainA to chainB, to make sure the upgrade did not break the packet flow", func(t *testing.T) {
transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "")
s.AssertTxSuccess(transferTxResp)

s.AssertPacketRelayed(ctx, chainA, channelA.PortID, channelA.ChannelID, 2)

actualBalance, err := chainB.GetBalance(ctx, chainBAddress, chainBIBCToken.IBCDenom())
s.Require().NoError(err)

expected := testvalues.IBCTransferAmount * 2
s.Require().Equal(expected, actualBalance.Int64())
})
}

// ClientState queries the current ClientState by clientID
func (*UpgradeTestSuite) ClientState(ctx context.Context, chain ibc.Chain, clientID string) (*clienttypes.QueryClientStateResponse, error) {
res, err := query.GRPCQuery[clienttypes.QueryClientStateResponse](ctx, chain, &clienttypes.QueryClientStateRequest{ClientId: clientID})
Expand Down
23 changes: 23 additions & 0 deletions simapp/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
storetypes "cosmossdk.io/store/types"
circuittypes "cosmossdk.io/x/circuit/types"
upgradetypes "cosmossdk.io/x/upgrade/types"
packetforwardtypes "github.com/cosmos/ibc-go/v10/modules/apps/packet-forward-middleware/types"
ratelimitingtypes "github.com/cosmos/ibc-go/v10/modules/apps/rate-limiting/types"

"github.com/cosmos/ibc-go/simapp/upgrades"
)
Expand Down Expand Up @@ -34,6 +36,15 @@ func (app *SimApp) registerUpgradeHandlers() {
),
)

app.UpgradeKeeper.SetUpgradeHandler(
upgrades.V11,
upgrades.CreateV11UpgradeHandler(
app.ModuleManager,
app.configurator,
app,
),
)

upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk()
if err != nil {
panic(err)
Expand All @@ -48,4 +59,16 @@ func (app *SimApp) registerUpgradeHandlers() {
// configure store loader that checks if version == upgradeHeight and applies store upgrades
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades))
}

if upgradeInfo.Name == upgrades.V11 && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
storeUpgrades := storetypes.StoreUpgrades{
Added: []string{
packetforwardtypes.ModuleName,
ratelimitingtypes.ModuleName,
},
}
// configure store loader that checks if version == upgradeHeight and applies store upgrades
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades))
}

}
58 changes: 58 additions & 0 deletions simapp/upgrades/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@ package upgrades

import (
"context"
"fmt"

storetypes "cosmossdk.io/store/types"
upgradetypes "cosmossdk.io/x/upgrade/types"
"github.com/cosmos/cosmos-sdk/runtime"

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
v11 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/migrations/v11"
ibcexported "github.com/cosmos/ibc-go/v10/modules/core/exported"
ibckeeper "github.com/cosmos/ibc-go/v10/modules/core/keeper"
)

const (
Expand All @@ -15,6 +23,8 @@ const (
V8_1 = "v8.1"
// V10 defines the upgrade name for the ibc-go/v10 upgrade handler.
V10 = "v10"
// V11 defines the upgrade name for the ibc-go/v11 upgrade handler.
V11 = "v11"
)

// CreateDefaultUpgradeHandler creates an upgrade handler which can be used for regular upgrade tests
Expand All @@ -27,3 +37,51 @@ func CreateDefaultUpgradeHandler(
return mm.RunMigrations(ctx, configurator, vm)
}
}

// CreateV11UpgradeHandler creates an upgrade handler for v11 that includes IBC sequence migration
func CreateV11UpgradeHandler(
mm *module.Manager,
configurator module.Configurator,
app interface{},
) upgradetypes.UpgradeHandler {
return func(ctx context.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
// Run module migrations
vm, err := mm.RunMigrations(ctx, configurator, vm)
if err != nil {
return vm, fmt.Errorf("failed to run module migrations: %w", err)
}

// Perform IBC v11 migration
if err := performIBCV11Migration(ctx, app); err != nil {
return vm, fmt.Errorf("failed to perform IBC v11 migration: %w", err)
}

return vm, nil
}
}

// performIBCV11Migration performs the IBC v11 sequence migration
func performIBCV11Migration(ctx context.Context, app interface{}) error {
// Type assertion to get the app methods we need
simApp, ok := app.(interface {
GetIBCKeeper() *ibckeeper.Keeper
AppCodec() codec.Codec
GetKey(moduleName string) *storetypes.KVStoreKey
})
if !ok {
return fmt.Errorf("invalid app type for IBC migration")
}

// Get the store service
storeService := runtime.NewKVStoreService(simApp.GetKey(ibcexported.StoreKey))

// Try to perform the migration
err := v11.MigrateStore(
sdk.UnwrapSDKContext(ctx),
storeService,
simApp.AppCodec(),
simApp.GetIBCKeeper(),
)

return err
}
Loading