ibc/04-channel: import export GenesisState (#6087)

* 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
This commit is contained in:
Federico Kunze 2020-04-29 09:17:20 -04:00 committed by GitHub
parent 6469447d52
commit 2d3a8525b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 603 additions and 59 deletions

View File

@ -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
@ -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
@ -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
@ -82,4 +88,7 @@ type (
MsgTimeout = types.MsgTimeout
Packet = types.Packet
ChannelResponse = types.ChannelResponse
PacketAckCommitment = types.PacketAckCommitment
PacketSequence = types.PacketSequence
GenesisState = types.GenesisState
)

View File

@ -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,

View File

@ -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),
}
}

View File

@ -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,
)

View File

@ -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"
@ -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.
@ -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
}
}
@ -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
}
}
}

View File

@ -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)
@ -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)
@ -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)

View File

@ -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)
}
}

View File

@ -20,8 +20,8 @@ type Channel struct {
// NewChannel creates a new Channel instance
func NewChannel(
state exported.State, ordering exported.Order, counterparty Counterparty,
hops []string, version string,
state exported.State, ordering exported.Order,
counterparty Counterparty, hops []string, version string,
) Channel {
return Channel{
State: state,
@ -126,3 +126,40 @@ func (c Counterparty) ValidateBasic() error {
}
return nil
}
// IdentifiedChannel defines a channel with additional port and channel identifier
// fields.
type IdentifiedChannel struct {
ID string `json:"id" yaml:"id"`
PortID string `json:"port_id" yaml:"port_id"`
State exported.State `json:"state" yaml:"state"`
Ordering exported.Order `json:"ordering" yaml:"ordering"`
Counterparty Counterparty `json:"counterparty" yaml:"counterparty"`
ConnectionHops []string `json:"connection_hops" yaml:"connection_hops"`
Version string `json:"version" yaml:"version "`
}
// NewIdentifiedChannel creates a new IdentifiedChannel instance
func NewIdentifiedChannel(portID, channelID string, ch Channel) IdentifiedChannel {
return IdentifiedChannel{
ID: channelID,
PortID: portID,
State: ch.State,
Ordering: ch.Ordering,
Counterparty: ch.Counterparty,
ConnectionHops: ch.ConnectionHops,
Version: ch.Version,
}
}
// ValidateBasic performs a basic validation of the identifiers and channel fields.
func (ic IdentifiedChannel) ValidateBasic() error {
if err := host.DefaultChannelIdentifierValidator(ic.ID); err != nil {
return sdkerrors.Wrap(ErrInvalidChannel, err.Error())
}
if err := host.DefaultPortIdentifierValidator(ic.PortID); err != nil {
return sdkerrors.Wrap(ErrInvalidChannel, err.Error())
}
channel := NewChannel(ic.State, ic.Ordering, ic.Counterparty, ic.ConnectionHops, ic.Version)
return channel.ValidateBasic()
}

View File

@ -0,0 +1,142 @@
package types
import (
"errors"
"fmt"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
)
// PacketAckCommitment defines the genesis type necessary to retrieve and store
// acknowlegements.
type PacketAckCommitment struct {
PortID string `json:"port_id" yaml:"port_id"`
ChannelID string `json:"channel_id" yaml:"channel_id"`
Sequence uint64 `json:"sequence" yaml:"sequence"`
Hash []byte `json:"hash" yaml:"hash"`
}
// NewPacketAckCommitment creates a new PacketAckCommitment instance.
func NewPacketAckCommitment(portID, channelID string, seq uint64, hash []byte) PacketAckCommitment {
return PacketAckCommitment{
PortID: portID,
ChannelID: channelID,
Sequence: seq,
Hash: hash,
}
}
// Validate performs basic validation of fields returning an error upon any
// failure.
func (pa PacketAckCommitment) Validate() error {
if len(pa.Hash) == 0 {
return errors.New("hash bytes cannot be empty")
}
return validateGenFields(pa.PortID, pa.ChannelID, pa.Sequence)
}
// PacketSequence defines the genesis type necessary to retrieve and store
// next send and receive sequences.
type PacketSequence struct {
PortID string `json:"port_id" yaml:"port_id"`
ChannelID string `json:"channel_id" yaml:"channel_id"`
Sequence uint64 `json:"sequence" yaml:"sequence"`
}
// NewPacketSequence creates a new PacketSequences instance.
func NewPacketSequence(portID, channelID string, seq uint64) PacketSequence {
return PacketSequence{
PortID: portID,
ChannelID: channelID,
Sequence: seq,
}
}
// Validate performs basic validation of fields returning an error upon any
// failure.
func (ps PacketSequence) Validate() error {
return validateGenFields(ps.PortID, ps.ChannelID, ps.Sequence)
}
// GenesisState defines the ibc channel submodule's genesis state.
type GenesisState struct {
Channels []IdentifiedChannel `json:"channels" yaml:"channels"`
Acknowledgements []PacketAckCommitment `json:"acknowledgements" yaml:"acknowledgements"`
Commitments []PacketAckCommitment `json:"commitments" yaml:"commitments"`
SendSequences []PacketSequence `json:"send_sequences" yaml:"send_sequences"`
RecvSequences []PacketSequence `json:"recv_sequences" yaml:"recv_sequences"`
}
// NewGenesisState creates a GenesisState instance.
func NewGenesisState(
channels []IdentifiedChannel, acks, commitments []PacketAckCommitment,
sendSeqs, recvSeqs []PacketSequence,
) GenesisState {
return GenesisState{
Channels: channels,
Acknowledgements: acks,
Commitments: commitments,
SendSequences: sendSeqs,
RecvSequences: recvSeqs,
}
}
// DefaultGenesisState returns the ibc channel submodule's default genesis state.
func DefaultGenesisState() GenesisState {
return GenesisState{
Channels: []IdentifiedChannel{},
Acknowledgements: []PacketAckCommitment{},
Commitments: []PacketAckCommitment{},
SendSequences: []PacketSequence{},
RecvSequences: []PacketSequence{},
}
}
// Validate performs basic genesis state validation returning an error upon any
// failure.
func (gs GenesisState) Validate() error {
for i, channel := range gs.Channels {
if err := channel.ValidateBasic(); err != nil {
return fmt.Errorf("invalid channel %d: %w", i, err)
}
}
for i, ack := range gs.Acknowledgements {
if err := ack.Validate(); err != nil {
return fmt.Errorf("invalid acknowledgement %d: %w", i, err)
}
}
for i, commitment := range gs.Commitments {
if err := commitment.Validate(); err != nil {
return fmt.Errorf("invalid commitment %d: %w", i, err)
}
}
for i, ss := range gs.SendSequences {
if err := ss.Validate(); err != nil {
return fmt.Errorf("invalid send sequence %d: %w", i, err)
}
}
for i, rs := range gs.RecvSequences {
if err := rs.Validate(); err != nil {
return fmt.Errorf("invalid receive sequence %d: %w", i, err)
}
}
return nil
}
func validateGenFields(portID, channelID string, sequence uint64) error {
if err := host.DefaultPortIdentifierValidator(portID); err != nil {
return err
}
if err := host.DefaultChannelIdentifierValidator(channelID); err != nil {
return err
}
if sequence == 0 {
return errors.New("sequence cannot be 0")
}
return nil
}

View File

@ -0,0 +1,135 @@
package types
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported"
)
const (
testPort1 = "firstport"
testPort2 = "secondport"
testConnectionIDA = "connectionidatob"
testChannel1 = "firstchannel"
testChannel2 = "secondchannel"
testChannelOrder = exported.ORDERED
testChannelVersion = "1.0"
)
func TestValidateGenesis(t *testing.T) {
counterparty1 := NewCounterparty(testPort1, testChannel1)
counterparty2 := NewCounterparty(testPort2, testChannel2)
testCases := []struct {
name string
genState GenesisState
expPass bool
}{
{
name: "default",
genState: DefaultGenesisState(),
expPass: true,
},
{
name: "valid genesis",
genState: NewGenesisState(
[]IdentifiedChannel{
NewIdentifiedChannel(
testPort1, testChannel1, NewChannel(
exported.INIT, testChannelOrder, counterparty2, []string{testConnectionIDA}, testChannelVersion,
),
),
NewIdentifiedChannel(
testPort2, testChannel2, NewChannel(
exported.INIT, testChannelOrder, counterparty1, []string{testConnectionIDA}, testChannelVersion,
),
),
},
[]PacketAckCommitment{
NewPacketAckCommitment(testPort2, testChannel2, 1, []byte("ack")),
},
[]PacketAckCommitment{
NewPacketAckCommitment(testPort1, testChannel1, 1, []byte("commit_hash")),
},
[]PacketSequence{
NewPacketSequence(testPort1, testChannel1, 1),
},
[]PacketSequence{
NewPacketSequence(testPort2, testChannel2, 1),
},
),
expPass: true,
},
{
name: "invalid channel",
genState: GenesisState{
Channels: []IdentifiedChannel{
NewIdentifiedChannel(
testPort1, "testChannel1", NewChannel(
exported.INIT, testChannelOrder, counterparty2, []string{testConnectionIDA}, testChannelVersion,
),
),
},
},
expPass: false,
},
{
name: "invalid ack",
genState: GenesisState{
Acknowledgements: []PacketAckCommitment{
NewPacketAckCommitment(testPort2, testChannel2, 1, nil),
},
},
expPass: false,
},
{
name: "invalid commitment",
genState: GenesisState{
Commitments: []PacketAckCommitment{
NewPacketAckCommitment(testPort1, testChannel1, 1, nil),
},
},
expPass: false,
},
{
name: "invalid send seq",
genState: GenesisState{
SendSequences: []PacketSequence{
NewPacketSequence(testPort1, testChannel1, 0),
},
},
expPass: false,
},
{
name: "invalid recv seq",
genState: GenesisState{
RecvSequences: []PacketSequence{
NewPacketSequence(testPort1, "testChannel1", 1),
},
},
expPass: false,
},
{
name: "invalid recv seq 2",
genState: GenesisState{
RecvSequences: []PacketSequence{
NewPacketSequence("testPort1", testChannel1, 1),
},
},
expPass: false,
},
}
for _, tc := range testCases {
tc := tc
err := tc.genState.Validate()
if tc.expPass {
require.NoError(t, err, tc.name)
} else {
require.Error(t, err, tc.name)
}
}
}

View File

@ -16,12 +16,6 @@ const (
QueryConnectionChannels = "connection-channels"
)
type IdentifiedChannel struct {
Channel Channel `json:"channel_end" yaml:"channel_end"`
PortIdentifier string `json:"port_identifier" yaml:"port_identifier"`
ChannelIdentifier string `json:"channel_identifier" yaml:"channel_identifier"`
}
// ChannelResponse defines the client query response for a channel which also
// includes a proof,its path and the height from which the proof was retrieved.
type ChannelResponse struct {
@ -36,7 +30,8 @@ func NewChannelResponse(
portID, channelID string, channel Channel, proof *merkle.Proof, height int64,
) ChannelResponse {
return ChannelResponse{
Channel: IdentifiedChannel{Channel: channel, PortIdentifier: portID, ChannelIdentifier: channelID},
Channel: NewIdentifiedChannel(portID, channelID, channel),
Proof: commitmenttypes.MerkleProof{Proof: proof},
ProofPath: commitmenttypes.NewMerklePath(strings.Split(ibctypes.ChannelPath(portID, channelID), "/")),
ProofHeight: uint64(height),

View File

@ -4,12 +4,14 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
client "github.com/cosmos/cosmos-sdk/x/ibc/02-client"
connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection"
channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel"
)
// GenesisState defines the ibc module's genesis state.
type GenesisState struct {
ClientGenesis client.GenesisState `json:"client_genesis" yaml:"client_genesis"`
ConnectionGenesis connection.GenesisState `json:"connection_genesis" yaml:"connection_genesis"`
ChannelGenesis channel.GenesisState `json:"channel_genesis" yaml:"channel_genesis"`
}
// DefaultGenesisState returns the ibc module's default genesis state.
@ -17,6 +19,7 @@ func DefaultGenesisState() GenesisState {
return GenesisState{
ClientGenesis: client.DefaultGenesisState(),
ConnectionGenesis: connection.DefaultGenesisState(),
ChannelGenesis: channel.DefaultGenesisState(),
}
}
@ -27,7 +30,11 @@ func (gs GenesisState) Validate() error {
return err
}
return gs.ConnectionGenesis.Validate()
if err := gs.ConnectionGenesis.Validate(); err != nil {
return err
}
return gs.ChannelGenesis.Validate()
}
// InitGenesis initializes the ibc state from a provided genesis
@ -35,6 +42,7 @@ func (gs GenesisState) Validate() error {
func InitGenesis(ctx sdk.Context, k Keeper, gs GenesisState) {
client.InitGenesis(ctx, k.ClientKeeper, gs.ClientGenesis)
connection.InitGenesis(ctx, k.ConnectionKeeper, gs.ConnectionGenesis)
channel.InitGenesis(ctx, k.ChannelKeeper, gs.ChannelGenesis)
}
// ExportGenesis returns the ibc exported genesis.
@ -42,5 +50,6 @@ func ExportGenesis(ctx sdk.Context, k Keeper) GenesisState {
return GenesisState{
ClientGenesis: client.ExportGenesis(ctx, k.ClientKeeper),
ConnectionGenesis: connection.ExportGenesis(ctx, k.ConnectionKeeper),
ChannelGenesis: channel.ExportGenesis(ctx, k.ChannelKeeper),
}
}

View File

@ -6,6 +6,8 @@ import (
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection"
connectionexported "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/exported"
channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel"
channelexported "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/09-localhost/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
@ -50,6 +52,28 @@ func (suite *IBCTestSuite) TestValidateGenesis() {
connection.NewConnectionPaths(clientID, []string{ibctypes.ConnectionPath(connectionID)}),
},
),
ChannelGenesis: channel.NewGenesisState(
[]channel.IdentifiedChannel{
channel.NewIdentifiedChannel(
port1, channel1, channel.NewChannel(
channelexported.INIT, channelOrder,
channel.NewCounterparty(port2, channel2), []string{connectionID}, channelVersion,
),
),
},
[]channel.PacketAckCommitment{
channel.NewPacketAckCommitment(port2, channel2, 1, []byte("ack")),
},
[]channel.PacketAckCommitment{
channel.NewPacketAckCommitment(port1, channel1, 1, []byte("commit_hash")),
},
[]channel.PacketSequence{
channel.NewPacketSequence(port1, channel1, 1),
},
[]channel.PacketSequence{
channel.NewPacketSequence(port2, channel2, 1),
},
),
},
expPass: true,
},
@ -82,6 +106,19 @@ func (suite *IBCTestSuite) TestValidateGenesis() {
},
expPass: false,
},
{
name: "invalid channel genesis",
genState: ibc.GenesisState{
ClientGenesis: client.DefaultGenesisState(),
ConnectionGenesis: connection.DefaultGenesisState(),
ChannelGenesis: channel.GenesisState{
Acknowledgements: []channel.PacketAckCommitment{
channel.NewPacketAckCommitment("portID", channel1, 1, []byte("ack")),
},
},
},
expPass: false,
},
}
for _, tc := range testCases {

View File

@ -15,6 +15,7 @@ import (
"github.com/cosmos/cosmos-sdk/store/cachekv"
"github.com/cosmos/cosmos-sdk/store/dbadapter"
sdk "github.com/cosmos/cosmos-sdk/types"
channelexported "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
)
@ -24,6 +25,15 @@ const (
connectionID2 = "connectionidtwo"
clientID2 = "clientidtwo"
port1 = "firstport"
port2 = "secondport"
channel1 = "firstchannel"
channel2 = "secondchannel"
channelOrder = channelexported.ORDERED
channelVersion = "1.0"
trustingPeriod time.Duration = time.Hour * 24 * 7 * 2
ubdPeriod time.Duration = time.Hour * 24 * 7 * 3
maxClockDrift time.Duration = time.Second * 10

View File

@ -144,12 +144,6 @@ func KeyChannel(portID, channelID string) []byte {
return []byte(ChannelPath(portID, channelID))
}
// KeyChannelCapabilityPath returns the store key for the capability key of a
// particular channel binded to a specific port
func KeyChannelCapabilityPath(portID, channelID string) []byte {
return []byte(ChannelCapabilityPath(portID, channelID))
}
// KeyNextSequenceSend returns the store key for the send sequence of a particular
// channel binded to a specific port
func KeyNextSequenceSend(portID, channelID string) []byte {