diff --git a/modules/core/04-channel/keeper/keeper.go b/modules/core/04-channel/keeper/keeper.go index db81e134084..02f2ffec2f2 100644 --- a/modules/core/04-channel/keeper/keeper.go +++ b/modules/core/04-channel/keeper/keeper.go @@ -22,6 +22,7 @@ import ( "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" porttypes "github.com/cosmos/ibc-go/v9/modules/core/05-port/types" host "github.com/cosmos/ibc-go/v9/modules/core/24-host" + hostv2 "github.com/cosmos/ibc-go/v9/modules/core/24-host/v2" "github.com/cosmos/ibc-go/v9/modules/core/exported" ) @@ -138,9 +139,10 @@ func (k *Keeper) SetNextChannelSequence(ctx context.Context, sequence uint64) { } // GetNextSequenceSend gets a channel's next send sequence from the store +// NOTE: portID is now ignored in key to use same key as v2. However this API remains unchanged func (k *Keeper) GetNextSequenceSend(ctx context.Context, portID, channelID string) (uint64, bool) { store := k.storeService.OpenKVStore(ctx) - bz, err := store.Get(host.NextSequenceSendKey(portID, channelID)) + bz, err := store.Get(hostv2.NextSequenceSendKey(channelID)) if err != nil { panic(err) } @@ -152,10 +154,11 @@ func (k *Keeper) GetNextSequenceSend(ctx context.Context, portID, channelID stri } // SetNextSequenceSend sets a channel's next send sequence to the store +// NOTE: portID is now ignored in key to use same key as v2. However this API remains unchanged func (k *Keeper) SetNextSequenceSend(ctx context.Context, portID, channelID string, sequence uint64) { store := k.storeService.OpenKVStore(ctx) bz := sdk.Uint64ToBigEndian(sequence) - if err := store.Set(host.NextSequenceSendKey(portID, channelID), bz); err != nil { + if err := store.Set(hostv2.NextSequenceSendKey(channelID), bz); err != nil { panic(err) } } @@ -335,15 +338,18 @@ func (k *Keeper) IteratePacketSequence(ctx context.Context, iterator db.Iterator } } -// GetAllPacketSendSeqs returns all stored next send sequences. func (k *Keeper) GetAllPacketSendSeqs(ctx context.Context) (seqs []types.PacketSequence) { store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) - iterator := storetypes.KVStorePrefixIterator(store, []byte(host.KeyNextSeqSendPrefix)) - k.IteratePacketSequence(ctx, iterator, func(portID, channelID string, nextSendSeq uint64) bool { - ps := types.NewPacketSequence(portID, channelID, nextSendSeq) + iterator := storetypes.KVStorePrefixIterator(store, []byte(hostv2.NextSequenceSendKeyPrefix)) + defer sdk.LogDeferred(k.Logger(ctx), func() error { return iterator.Close() }) + for ; iterator.Valid(); iterator.Next() { + channelID := string(iterator.Key()[len(hostv2.NextSequenceSendKeyPrefix):]) + + sequence := sdk.BigEndianToUint64(iterator.Value()) + + ps := types.NewPacketSequence("", channelID, sequence) seqs = append(seqs, ps) - return false - }) + } return seqs } diff --git a/modules/core/04-channel/keeper/keeper_test.go b/modules/core/04-channel/keeper/keeper_test.go index bd46d702312..c43f11ec065 100644 --- a/modules/core/04-channel/keeper/keeper_test.go +++ b/modules/core/04-channel/keeper/keeper_test.go @@ -274,9 +274,14 @@ func (suite *KeeperTestSuite) TestGetAllSequences() { suite.Len(recvSeqs, 2) suite.Len(ackSeqs, 2) - suite.Equal(expSeqs, sendSeqs) suite.Equal(expSeqs, recvSeqs) suite.Equal(expSeqs, ackSeqs) + + expSendSeqs := []types.PacketSequence{} + for _, es := range expSeqs { + expSendSeqs = append(expSendSeqs, types.NewPacketSequence("", es.ChannelId, es.Sequence)) + } + suite.Equal(expSendSeqs, sendSeqs) } // TestGetAllPacketState creates a set of acks, packet commitments, and receipts on two different diff --git a/modules/core/04-channel/keeper/migrations.go b/modules/core/04-channel/keeper/migrations.go index 9a382d26265..e4178ac02c6 100644 --- a/modules/core/04-channel/keeper/migrations.go +++ b/modules/core/04-channel/keeper/migrations.go @@ -1,9 +1,13 @@ package keeper import ( + storetypes "cosmossdk.io/store/types" + + "github.com/cosmos/cosmos-sdk/runtime" sdk "github.com/cosmos/cosmos-sdk/types" channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" + host "github.com/cosmos/ibc-go/v9/modules/core/24-host" ) // Migrator is a struct for handling in-place store migrations. @@ -23,3 +27,14 @@ func (m Migrator) MigrateParams(ctx sdk.Context) error { m.keeper.Logger(ctx).Info("successfully migrated ibc channel params") return nil } + +// MigrateNextSequenceSend migrates the nextSequenceSend storage from the v1 to v2 format +func (m Migrator) MigrateNextSequenceSend(ctx sdk.Context) error { + store := runtime.KVStoreAdapter(m.keeper.storeService.OpenKVStore(ctx)) + iterator := storetypes.KVStorePrefixIterator(store, []byte(host.KeyNextSeqSendPrefix)) + m.keeper.IteratePacketSequence(ctx, iterator, func(portID, channelID string, nextSendSeq uint64) bool { + m.keeper.SetNextSequenceSend(ctx, portID, channelID, nextSendSeq) + return false + }) + return nil +} diff --git a/modules/core/04-channel/keeper/migrations_test.go b/modules/core/04-channel/keeper/migrations_test.go index 1d2af1baa3e..cce05b72549 100644 --- a/modules/core/04-channel/keeper/migrations_test.go +++ b/modules/core/04-channel/keeper/migrations_test.go @@ -1,19 +1,23 @@ package keeper_test import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/ibc-go/v9/modules/core/04-channel/keeper" - channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" + "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" + host "github.com/cosmos/ibc-go/v9/modules/core/24-host" + "github.com/cosmos/ibc-go/v9/modules/core/exported" ) // TestMigrateDefaultParams tests the migration for the channel params func (suite *KeeperTestSuite) TestMigrateDefaultParams() { testCases := []struct { name string - expectedParams channeltypes.Params + expectedParams types.Params }{ { "success: default params", - channeltypes.DefaultParams(), + types.DefaultParams(), }, } @@ -32,3 +36,38 @@ func (suite *KeeperTestSuite) TestMigrateDefaultParams() { }) } } + +// TestMigrateNextSequenceSend will test the migration from the v1 NextSeqSend keys +// to the v2 format. +func (suite *KeeperTestSuite) TestMigrateNextSequenceSend() { + seq1 := types.NewPacketSequence("transfer", "channel-0", 1) + seq2 := types.NewPacketSequence("mock", "channel-2", 2) + seq3 := types.NewPacketSequence("ica", "channel-4", 3) + + expSeqs := []types.PacketSequence{seq1, seq2, seq3} + + store := suite.chainA.GetContext().KVStore(suite.chainA.GetSimApp().GetKey(exported.StoreKey)) + for _, es := range expSeqs { + bz := sdk.Uint64ToBigEndian(es.Sequence) + store.Set(host.NextSequenceSendKey(es.PortId, es.ChannelId), bz) + } + + k := suite.chainA.GetSimApp().IBCKeeper.ChannelKeeper + + ctx := suite.chainA.GetContext() + seqs := k.GetAllPacketSendSeqs(ctx) + suite.Require().Equal([]types.PacketSequence(nil), seqs, "sequences already exist in correct key format") + + migrator := keeper.NewMigrator(k) + + err := migrator.MigrateNextSequenceSend(ctx) + suite.Require().NoError(err) + + expV2Seqs := []types.PacketSequence{} + for _, es := range expSeqs { + expV2Seqs = append(expV2Seqs, types.NewPacketSequence("", es.ChannelId, es.Sequence)) + } + + seqs = k.GetAllPacketSendSeqs(ctx) + suite.Require().Equal(expV2Seqs, seqs, "new sequence keys not stored correctly") +} diff --git a/modules/core/04-channel/keeper/upgrade_test.go b/modules/core/04-channel/keeper/upgrade_test.go index 8565f12a195..a87181c4498 100644 --- a/modules/core/04-channel/keeper/upgrade_test.go +++ b/modules/core/04-channel/keeper/upgrade_test.go @@ -13,6 +13,7 @@ import ( "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" commitmenttypes "github.com/cosmos/ibc-go/v9/modules/core/23-commitment/types" host "github.com/cosmos/ibc-go/v9/modules/core/24-host" + hostv2 "github.com/cosmos/ibc-go/v9/modules/core/24-host/v2" "github.com/cosmos/ibc-go/v9/modules/core/exported" ibctesting "github.com/cosmos/ibc-go/v9/testing" "github.com/cosmos/ibc-go/v9/testing/mock" @@ -2249,7 +2250,7 @@ func (suite *KeeperTestSuite) TestStartFlush() { func() { // Delete next sequence send key from store store := suite.chainB.GetContext().KVStore(suite.chainB.GetSimApp().GetKey(exported.StoreKey)) - store.Delete(host.NextSequenceSendKey(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)) + store.Delete(hostv2.NextSequenceSendKey(path.EndpointB.ChannelID)) }, types.ErrSequenceSendNotFound, }, diff --git a/modules/core/24-host/v2/packet_keys.go b/modules/core/24-host/v2/packet_keys.go index 03f15a858d5..8611f85d328 100644 --- a/modules/core/24-host/v2/packet_keys.go +++ b/modules/core/24-host/v2/packet_keys.go @@ -1,11 +1,13 @@ package v2 import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" ) +const ( + NextSequenceSendKeyPrefix = "nextSequenceSendV2/" +) + // PacketCommitmentPrefixKey returns the store key prefix under which packet commitments for a particular channel are stored. // channelID must be a generated identifier, not provided externally so key collisions are not possible. func PacketCommitmentPrefixKey(channelID string) []byte { @@ -44,5 +46,5 @@ func PacketAcknowledgementKey(channelID string, sequence uint64) []byte { // NextSequenceSendKey returns the store key for the next sequence send of a given channelID. func NextSequenceSendKey(channelID string) []byte { - return []byte(fmt.Sprintf("nextSequenceSend/%s", channelID)) + return append([]byte(NextSequenceSendKeyPrefix), []byte(channelID)...) }