ibc/03-connection: import export GenesisState (#6067)
* ibc/03-connection: import export GenesisState * add connection paths * add genesis to ibc module root package * genesis tests * iterator and fixes * changelog * lint fixes * godoc * revert validation
This commit is contained in:
parent
bdcc04347c
commit
e9b5fc9716
|
@ -223,6 +223,7 @@ functionality that requires an online connection.
|
|||
* (x/auth/ante) [\#6040](https://github.com/cosmos/cosmos-sdk/pull/6040) `AccountKeeper` interface used for `NewAnteHandler` and handler's decorators to add support of using custom `AccountKeeper` implementations.
|
||||
* (simulation) [\#6002](https://github.com/cosmos/cosmos-sdk/pull/6002) Add randomized consensus params into simulation.
|
||||
* (x/staking) [\#6059](https://github.com/cosmos/cosmos-sdk/pull/6059) Updated `HistoricalEntries` parameter default to 100.
|
||||
* (x/ibc) [\#5948](https://github.com/cosmos/cosmos-sdk/issues/5948) Add `InitGenesis` and `ExportGenesis` functions for `ibc` module.
|
||||
|
||||
## [v0.38.3] - 2020-04-09
|
||||
|
||||
|
|
|
@ -46,6 +46,9 @@ var (
|
|||
GetCompatibleVersions = types.GetCompatibleVersions
|
||||
LatestVersion = types.LatestVersion
|
||||
PickVersion = types.PickVersion
|
||||
NewConnectionPaths = types.NewConnectionPaths
|
||||
DefaultGenesisState = types.DefaultGenesisState
|
||||
NewGenesisState = types.NewGenesisState
|
||||
|
||||
// variable aliases
|
||||
SubModuleCdc = types.SubModuleCdc
|
||||
|
@ -69,4 +72,6 @@ type (
|
|||
ConnectionResponse = types.ConnectionResponse
|
||||
ClientConnectionsResponse = types.ClientConnectionsResponse
|
||||
QueryClientConnectionsParams = types.QueryClientConnectionsParams
|
||||
GenesisState = types.GenesisState
|
||||
ConnectionPaths = types.ConnectionPaths
|
||||
)
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
|
||||
// QueryAllConnections returns all the connections. It _does not_ return
|
||||
// any merkle proof.
|
||||
func QueryAllConnections(cliCtx context.CLIContext, page, limit int) ([]types.IdentifiedConnectionEnd, int64, error) {
|
||||
func QueryAllConnections(cliCtx context.CLIContext, page, limit int) ([]types.ConnectionEnd, int64, error) {
|
||||
params := types.NewQueryAllConnectionsParams(page, limit)
|
||||
bz, err := cliCtx.Codec.MarshalJSON(params)
|
||||
if err != nil {
|
||||
|
@ -30,7 +30,7 @@ func QueryAllConnections(cliCtx context.CLIContext, page, limit int) ([]types.Id
|
|||
return nil, 0, err
|
||||
}
|
||||
|
||||
var connections []types.IdentifiedConnectionEnd
|
||||
var connections []types.ConnectionEnd
|
||||
err = cliCtx.Codec.UnmarshalJSON(res, &connections)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to unmarshal connections: %w", err)
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
// ConnectionI describes the required methods for a connection.
|
||||
type ConnectionI interface {
|
||||
GetState() State
|
||||
GetID() string
|
||||
GetClientID() string
|
||||
GetCounterparty() CounterpartyI
|
||||
GetVersions() []string
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package connection
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// InitGenesis initializes the ibc connection submodule's state from a provided genesis
|
||||
// state.
|
||||
func InitGenesis(ctx sdk.Context, k Keeper, gs GenesisState) {
|
||||
for _, connection := range gs.Connections {
|
||||
k.SetConnection(ctx, connection.ID, connection)
|
||||
}
|
||||
for _, connPaths := range gs.ClientConnectionPaths {
|
||||
k.SetClientConnectionPaths(ctx, connPaths.ClientID, connPaths.Paths)
|
||||
}
|
||||
}
|
||||
|
||||
// ExportGenesis returns the ibc connection submodule's exported genesis.
|
||||
func ExportGenesis(ctx sdk.Context, k Keeper) GenesisState {
|
||||
return GenesisState{
|
||||
Connections: k.GetAllConnections(ctx),
|
||||
ClientConnectionPaths: k.GetAllClientConnectionPaths(ctx),
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ func (k Keeper) ConnOpenInit(
|
|||
}
|
||||
|
||||
// connection defines chain A's ConnectionEnd
|
||||
connection := types.NewConnectionEnd(exported.INIT, clientID, counterparty, types.GetCompatibleVersions())
|
||||
connection := types.NewConnectionEnd(exported.INIT, connectionID, clientID, counterparty, types.GetCompatibleVersions())
|
||||
k.SetConnection(ctx, connectionID, connection)
|
||||
|
||||
if err := k.addConnectionToClient(ctx, clientID, connectionID); err != nil {
|
||||
|
@ -69,14 +69,14 @@ func (k Keeper) ConnOpenTry(
|
|||
// NOTE: chain A's counterparty is chain B (i.e where this code is executed)
|
||||
prefix := k.GetCommitmentPrefix()
|
||||
expectedCounterparty := types.NewCounterparty(clientID, connectionID, prefix)
|
||||
expectedConnection := types.NewConnectionEnd(exported.INIT, counterparty.ClientID, expectedCounterparty, counterpartyVersions)
|
||||
expectedConnection := types.NewConnectionEnd(exported.INIT, counterparty.ConnectionID, counterparty.ClientID, expectedCounterparty, counterpartyVersions)
|
||||
|
||||
// chain B picks a version from Chain A's available versions that is compatible
|
||||
// with the supported IBC versions
|
||||
version := types.PickVersion(counterpartyVersions, types.GetCompatibleVersions())
|
||||
|
||||
// connection defines chain B's ConnectionEnd
|
||||
connection := types.NewConnectionEnd(exported.UNINITIALIZED, clientID, counterparty, []string{version})
|
||||
connection := types.NewConnectionEnd(exported.UNINITIALIZED, connectionID, clientID, counterparty, []string{version})
|
||||
|
||||
// Check that ChainA committed expectedConnectionEnd to its state
|
||||
if err := k.VerifyConnectionState(
|
||||
|
@ -165,7 +165,7 @@ func (k Keeper) ConnOpenAck(
|
|||
|
||||
prefix := k.GetCommitmentPrefix()
|
||||
expectedCounterparty := types.NewCounterparty(connection.ClientID, connectionID, prefix)
|
||||
expectedConnection := types.NewConnectionEnd(exported.TRYOPEN, connection.Counterparty.ClientID, expectedCounterparty, []string{version})
|
||||
expectedConnection := types.NewConnectionEnd(exported.TRYOPEN, connection.Counterparty.ConnectionID, connection.Counterparty.ClientID, expectedCounterparty, []string{version})
|
||||
|
||||
// Ensure that ChainB stored expected connectionEnd in its state during ConnOpenTry
|
||||
if err := k.VerifyConnectionState(
|
||||
|
@ -216,7 +216,7 @@ func (k Keeper) ConnOpenConfirm(
|
|||
|
||||
prefix := k.GetCommitmentPrefix()
|
||||
expectedCounterparty := types.NewCounterparty(connection.ClientID, connectionID, prefix)
|
||||
expectedConnection := types.NewConnectionEnd(exported.OPEN, connection.Counterparty.ClientID, expectedCounterparty, connection.Versions)
|
||||
expectedConnection := types.NewConnectionEnd(exported.OPEN, connection.Counterparty.ConnectionID, connection.Counterparty.ClientID, expectedCounterparty, connection.Versions)
|
||||
|
||||
// Check that connection on ChainA is open
|
||||
if err := k.VerifyConnectionState(
|
||||
|
|
|
@ -25,7 +25,7 @@ func (suite *KeeperTestSuite) TestConnOpenInit() {
|
|||
{"couldn't add connection to client", func() {}, false},
|
||||
}
|
||||
|
||||
counterparty := connection.NewCounterparty(testClientIDA, testConnectionIDB, suite.chainA.App.IBCKeeper.ConnectionKeeper.GetCommitmentPrefix())
|
||||
counterparty := connection.NewCounterparty(testClientIDB, testConnectionIDB, suite.chainA.App.IBCKeeper.ConnectionKeeper.GetCommitmentPrefix())
|
||||
|
||||
for i, tc := range testCases {
|
||||
tc := tc
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
|
||||
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
|
||||
commitmentexported "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/exported"
|
||||
|
@ -101,10 +102,29 @@ func (k Keeper) SetClientConnectionPaths(ctx sdk.Context, clientID string, paths
|
|||
store.Set(ibctypes.KeyClientConnections(clientID), bz)
|
||||
}
|
||||
|
||||
// GetAllClientConnectionPaths returns all stored clients connection id paths. It
|
||||
// will ignore the clients that haven't initialized a connection handshake since
|
||||
// no paths are stored.
|
||||
func (k Keeper) GetAllClientConnectionPaths(ctx sdk.Context) []types.ConnectionPaths {
|
||||
var allConnectionPaths []types.ConnectionPaths
|
||||
k.clientKeeper.IterateClients(ctx, func(cs clientexported.ClientState) bool {
|
||||
paths, found := k.GetClientConnectionPaths(ctx, cs.GetID())
|
||||
if !found {
|
||||
// continue when connection handshake is not initialized
|
||||
return false
|
||||
}
|
||||
connPaths := types.NewConnectionPaths(cs.GetID(), paths)
|
||||
allConnectionPaths = append(allConnectionPaths, connPaths)
|
||||
return false
|
||||
})
|
||||
|
||||
return allConnectionPaths
|
||||
}
|
||||
|
||||
// IterateConnections provides an iterator over all ConnectionEnd objects.
|
||||
// For each ConnectionEnd, cb will be called. If the cb returns true, the
|
||||
// iterator will close and stop.
|
||||
func (k Keeper) IterateConnections(ctx sdk.Context, cb func(types.IdentifiedConnectionEnd) bool) {
|
||||
func (k Keeper) IterateConnections(ctx sdk.Context, cb func(types.ConnectionEnd) bool) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
iterator := sdk.KVStorePrefixIterator(store, ibctypes.KeyConnectionPrefix)
|
||||
|
||||
|
@ -112,22 +132,16 @@ func (k Keeper) IterateConnections(ctx sdk.Context, cb func(types.IdentifiedConn
|
|||
for ; iterator.Valid(); iterator.Next() {
|
||||
var connection types.ConnectionEnd
|
||||
k.cdc.MustUnmarshalBinaryBare(iterator.Value(), &connection)
|
||||
identifier := string(iterator.Key()[len(ibctypes.KeyConnectionPrefix)+1:])
|
||||
|
||||
conn := types.IdentifiedConnectionEnd{
|
||||
Connection: connection,
|
||||
Identifier: identifier,
|
||||
}
|
||||
|
||||
if cb(conn) {
|
||||
if cb(connection) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetAllConnections returns all stored ConnectionEnd objects.
|
||||
func (k Keeper) GetAllConnections(ctx sdk.Context) (connections []types.IdentifiedConnectionEnd) {
|
||||
k.IterateConnections(ctx, func(connection types.IdentifiedConnectionEnd) bool {
|
||||
func (k Keeper) GetAllConnections(ctx sdk.Context) (connections []types.ConnectionEnd) {
|
||||
k.IterateConnections(ctx, func(connection types.ConnectionEnd) bool {
|
||||
connections = append(connections, connection)
|
||||
return false
|
||||
})
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/exported"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
|
||||
channelexported "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported"
|
||||
|
@ -36,7 +37,7 @@ const (
|
|||
|
||||
trustingPeriod time.Duration = time.Hour * 24 * 7 * 2
|
||||
ubdPeriod time.Duration = time.Hour * 24 * 7 * 3
|
||||
maxClockDrift time.Duration = time.Second * 10
|
||||
maxClockDrift time.Duration = time.Second * 10
|
||||
|
||||
nextTimestamp = 10 // increment used for the next header's timestamp
|
||||
)
|
||||
|
@ -88,7 +89,7 @@ func (suite *KeeperTestSuite) TestSetAndGetConnection() {
|
|||
suite.Require().False(existed)
|
||||
|
||||
counterparty := types.NewCounterparty(testClientIDA, testConnectionIDA, suite.chainA.App.IBCKeeper.ConnectionKeeper.GetCommitmentPrefix())
|
||||
expConn := types.NewConnectionEnd(exported.INIT, testClientIDB, counterparty, types.GetCompatibleVersions())
|
||||
expConn := types.NewConnectionEnd(exported.INIT, testConnectionIDB, testClientIDB, counterparty, types.GetCompatibleVersions())
|
||||
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), testConnectionIDA, expConn)
|
||||
conn, existed := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetConnection(suite.chainA.GetContext(), testConnectionIDA)
|
||||
suite.Require().True(existed)
|
||||
|
@ -111,25 +112,46 @@ func (suite KeeperTestSuite) TestGetAllConnections() {
|
|||
counterparty2 := types.NewCounterparty(testClientIDB, testConnectionIDB, suite.chainA.App.IBCKeeper.ConnectionKeeper.GetCommitmentPrefix())
|
||||
counterparty3 := types.NewCounterparty(testClientID3, testConnectionID3, suite.chainA.App.IBCKeeper.ConnectionKeeper.GetCommitmentPrefix())
|
||||
|
||||
conn1 := types.NewConnectionEnd(exported.INIT, testClientIDA, counterparty3, types.GetCompatibleVersions())
|
||||
conn2 := types.NewConnectionEnd(exported.INIT, testClientIDB, counterparty1, types.GetCompatibleVersions())
|
||||
conn3 := types.NewConnectionEnd(exported.UNINITIALIZED, testClientID3, counterparty2, types.GetCompatibleVersions())
|
||||
conn1 := types.NewConnectionEnd(exported.INIT, testConnectionIDA, testClientIDA, counterparty3, types.GetCompatibleVersions())
|
||||
conn2 := types.NewConnectionEnd(exported.INIT, testConnectionIDB, testClientIDB, counterparty1, types.GetCompatibleVersions())
|
||||
conn3 := types.NewConnectionEnd(exported.UNINITIALIZED, testConnectionID3, testClientID3, counterparty2, types.GetCompatibleVersions())
|
||||
|
||||
expConnections := []types.IdentifiedConnectionEnd{
|
||||
{Connection: conn1, Identifier: testConnectionIDA},
|
||||
{Connection: conn2, Identifier: testConnectionIDB},
|
||||
{Connection: conn3, Identifier: testConnectionID3},
|
||||
expConnections := []types.ConnectionEnd{conn1, conn2, conn3}
|
||||
|
||||
for i := range expConnections {
|
||||
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), expConnections[i].ID, expConnections[i])
|
||||
}
|
||||
|
||||
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), testConnectionIDA, conn1)
|
||||
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), testConnectionIDB, conn2)
|
||||
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), testConnectionID3, conn3)
|
||||
|
||||
connections := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetAllConnections(suite.chainA.GetContext())
|
||||
suite.Require().Len(connections, len(expConnections))
|
||||
suite.Require().ElementsMatch(expConnections, connections)
|
||||
}
|
||||
|
||||
func (suite KeeperTestSuite) TestGetAllClientConnectionPaths() {
|
||||
clients := []clientexported.ClientState{
|
||||
ibctmtypes.NewClientState(testClientIDA, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}),
|
||||
ibctmtypes.NewClientState(testClientIDB, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}),
|
||||
ibctmtypes.NewClientState(testClientID3, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}),
|
||||
}
|
||||
|
||||
for i := range clients {
|
||||
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clients[i])
|
||||
}
|
||||
|
||||
expPaths := []types.ConnectionPaths{
|
||||
types.NewConnectionPaths(testClientIDA, []string{ibctypes.ConnectionPath(testConnectionIDA)}),
|
||||
types.NewConnectionPaths(testClientIDB, []string{ibctypes.ConnectionPath(testConnectionIDB), ibctypes.ConnectionPath(testConnectionID3)}),
|
||||
}
|
||||
|
||||
for i := range expPaths {
|
||||
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetClientConnectionPaths(suite.chainA.GetContext(), expPaths[i].ClientID, expPaths[i].Paths)
|
||||
}
|
||||
|
||||
connPaths := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetAllClientConnectionPaths(suite.chainA.GetContext())
|
||||
suite.Require().Len(connPaths, 2)
|
||||
suite.Require().Equal(connPaths, expPaths)
|
||||
}
|
||||
|
||||
// TestGetTimestampAtHeight verifies if the clients on each chain return the correct timestamp
|
||||
// for the other chain.
|
||||
func (suite *KeeperTestSuite) TestGetTimestampAtHeight() {
|
||||
|
@ -338,6 +360,7 @@ func (chain *TestChain) createConnection(
|
|||
counterparty := types.NewCounterparty(counterpartyClientID, counterpartyConnID, chain.App.IBCKeeper.ConnectionKeeper.GetCommitmentPrefix())
|
||||
connection := types.ConnectionEnd{
|
||||
State: state,
|
||||
ID: connID,
|
||||
ClientID: clientID,
|
||||
Counterparty: counterparty,
|
||||
Versions: types.GetCompatibleVersions(),
|
||||
|
|
|
@ -22,7 +22,7 @@ func QuerierConnections(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byt
|
|||
|
||||
start, end := client.Paginate(len(connections), params.Page, params.Limit, 100)
|
||||
if start < 0 || end < 0 {
|
||||
connections = []types.IdentifiedConnectionEnd{}
|
||||
connections = []types.ConnectionEnd{}
|
||||
} else {
|
||||
connections = connections[start:end]
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ func (suite *KeeperTestSuite) TestVerifyClientConsensusState() {
|
|||
suite.chainA.App.IBCKeeper.ConnectionKeeper.GetCommitmentPrefix(),
|
||||
)
|
||||
connection1 := types.NewConnectionEnd(
|
||||
exported.UNINITIALIZED, testClientIDB, counterparty,
|
||||
exported.UNINITIALIZED, testConnectionIDB, testClientIDB, counterparty,
|
||||
types.GetCompatibleVersions(),
|
||||
)
|
||||
|
||||
|
@ -135,8 +135,8 @@ func (suite *KeeperTestSuite) TestVerifyConnectionState() {
|
|||
}
|
||||
|
||||
// Create B's connection to A
|
||||
counterparty := types.NewCounterparty(testClientIDB, testConnectionIDA, commitmenttypes.NewMerklePrefix([]byte("ibc")))
|
||||
connection := types.NewConnectionEnd(exported.UNINITIALIZED, testClientIDA, counterparty, []string{"1.0.0"})
|
||||
counterparty := types.NewCounterparty(testClientIDB, testConnectionIDB, commitmenttypes.NewMerklePrefix([]byte("ibc")))
|
||||
connection := types.NewConnectionEnd(exported.UNINITIALIZED, testConnectionIDA, testClientIDA, counterparty, []string{"1.0.0"})
|
||||
// Ensure chain B can verify connection exists in chain A
|
||||
err := suite.chainB.App.IBCKeeper.ConnectionKeeper.VerifyConnectionState(
|
||||
suite.chainB.GetContext(), connection, proofHeight+1, proof, testConnectionIDA, expectedConnection,
|
||||
|
@ -161,7 +161,7 @@ func (suite *KeeperTestSuite) TestVerifyChannelState() {
|
|||
)
|
||||
|
||||
connection := types.NewConnectionEnd(
|
||||
exported.UNINITIALIZED, testClientIDA, counterparty,
|
||||
exported.UNINITIALIZED, testConnectionIDA, testClientIDA, counterparty,
|
||||
types.GetCompatibleVersions(),
|
||||
)
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ var _ exported.ConnectionI = ConnectionEnd{}
|
|||
// between two chains.
|
||||
type ConnectionEnd struct {
|
||||
State exported.State `json:"state" yaml:"state"`
|
||||
ID string `json:"id" yaml:"id"`
|
||||
ClientID string `json:"client_id" yaml:"client_id"`
|
||||
|
||||
// Counterparty chain associated with this connection.
|
||||
|
@ -30,9 +31,10 @@ type ConnectionEnd struct {
|
|||
}
|
||||
|
||||
// NewConnectionEnd creates a new ConnectionEnd instance.
|
||||
func NewConnectionEnd(state exported.State, clientID string, counterparty Counterparty, versions []string) ConnectionEnd {
|
||||
func NewConnectionEnd(state exported.State, connectionID, clientID string, counterparty Counterparty, versions []string) ConnectionEnd {
|
||||
return ConnectionEnd{
|
||||
State: state,
|
||||
ID: connectionID,
|
||||
ClientID: clientID,
|
||||
Counterparty: counterparty,
|
||||
Versions: versions,
|
||||
|
@ -44,6 +46,11 @@ func (c ConnectionEnd) GetState() exported.State {
|
|||
return c.State
|
||||
}
|
||||
|
||||
// GetID implements the Connection interface
|
||||
func (c ConnectionEnd) GetID() string {
|
||||
return c.ID
|
||||
}
|
||||
|
||||
// GetClientID implements the Connection interface
|
||||
func (c ConnectionEnd) GetClientID() string {
|
||||
return c.ClientID
|
||||
|
@ -59,8 +66,13 @@ func (c ConnectionEnd) GetVersions() []string {
|
|||
return c.Versions
|
||||
}
|
||||
|
||||
// ValidateBasic implements the Connection interface
|
||||
// ValidateBasic implements the Connection interface.
|
||||
// NOTE: the protocol supports that the connection and client IDs match the
|
||||
// counterparty's.
|
||||
func (c ConnectionEnd) ValidateBasic() error {
|
||||
if err := host.DefaultConnectionIdentifierValidator(c.ID); err != nil {
|
||||
return sdkerrors.Wrapf(err, "invalid connection ID: %s", c.ID)
|
||||
}
|
||||
if err := host.DefaultClientIdentifierValidator(c.ClientID); err != nil {
|
||||
return sdkerrors.Wrapf(err, "invalid client ID: %s", c.ClientID)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,13 @@ import (
|
|||
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
|
||||
)
|
||||
|
||||
var (
|
||||
connectionID = "connectionidone"
|
||||
clientID = "clientidone"
|
||||
connectionID2 = "connectionidtwo"
|
||||
clientID2 = "clientidtwo"
|
||||
)
|
||||
|
||||
func TestConnectionValidateBasic(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
|
@ -17,27 +24,32 @@ func TestConnectionValidateBasic(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
"valid connection",
|
||||
ConnectionEnd{exported.INIT, "clientidone", Counterparty{"clientidtwo", "connectionidone", commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{"1.0.0"}},
|
||||
ConnectionEnd{exported.INIT, connectionID, clientID, Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{"1.0.0"}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid connection id",
|
||||
ConnectionEnd{exported.INIT, "connectionIDONE", clientID, Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{"1.0.0"}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid client id",
|
||||
ConnectionEnd{exported.INIT, "ClientIDTwo", Counterparty{"clientidtwo", "connectionidone", commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{"1.0.0"}},
|
||||
ConnectionEnd{exported.INIT, connectionID, "ClientIDTwo", Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{"1.0.0"}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"empty versions",
|
||||
ConnectionEnd{exported.INIT, "clientidone", Counterparty{"clientidtwo", "connectionidone", commitmenttypes.NewMerklePrefix([]byte("prefix"))}, nil},
|
||||
ConnectionEnd{exported.INIT, connectionID, clientID, Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, nil},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid version",
|
||||
ConnectionEnd{exported.INIT, "clientidone", Counterparty{"clientidtwo", "connectionidone", commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{""}},
|
||||
ConnectionEnd{exported.INIT, connectionID, clientID, Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{""}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid counterparty",
|
||||
ConnectionEnd{exported.INIT, "clientidone", Counterparty{"clientidtwo", "connectionidone", nil}, []string{"1.0.0"}},
|
||||
ConnectionEnd{exported.INIT, connectionID, clientID, Counterparty{clientID2, connectionID2, nil}, []string{"1.0.0"}},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
@ -60,10 +72,10 @@ func TestCounterpartyValidateBasic(t *testing.T) {
|
|||
counterparty Counterparty
|
||||
expPass bool
|
||||
}{
|
||||
{"valid counterparty", Counterparty{"clientidone", "connectionidone", commitmenttypes.NewMerklePrefix([]byte("prefix"))}, true},
|
||||
{"valid counterparty", Counterparty{"clientidone", connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, true},
|
||||
{"invalid client id", Counterparty{"InvalidClient", "channelidone", commitmenttypes.NewMerklePrefix([]byte("prefix"))}, false},
|
||||
{"invalid connection id", Counterparty{"clientidone", "InvalidConnection", commitmenttypes.NewMerklePrefix([]byte("prefix"))}, false},
|
||||
{"invalid prefix", Counterparty{"clientidone", "connectionidone", nil}, false},
|
||||
{"invalid prefix", Counterparty{"clientidone", connectionID2, nil}, false},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
|
|
|
@ -10,4 +10,5 @@ type ClientKeeper interface {
|
|||
GetClientState(ctx sdk.Context, clientID string) (clientexported.ClientState, bool)
|
||||
GetClientConsensusState(ctx sdk.Context, clientID string, height uint64) (clientexported.ConsensusState, bool)
|
||||
GetSelfConsensusState(ctx sdk.Context, height uint64) (clientexported.ConsensusState, bool)
|
||||
IterateClients(ctx sdk.Context, cb func(clientexported.ClientState) bool)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
|
||||
)
|
||||
|
||||
// ConnectionPaths define all the connection paths for a given client state.
|
||||
type ConnectionPaths struct {
|
||||
ClientID string `json:"client_id" yaml:"client_id"`
|
||||
Paths []string `json:"paths" yaml:"paths"`
|
||||
}
|
||||
|
||||
// NewConnectionPaths creates a ConnectionPaths instance.
|
||||
func NewConnectionPaths(id string, paths []string) ConnectionPaths {
|
||||
return ConnectionPaths{
|
||||
ClientID: id,
|
||||
Paths: paths,
|
||||
}
|
||||
}
|
||||
|
||||
// GenesisState defines the ibc connection submodule's genesis state.
|
||||
type GenesisState struct {
|
||||
Connections []ConnectionEnd `json:"connections" yaml:"connections"`
|
||||
ClientConnectionPaths []ConnectionPaths `json:"client_connection_paths" yaml:"client_connection_paths"`
|
||||
}
|
||||
|
||||
// NewGenesisState creates a GenesisState instance.
|
||||
func NewGenesisState(
|
||||
connections []ConnectionEnd, connPaths []ConnectionPaths,
|
||||
) GenesisState {
|
||||
return GenesisState{
|
||||
Connections: connections,
|
||||
ClientConnectionPaths: connPaths,
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultGenesisState returns the ibc connection submodule's default genesis state.
|
||||
func DefaultGenesisState() GenesisState {
|
||||
return GenesisState{
|
||||
Connections: []ConnectionEnd{},
|
||||
ClientConnectionPaths: []ConnectionPaths{},
|
||||
}
|
||||
}
|
||||
|
||||
// Validate performs basic genesis state validation returning an error upon any
|
||||
// failure.
|
||||
func (gs GenesisState) Validate() error {
|
||||
for i, conn := range gs.Connections {
|
||||
if err := conn.ValidateBasic(); err != nil {
|
||||
return fmt.Errorf("invalid connection %d: %w", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
for i, conPaths := range gs.ClientConnectionPaths {
|
||||
if err := host.DefaultClientIdentifierValidator(conPaths.ClientID); err != nil {
|
||||
return fmt.Errorf("invalid client connection path %d: %w", i, err)
|
||||
}
|
||||
for _, path := range conPaths.Paths {
|
||||
if err := host.DefaultPathValidator(path); err != nil {
|
||||
return fmt.Errorf("invalid client connection path %d: %w", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/exported"
|
||||
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
|
||||
ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types"
|
||||
)
|
||||
|
||||
func TestValidateGenesis(t *testing.T) {
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
genState GenesisState
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
name: "default",
|
||||
genState: DefaultGenesisState(),
|
||||
expPass: true,
|
||||
},
|
||||
{
|
||||
name: "valid genesis",
|
||||
genState: NewGenesisState(
|
||||
[]ConnectionEnd{
|
||||
{exported.INIT, connectionID, clientID, Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{"1.0.0"}},
|
||||
},
|
||||
[]ConnectionPaths{
|
||||
{clientID, []string{ibctypes.ConnectionPath(connectionID)}},
|
||||
},
|
||||
),
|
||||
expPass: true,
|
||||
},
|
||||
{
|
||||
name: "invalid connection",
|
||||
genState: NewGenesisState(
|
||||
[]ConnectionEnd{
|
||||
NewConnectionEnd(exported.INIT, connectionID, "CLIENTIDONE", Counterparty{clientID, connectionID, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{"1.0.0"}),
|
||||
},
|
||||
[]ConnectionPaths{
|
||||
{clientID, []string{ibctypes.ConnectionPath(connectionID)}},
|
||||
},
|
||||
),
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "invalid client id",
|
||||
genState: NewGenesisState(
|
||||
[]ConnectionEnd{
|
||||
{exported.INIT, connectionID, clientID, Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{"1.0.0"}},
|
||||
},
|
||||
[]ConnectionPaths{
|
||||
{"CLIENTIDONE", []string{ibctypes.ConnectionPath(connectionID)}},
|
||||
},
|
||||
),
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "invalid path",
|
||||
genState: NewGenesisState(
|
||||
[]ConnectionEnd{
|
||||
{exported.INIT, connectionID, clientID, Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{"1.0.0"}},
|
||||
},
|
||||
[]ConnectionPaths{
|
||||
{clientID, []string{connectionID}},
|
||||
},
|
||||
),
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,16 +15,10 @@ const (
|
|||
QueryClientConnections = "client_connections"
|
||||
)
|
||||
|
||||
// IdentifiedConnectionEnd defines the union of a connection end & an identifier.
|
||||
type IdentifiedConnectionEnd struct {
|
||||
Connection ConnectionEnd `json:"connection_end" yaml:"connection_end"`
|
||||
Identifier string `json:"identifier" yaml:"identifier"`
|
||||
}
|
||||
|
||||
// ConnectionResponse defines the client query response for a connection which
|
||||
// also includes a proof and the height from which the proof was retrieved.
|
||||
type ConnectionResponse struct {
|
||||
Connection IdentifiedConnectionEnd `json:"connection" yaml:"connection"`
|
||||
Connection ConnectionEnd `json:"connection" yaml:"connection"`
|
||||
Proof commitmenttypes.MerkleProof `json:"proof,omitempty" yaml:"proof,omitempty"`
|
||||
ProofPath commitmenttypes.MerklePath `json:"proof_path,omitempty" yaml:"proof_path,omitempty"`
|
||||
ProofHeight uint64 `json:"proof_height,omitempty" yaml:"proof_height,omitempty"`
|
||||
|
@ -35,7 +29,7 @@ func NewConnectionResponse(
|
|||
connectionID string, connection ConnectionEnd, proof *merkle.Proof, height int64,
|
||||
) ConnectionResponse {
|
||||
return ConnectionResponse{
|
||||
Connection: IdentifiedConnectionEnd{connection, connectionID},
|
||||
Connection: connection,
|
||||
Proof: commitmenttypes.MerkleProof{Proof: proof},
|
||||
ProofPath: commitmenttypes.NewMerklePath(strings.Split(ibctypes.ConnectionPath(connectionID), "/")),
|
||||
ProofHeight: uint64(height),
|
||||
|
|
|
@ -92,7 +92,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
|
|||
|
||||
func (suite *TendermintTestSuite) TestVerifyConnectionState() {
|
||||
counterparty := connection.NewCounterparty("clientB", testConnectionID, commitmenttypes.NewMerklePrefix([]byte("ibc")))
|
||||
conn := connection.NewConnectionEnd(connectionexported.OPEN, "clientA", counterparty, []string{"1.0.0"})
|
||||
conn := connection.NewConnectionEnd(connectionexported.OPEN, testConnectionID, "clientA", counterparty, []string{"1.0.0"})
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
|
|
|
@ -58,7 +58,7 @@ func (suite *LocalhostTestSuite) TestVerifyClientConsensusState() {
|
|||
|
||||
func (suite *LocalhostTestSuite) TestVerifyConnectionState() {
|
||||
counterparty := connection.NewCounterparty("clientB", testConnectionID, commitmenttypes.NewMerklePrefix([]byte("ibc")))
|
||||
conn := connection.NewConnectionEnd(connectionexported.OPEN, "clientA", counterparty, []string{"1.0.0"})
|
||||
conn := connection.NewConnectionEnd(connectionexported.OPEN, testConnectionID, "clientA", counterparty, []string{"1.0.0"})
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package ibc
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection"
|
||||
)
|
||||
|
||||
// GenesisState defines the ibc module's genesis state.
|
||||
type GenesisState struct {
|
||||
ConnectionGenesis connection.GenesisState `json:"connection_genesis" yaml:"connection_genesis"`
|
||||
}
|
||||
|
||||
// DefaultGenesisState returns the ibc module's default genesis state.
|
||||
func DefaultGenesisState() GenesisState {
|
||||
return GenesisState{
|
||||
ConnectionGenesis: connection.DefaultGenesisState(),
|
||||
}
|
||||
}
|
||||
|
||||
// Validate performs basic genesis state validation returning an error upon any
|
||||
// failure.
|
||||
func (gs GenesisState) Validate() error {
|
||||
return gs.ConnectionGenesis.Validate()
|
||||
}
|
||||
|
||||
// InitGenesis initializes the ibc connection submodule's state from a provided genesis
|
||||
// state.
|
||||
func InitGenesis(ctx sdk.Context, k Keeper, gs GenesisState) {
|
||||
connection.InitGenesis(ctx, k.ConnectionKeeper, gs.ConnectionGenesis)
|
||||
}
|
||||
|
||||
// ExportGenesis returns the ibc connection submodule's exported genesis.
|
||||
func ExportGenesis(ctx sdk.Context, k Keeper) GenesisState {
|
||||
return GenesisState{
|
||||
ConnectionGenesis: connection.ExportGenesis(ctx, k.ConnectionKeeper),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package ibc
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection"
|
||||
connectionexported "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/exported"
|
||||
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
|
||||
ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types"
|
||||
)
|
||||
|
||||
var (
|
||||
connectionID = "connectionidone"
|
||||
clientID = "clientidone"
|
||||
connectionID2 = "connectionidtwo"
|
||||
clientID2 = "clientidtwo"
|
||||
)
|
||||
|
||||
func TestValidateGenesis(t *testing.T) {
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
genState GenesisState
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
name: "default",
|
||||
genState: DefaultGenesisState(),
|
||||
expPass: true,
|
||||
},
|
||||
{
|
||||
name: "valid genesis",
|
||||
genState: GenesisState{
|
||||
ConnectionGenesis: connection.NewGenesisState(
|
||||
[]connection.ConnectionEnd{
|
||||
connection.NewConnectionEnd(connectionexported.INIT, connectionID, clientID, connection.NewCounterparty(clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))), []string{"1.0.0"}),
|
||||
},
|
||||
[]connection.ConnectionPaths{
|
||||
connection.NewConnectionPaths(clientID, []string{ibctypes.ConnectionPath(connectionID)}),
|
||||
},
|
||||
),
|
||||
},
|
||||
expPass: true,
|
||||
},
|
||||
{
|
||||
name: "invalid connection genesis",
|
||||
genState: GenesisState{
|
||||
ConnectionGenesis: connection.NewGenesisState(
|
||||
[]connection.ConnectionEnd{
|
||||
connection.NewConnectionEnd(connectionexported.INIT, connectionID, "CLIENTIDONE", connection.NewCounterparty(clientID, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))), []string{"1.0.0"}),
|
||||
},
|
||||
nil,
|
||||
),
|
||||
},
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package ibc
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -56,8 +57,13 @@ func (AppModuleBasic) DefaultGenesis(_ codec.JSONMarshaler) json.RawMessage {
|
|||
}
|
||||
|
||||
// ValidateGenesis performs genesis state validation for the ibc module.
|
||||
func (AppModuleBasic) ValidateGenesis(_ codec.JSONMarshaler, _ json.RawMessage) error {
|
||||
return nil
|
||||
func (AppModuleBasic) ValidateGenesis(cdc codec.JSONMarshaler, bz json.RawMessage) error {
|
||||
var gs GenesisState
|
||||
if err := cdc.UnmarshalJSON(bz, &gs); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal %s genesis state: %w", ModuleName, err)
|
||||
}
|
||||
|
||||
return gs.Validate()
|
||||
}
|
||||
|
||||
// RegisterRESTRoutes registers the REST routes for the ibc module.
|
||||
|
@ -120,14 +126,20 @@ func (am AppModule) NewQuerierHandler() sdk.Querier {
|
|||
|
||||
// InitGenesis performs genesis initialization for the ibc module. It returns
|
||||
// no validator updates.
|
||||
func (am AppModule) InitGenesis(_ sdk.Context, _ codec.JSONMarshaler, _ json.RawMessage) []abci.ValidatorUpdate {
|
||||
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, bz json.RawMessage) []abci.ValidatorUpdate {
|
||||
var gs GenesisState
|
||||
err := cdc.UnmarshalJSON(bz, &gs)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to unmarshal %s genesis state: %s", ModuleName, err))
|
||||
}
|
||||
InitGenesis(ctx, *am.keeper, gs)
|
||||
return []abci.ValidatorUpdate{}
|
||||
}
|
||||
|
||||
// ExportGenesis returns the exported genesis state as raw bytes for the ibc
|
||||
// module.
|
||||
func (am AppModule) ExportGenesis(_ sdk.Context, _ codec.JSONMarshaler) json.RawMessage {
|
||||
return nil
|
||||
func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json.RawMessage {
|
||||
return cdc.MustMarshalJSON(ExportGenesis(ctx, *am.keeper))
|
||||
}
|
||||
|
||||
// BeginBlock returns the begin blocker for the ibc module.
|
||||
|
|
Loading…
Reference in New Issue