Skip to content

Commit

Permalink
ibc/04-channel: import export GenesisState (#6087)
Browse files Browse the repository at this point in the history
* ibc/04-channel: import export GenesisState

* update tests

* add missing genesis fields

* genesis tests

* keeper tests

* update genesis test

* typo

* rename types

* address comments from review

* minor updates

* typo
  • Loading branch information
fedekunze committed Apr 29, 2020
1 parent 6469447 commit 2d3a852
Show file tree
Hide file tree
Showing 15 changed files with 603 additions and 59 deletions.
9 changes: 9 additions & 0 deletions x/ibc/04-channel/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var (
QuerierConnectionChannels = keeper.QuerierConnectionChannels
NewChannel = types.NewChannel
NewCounterparty = types.NewCounterparty
NewIdentifiedChannel = types.NewIdentifiedChannel
RegisterCodec = types.RegisterCodec
ErrChannelExists = types.ErrChannelExists
ErrChannelNotFound = types.ErrChannelNotFound
Expand All @@ -50,7 +51,11 @@ var (
NewMsgTimeout = types.NewMsgTimeout
NewMsgAcknowledgement = types.NewMsgAcknowledgement
NewPacket = types.NewPacket
NewPacketAckCommitment = types.NewPacketAckCommitment
NewPacketSequence = types.NewPacketSequence
NewChannelResponse = types.NewChannelResponse
DefaultGenesisState = types.DefaultGenesisState
NewGenesisState = types.NewGenesisState

// variable aliases
SubModuleCdc = types.SubModuleCdc
Expand All @@ -68,6 +73,7 @@ type (
Keeper = keeper.Keeper
Channel = types.Channel
Counterparty = types.Counterparty
IdentifiedChannel = types.IdentifiedChannel
ClientKeeper = types.ClientKeeper
ConnectionKeeper = types.ConnectionKeeper
PortKeeper = types.PortKeeper
Expand All @@ -82,4 +88,7 @@ type (
MsgTimeout = types.MsgTimeout
Packet = types.Packet
ChannelResponse = types.ChannelResponse
PacketAckCommitment = types.PacketAckCommitment
PacketSequence = types.PacketSequence
GenesisState = types.GenesisState
)
4 changes: 2 additions & 2 deletions x/ibc/04-channel/client/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ func QueryPacket(
return types.PacketResponse{}, err
}

destPortID := channelRes.Channel.Channel.Counterparty.PortID
destChannelID := channelRes.Channel.Channel.Counterparty.ChannelID
destPortID := channelRes.Channel.Counterparty.PortID
destChannelID := channelRes.Channel.Counterparty.ChannelID

packet := types.NewPacket(
res.Value,
Expand Down
37 changes: 37 additions & 0 deletions x/ibc/04-channel/genesis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package channel

import (
sdk "github.com/cosmos/cosmos-sdk/types"
)

// InitGenesis initializes the ibc channel submodule's state from a provided genesis
// state.
func InitGenesis(ctx sdk.Context, k Keeper, gs GenesisState) {
for _, channel := range gs.Channels {
ch := NewChannel(channel.State, channel.Ordering, channel.Counterparty, channel.ConnectionHops, channel.Version)
k.SetChannel(ctx, channel.PortID, channel.ID, ch)
}
for _, ack := range gs.Acknowledgements {
k.SetPacketAcknowledgement(ctx, ack.PortID, ack.ChannelID, ack.Sequence, ack.Hash)
}
for _, commitment := range gs.Commitments {
k.SetPacketCommitment(ctx, commitment.PortID, commitment.ChannelID, commitment.Sequence, commitment.Hash)
}
for _, ss := range gs.SendSequences {
k.SetNextSequenceSend(ctx, ss.PortID, ss.ChannelID, ss.Sequence)
}
for _, rs := range gs.RecvSequences {
k.SetNextSequenceRecv(ctx, rs.PortID, rs.ChannelID, rs.Sequence)
}
}

// ExportGenesis returns the ibc channel submodule's exported genesis.
func ExportGenesis(ctx sdk.Context, k Keeper) GenesisState {
return GenesisState{
Channels: k.GetAllChannels(ctx),
Acknowledgements: k.GetAllPacketAcks(ctx),
Commitments: k.GetAllPacketCommitments(ctx),
SendSequences: k.GetAllPacketSendSeqs(ctx),
RecvSequences: k.GetAllPacketRecvSeqs(ctx),
}
}
4 changes: 2 additions & 2 deletions x/ibc/04-channel/keeper/handshake.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,9 @@ func (k Keeper) ChanOpenAck(
}

// counterparty of the counterparty channel end (i.e self)
counterparty := types.NewCounterparty(portID, channelID)
expectedCounterparty := types.NewCounterparty(portID, channelID)
expectedChannel := types.NewChannel(
exported.TRYOPEN, channel.Ordering, counterparty,
exported.TRYOPEN, channel.Ordering, expectedCounterparty,
counterpartyHops, counterpartyVersion,
)

Expand Down
111 changes: 109 additions & 2 deletions x/ibc/04-channel/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ package keeper
import (
"encoding/binary"
"fmt"
"strconv"
"strings"

"github.com/tendermint/tendermint/libs/log"
db "github.com/tendermint/tm-db"

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -134,6 +137,90 @@ func (k Keeper) GetPacketAcknowledgement(ctx sdk.Context, portID, channelID stri
return bz, true
}

// IteratePacketSequence provides an iterator over all send and receive sequences. For each
// sequence, cb will be called. If the cb returns true, the iterator will close
// and stop.
func (k Keeper) IteratePacketSequence(ctx sdk.Context, send bool, cb func(portID, channelID string, sequence uint64) bool) {
store := ctx.KVStore(k.storeKey)
var iterator db.Iterator
if send {
iterator = sdk.KVStorePrefixIterator(store, []byte(ibctypes.KeyNextSeqSendPrefix))
} else {
iterator = sdk.KVStorePrefixIterator(store, []byte(ibctypes.KeyNextSeqRecvPrefix))
}

defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
keySplit := strings.Split(string(iterator.Key()), "/")
portID := keySplit[2]
channelID := keySplit[4]

sequence := sdk.BigEndianToUint64(iterator.Value())

if cb(portID, channelID, sequence) {
break
}
}
}

// GetAllPacketSendSeqs returns all stored next send sequences.
func (k Keeper) GetAllPacketSendSeqs(ctx sdk.Context) (seqs []types.PacketSequence) {
k.IteratePacketSequence(ctx, true, func(portID, channelID string, nextSendSeq uint64) bool {
ps := types.NewPacketSequence(portID, channelID, nextSendSeq)
seqs = append(seqs, ps)
return false
})
return seqs
}

// GetAllPacketRecvSeqs returns all stored next recv sequences.
func (k Keeper) GetAllPacketRecvSeqs(ctx sdk.Context) (seqs []types.PacketSequence) {
k.IteratePacketSequence(ctx, false, func(portID, channelID string, nextRecvSeq uint64) bool {
ps := types.NewPacketSequence(portID, channelID, nextRecvSeq)
seqs = append(seqs, ps)
return false
})
return seqs
}

// IteratePacketCommitment provides an iterator over all PacketCommitment objects. For each
// aknowledgement, cb will be called. If the cb returns true, the iterator will close
// and stop.
func (k Keeper) IteratePacketCommitment(ctx sdk.Context, cb func(portID, channelID string, sequence uint64, hash []byte) bool) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, []byte(ibctypes.KeyPacketCommitmentPrefix))
k.iterateHashes(ctx, iterator, cb)
}

// GetAllPacketCommitments returns all stored PacketCommitments objects.
func (k Keeper) GetAllPacketCommitments(ctx sdk.Context) (commitments []types.PacketAckCommitment) {
k.IteratePacketCommitment(ctx, func(portID, channelID string, sequence uint64, hash []byte) bool {
pc := types.NewPacketAckCommitment(portID, channelID, sequence, hash)
commitments = append(commitments, pc)
return false
})
return commitments
}

// IteratePacketAcknowledgement provides an iterator over all PacketAcknowledgement objects. For each
// aknowledgement, cb will be called. If the cb returns true, the iterator will close
// and stop.
func (k Keeper) IteratePacketAcknowledgement(ctx sdk.Context, cb func(portID, channelID string, sequence uint64, hash []byte) bool) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, []byte(ibctypes.KeyPacketAckPrefix))
k.iterateHashes(ctx, iterator, cb)
}

// GetAllPacketAcks returns all stored PacketAcknowledgements objects.
func (k Keeper) GetAllPacketAcks(ctx sdk.Context) (acks []types.PacketAckCommitment) {
k.IteratePacketAcknowledgement(ctx, func(portID, channelID string, sequence uint64, ack []byte) bool {
packetAck := types.NewPacketAckCommitment(portID, channelID, sequence, ack)
acks = append(acks, packetAck)
return false
})
return acks
}

// IterateChannels provides an iterator over all Channel objects. For each
// Channel, cb will be called. If the cb returns true, the iterator will close
// and stop.
Expand All @@ -145,9 +232,10 @@ func (k Keeper) IterateChannels(ctx sdk.Context, cb func(types.IdentifiedChannel
for ; iterator.Valid(); iterator.Next() {
var channel types.Channel
k.cdc.MustUnmarshalBinaryBare(iterator.Value(), &channel)
portID, channelID := ibctypes.MustParseChannelPath(string(iterator.Key()))

if cb(types.IdentifiedChannel{Channel: channel, PortIdentifier: portID, ChannelIdentifier: channelID}) {
portID, channelID := ibctypes.MustParseChannelPath(string(iterator.Key()))
identifiedChannel := types.NewIdentifiedChannel(portID, channelID, channel)
if cb(identifiedChannel) {
break
}
}
Expand All @@ -171,3 +259,22 @@ func (k Keeper) LookupModuleByChannel(ctx sdk.Context, portID, channelID string)

return ibctypes.GetModuleOwner(modules), cap, true
}

// common functionality for IteratePacketCommitment and IteratePacketAcknowledgemen
func (k Keeper) iterateHashes(ctx sdk.Context, iterator db.Iterator, cb func(portID, channelID string, sequence uint64, hash []byte) bool) {
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
keySplit := strings.Split(string(iterator.Key()), "/")
portID := keySplit[2]
channelID := keySplit[4]

sequence, err := strconv.ParseUint(keySplit[len(keySplit)-1], 10, 64)
if err != nil {
panic(err)
}

if cb(portID, channelID, sequence, iterator.Value()) {
break
}
}
}
104 changes: 68 additions & 36 deletions x/ibc/04-channel/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,11 @@ func (suite *KeeperTestSuite) TestSetChannel() {
_, found := suite.chainB.App.IBCKeeper.ChannelKeeper.GetChannel(ctx, testPort1, testChannel1)
suite.False(found)

channel := types.Channel{
State: exported.OPEN,
Ordering: testChannelOrder,
Counterparty: types.Counterparty{
PortID: testPort2,
ChannelID: testChannel2,
},
ConnectionHops: []string{testConnectionIDA},
Version: testChannelVersion,
}
counterparty2 := types.NewCounterparty(testPort2, testChannel2)
channel := types.NewChannel(
exported.INIT, testChannelOrder,
counterparty2, []string{testConnectionIDA}, testChannelVersion,
)
suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel(ctx, testPort1, testChannel1, channel)

storedChannel, found := suite.chainB.App.IBCKeeper.ChannelKeeper.GetChannel(ctx, testPort1, testChannel1)
Expand All @@ -98,37 +93,27 @@ func (suite KeeperTestSuite) TestGetAllChannels() {
counterparty2 := types.NewCounterparty(testPort2, testChannel2)
counterparty3 := types.NewCounterparty(testPort3, testChannel3)

channel1 := types.Channel{
State: exported.INIT,
Ordering: testChannelOrder,
Counterparty: counterparty3,
ConnectionHops: []string{testConnectionIDA},
Version: testChannelVersion,
}

channel2 := types.Channel{
State: exported.INIT,
Ordering: testChannelOrder,
Counterparty: counterparty1,
ConnectionHops: []string{testConnectionIDA},
Version: testChannelVersion,
}

channel3 := types.Channel{
State: exported.CLOSED,
Ordering: testChannelOrder,
Counterparty: counterparty2,
ConnectionHops: []string{testConnectionIDA},
Version: testChannelVersion,
}
channel1 := types.NewChannel(
exported.INIT, testChannelOrder,
counterparty3, []string{testConnectionIDA}, testChannelVersion,
)
channel2 := types.NewChannel(
exported.INIT, testChannelOrder,
counterparty1, []string{testConnectionIDA}, testChannelVersion,
)
channel3 := types.NewChannel(
exported.CLOSED, testChannelOrder,
counterparty2, []string{testConnectionIDA}, testChannelVersion,
)

expChannels := []types.IdentifiedChannel{
{Channel: channel1, PortIdentifier: testPort1, ChannelIdentifier: testChannel1},
{Channel: channel2, PortIdentifier: testPort2, ChannelIdentifier: testChannel2},
{Channel: channel3, PortIdentifier: testPort3, ChannelIdentifier: testChannel3},
types.NewIdentifiedChannel(testPort1, testChannel1, channel1),
types.NewIdentifiedChannel(testPort2, testChannel2, channel2),
types.NewIdentifiedChannel(testPort3, testChannel3, channel3),
}

ctx := suite.chainB.GetContext()

suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel(ctx, testPort1, testChannel1, channel1)
suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel(ctx, testPort2, testChannel2, channel2)
suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel(ctx, testPort3, testChannel3, channel3)
Expand All @@ -138,6 +123,53 @@ func (suite KeeperTestSuite) TestGetAllChannels() {
suite.Require().Equal(expChannels, channels)
}

func (suite KeeperTestSuite) TestGetAllSequences() {
seq1 := types.NewPacketSequence(testPort1, testChannel1, 1)
seq2 := types.NewPacketSequence(testPort2, testChannel2, 2)

expSeqs := []types.PacketSequence{seq1, seq2}

ctx := suite.chainB.GetContext()

for _, seq := range expSeqs {
suite.chainB.App.IBCKeeper.ChannelKeeper.SetNextSequenceSend(ctx, seq.PortID, seq.ChannelID, seq.Sequence)
suite.chainB.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(ctx, seq.PortID, seq.ChannelID, seq.Sequence)
}

sendSeqs := suite.chainB.App.IBCKeeper.ChannelKeeper.GetAllPacketSendSeqs(ctx)
recvSeqs := suite.chainB.App.IBCKeeper.ChannelKeeper.GetAllPacketRecvSeqs(ctx)
suite.Require().Len(sendSeqs, 2)
suite.Require().Len(recvSeqs, 2)

suite.Require().Equal(expSeqs, sendSeqs)
suite.Require().Equal(expSeqs, recvSeqs)
}

func (suite KeeperTestSuite) TestGetAllCommitmentsAcks() {
ack1 := types.NewPacketAckCommitment(testPort1, testChannel1, 1, []byte("ack"))
ack2 := types.NewPacketAckCommitment(testPort1, testChannel1, 2, []byte("ack"))
comm1 := types.NewPacketAckCommitment(testPort1, testChannel1, 1, []byte("hash"))
comm2 := types.NewPacketAckCommitment(testPort1, testChannel1, 2, []byte("hash"))

expAcks := []types.PacketAckCommitment{ack1, ack2}
expCommitments := []types.PacketAckCommitment{comm1, comm2}

ctx := suite.chainB.GetContext()

for i := 0; i < 2; i++ {
suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketAcknowledgement(ctx, expAcks[i].PortID, expAcks[i].ChannelID, expAcks[i].Sequence, expAcks[i].Hash)
suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(ctx, expCommitments[i].PortID, expCommitments[i].ChannelID, expCommitments[i].Sequence, expCommitments[i].Hash)
}

acks := suite.chainB.App.IBCKeeper.ChannelKeeper.GetAllPacketAcks(ctx)
commitments := suite.chainB.App.IBCKeeper.ChannelKeeper.GetAllPacketCommitments(ctx)
suite.Require().Len(acks, 2)
suite.Require().Len(commitments, 2)

suite.Require().Equal(expAcks, acks)
suite.Require().Equal(expCommitments, commitments)
}

func (suite *KeeperTestSuite) TestSetSequence() {
ctx := suite.chainB.GetContext()
_, found := suite.chainB.App.IBCKeeper.ChannelKeeper.GetNextSequenceSend(ctx, testPort1, testChannel1)
Expand Down
2 changes: 1 addition & 1 deletion x/ibc/04-channel/keeper/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func QuerierConnectionChannels(ctx sdk.Context, req abci.RequestQuery, k Keeper)

connectionChannels := []types.IdentifiedChannel{}
for _, channel := range channels {
if channel.Channel.ConnectionHops[0] == params.Connection {
if channel.ConnectionHops[0] == params.Connection {
connectionChannels = append(connectionChannels, channel)
}
}
Expand Down
Loading

0 comments on commit 2d3a852

Please sign in to comment.