Standardize connection versioning + channel versioning docs (#6640)
* update connection versions with feature set flag * make connection version modular to support channel versioning and registering * revert IBCVersion renaming, add channel versioning logic * fix channel version flag * remove unnecessary godoc * remove unused func * fix lint and version test * add test and fix error * revert changes * update docs * remove unnecessary godoc * Apply suggestions from code review Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> * update doc * add test cases for unchecked lines * go fmt * begin migration to standardized version * revert proto changes * restructure versioning to go from string to proto * update versionStr to encodedVersion naming * fix version test build * fix keeper tests * fix various tests * fixes from self review * update docs * fix lint * add more code cov * rename ToString funcs to Encode/DecodeVersion + GetCompatibleEncodedVersions renaming * update spec docs Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
parent
839ee4f5e7
commit
5dfc4a2ec9
@ -142,6 +142,28 @@ OnChanCloseConfirm(
|
||||
}
|
||||
```
|
||||
|
||||
#### Channel Handshake Version Negotiation
|
||||
|
||||
Application modules are expected to verify versioning used during the channel handshake procedure.
|
||||
|
||||
* `ChanOpenInit` callback should verify that the `MsgChanOpenInit.Version` is valid
|
||||
* `ChanOpenTry` callback should verify that the `MsgChanOpenTry.Version` is valid and that `MsgChanOpenTry.CounterpartyVersion` is valid.
|
||||
* `ChanOpenAck` callback should verify that the `MsgChanOpenAck.CounterpartyVersion` is valid and supported.
|
||||
|
||||
Versions must be strings but can implement any versioning structure. If your application plans to
|
||||
have linear releases then semantic versioning is recommended. If your application plans to release
|
||||
various features in between major releases then it is advised to use the same versioning scheme
|
||||
as IBC. This versioning scheme specifies a version identifier and compatible feature set with
|
||||
that identifier. Valid version selection includes selecting a compatible version identifier with
|
||||
a subset of features supported by your application for that version. The struct is used for this
|
||||
scheme can be found in `03-connection/types`.
|
||||
|
||||
Since the version type is a string, applications have the ability to do simple version verification
|
||||
via string matching or they can use the already impelemented versioning system and pass the proto
|
||||
encoded version into each handhshake call as necessary.
|
||||
|
||||
ICS20 currently implements basic string matching with a single supported version.
|
||||
|
||||
### Bind Ports
|
||||
|
||||
Currently, ports must be bound on app initialization. A module may bind to ports in `InitGenesis`
|
||||
|
||||
@ -9,70 +9,97 @@ import "ibc/commitment/commitment.proto";
|
||||
// MsgConnectionOpenInit defines the msg sent by an account on Chain A to
|
||||
// initialize a connection with Chain B.
|
||||
message MsgConnectionOpenInit {
|
||||
string client_id = 1 [(gogoproto.customname) = "ClientID", (gogoproto.moretags) = "yaml:\"client_id\""];
|
||||
string connection_id = 2 [(gogoproto.customname) = "ConnectionID", (gogoproto.moretags) = "yaml:\"connection_id\""];
|
||||
Counterparty counterparty = 3 [(gogoproto.nullable) = false];
|
||||
bytes signer = 4 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
|
||||
string client_id = 1 [
|
||||
(gogoproto.customname) = "ClientID",
|
||||
(gogoproto.moretags) = "yaml:\"client_id\""
|
||||
];
|
||||
string connection_id = 2 [
|
||||
(gogoproto.customname) = "ConnectionID",
|
||||
(gogoproto.moretags) = "yaml:\"connection_id\""
|
||||
];
|
||||
Counterparty counterparty = 3 [(gogoproto.nullable) = false];
|
||||
bytes signer = 4
|
||||
[(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
|
||||
}
|
||||
|
||||
// MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a connection
|
||||
// on Chain B.
|
||||
// MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a
|
||||
// connection on Chain B.
|
||||
message MsgConnectionOpenTry {
|
||||
string client_id = 1 [(gogoproto.customname) = "ClientID", (gogoproto.moretags) = "yaml:\"client_id\""];
|
||||
string connection_id = 2 [(gogoproto.customname) = "ConnectionID", (gogoproto.moretags) = "yaml:\"connection_id\""];
|
||||
Counterparty counterparty = 3 [(gogoproto.nullable) = false];
|
||||
repeated string counterparty_versions = 4 [(gogoproto.moretags) = "yaml:\"counterparty_versions\""];
|
||||
// proof of the initialization the connection on Chain A: `UNITIALIZED -> INIT`
|
||||
bytes proof_init = 5 [(gogoproto.moretags) = "yaml:\"proof_init\""];
|
||||
string client_id = 1 [
|
||||
(gogoproto.customname) = "ClientID",
|
||||
(gogoproto.moretags) = "yaml:\"client_id\""
|
||||
];
|
||||
string connection_id = 2 [
|
||||
(gogoproto.customname) = "ConnectionID",
|
||||
(gogoproto.moretags) = "yaml:\"connection_id\""
|
||||
];
|
||||
Counterparty counterparty = 3 [(gogoproto.nullable) = false];
|
||||
repeated string counterparty_versions = 4 [
|
||||
(gogoproto.moretags) = "yaml:\"counterparty_versions\""
|
||||
];
|
||||
// proof of the initialization the connection on Chain A: `UNITIALIZED ->
|
||||
// INIT`
|
||||
bytes proof_init = 5 [(gogoproto.moretags) = "yaml:\"proof_init\""];
|
||||
uint64 proof_height = 6;
|
||||
// proof of client consensus state
|
||||
bytes proof_consensus = 7
|
||||
[(gogoproto.moretags) = "yaml:\"proof_consensus\""];
|
||||
uint64 consensus_height = 8 [(gogoproto.moretags) = "yaml:\"consensus_height\""];
|
||||
bytes signer = 9 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
|
||||
bytes proof_consensus = 7 [(gogoproto.moretags) = "yaml:\"proof_consensus\""];
|
||||
uint64 consensus_height = 8
|
||||
[(gogoproto.moretags) = "yaml:\"consensus_height\""];
|
||||
bytes signer = 9
|
||||
[(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
|
||||
}
|
||||
|
||||
// MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to acknowledge
|
||||
// the change of connection state to TRYOPEN on Chain B.
|
||||
// MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to
|
||||
// acknowledge the change of connection state to TRYOPEN on Chain B.
|
||||
message MsgConnectionOpenAck {
|
||||
string connection_id = 1 [(gogoproto.customname) = "ConnectionID", (gogoproto.moretags) = "yaml:\"connection_id\""];
|
||||
string version = 2;
|
||||
// proof of the initialization the connection on Chain B: `UNITIALIZED -> TRYOPEN`
|
||||
bytes proof_try = 3
|
||||
[(gogoproto.moretags) = "yaml:\"proof_try\""];
|
||||
string connection_id = 1 [
|
||||
(gogoproto.customname) = "ConnectionID",
|
||||
(gogoproto.moretags) = "yaml:\"connection_id\""
|
||||
];
|
||||
string version = 2;
|
||||
// proof of the initialization the connection on Chain B: `UNITIALIZED ->
|
||||
// TRYOPEN`
|
||||
bytes proof_try = 3 [(gogoproto.moretags) = "yaml:\"proof_try\""];
|
||||
uint64 proof_height = 4 [(gogoproto.moretags) = "yaml:\"proof_height\""];
|
||||
// proof of client consensus state
|
||||
bytes proof_consensus = 5
|
||||
[(gogoproto.moretags) = "yaml:\"proof_consensus\""];
|
||||
uint64 consensus_height = 6 [(gogoproto.moretags) = "yaml:\"consensus_height\""];
|
||||
bytes signer = 7 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
|
||||
bytes proof_consensus = 5 [(gogoproto.moretags) = "yaml:\"proof_consensus\""];
|
||||
uint64 consensus_height = 6
|
||||
[(gogoproto.moretags) = "yaml:\"consensus_height\""];
|
||||
bytes signer = 7
|
||||
[(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
|
||||
}
|
||||
|
||||
// MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to acknowledge
|
||||
// the change of connection state to OPEN on Chain A.
|
||||
// MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to
|
||||
// acknowledge the change of connection state to OPEN on Chain A.
|
||||
message MsgConnectionOpenConfirm {
|
||||
string connection_id = 1 [(gogoproto.customname) = "ConnectionID", (gogoproto.moretags) = "yaml:\"connection_id\""];
|
||||
string connection_id = 1 [
|
||||
(gogoproto.customname) = "ConnectionID",
|
||||
(gogoproto.moretags) = "yaml:\"connection_id\""
|
||||
];
|
||||
// proof for the change of the connection state on Chain A: `INIT -> OPEN`
|
||||
bytes proof_ack = 2
|
||||
[(gogoproto.moretags) = "yaml:\"proof_ack\""];
|
||||
bytes proof_ack = 2 [(gogoproto.moretags) = "yaml:\"proof_ack\""];
|
||||
uint64 proof_height = 3 [(gogoproto.moretags) = "yaml:\"proof_height\""];
|
||||
bytes signer = 4 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
|
||||
bytes signer = 4
|
||||
[(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
|
||||
}
|
||||
|
||||
// ICS03 - Connection Data Structures as defined in
|
||||
// https://github.com/cosmos/ics/tree/master/spec/ics-003-connection-semantics#data-structures
|
||||
|
||||
// ConnectionEnd defines a stateful object on a chain connected to another separate
|
||||
// one.
|
||||
// NOTE: there must only be 2 defined ConnectionEnds to establish a connection
|
||||
// between two chains.
|
||||
// ConnectionEnd defines a stateful object on a chain connected to another
|
||||
// separate one. NOTE: there must only be 2 defined ConnectionEnds to establish
|
||||
// a connection between two chains.
|
||||
message ConnectionEnd {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
// connection identifier.
|
||||
string id = 1 [(gogoproto.customname) = "ID", (gogoproto.moretags) = "yaml:\"id\""];
|
||||
string id = 1
|
||||
[(gogoproto.customname) = "ID", (gogoproto.moretags) = "yaml:\"id\""];
|
||||
// client associated with this connection.
|
||||
string client_id = 2 [(gogoproto.customname) = "ClientID", (gogoproto.moretags) = "yaml:\"client_id\""];
|
||||
// opaque string which can be utilised to determine encodings or protocols for
|
||||
string client_id = 2 [
|
||||
(gogoproto.customname) = "ClientID",
|
||||
(gogoproto.moretags) = "yaml:\"client_id\""
|
||||
];
|
||||
// IBC version which can be utilised to determine encodings or protocols for
|
||||
// channels or packets utilising this connection
|
||||
repeated string versions = 3;
|
||||
// current state of the connection end.
|
||||
@ -87,10 +114,12 @@ enum State {
|
||||
option (gogoproto.goproto_enum_prefix) = false;
|
||||
|
||||
// Default State
|
||||
STATE_UNINITIALIZED_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "UNINITIALIZED"];
|
||||
STATE_UNINITIALIZED_UNSPECIFIED = 0
|
||||
[(gogoproto.enumvalue_customname) = "UNINITIALIZED"];
|
||||
// A connection end has just started the opening handshake.
|
||||
STATE_INIT = 1 [(gogoproto.enumvalue_customname) = "INIT"];
|
||||
// A connection end has acknowledged the handshake step on the counterparty chain.
|
||||
// A connection end has acknowledged the handshake step on the counterparty
|
||||
// chain.
|
||||
STATE_TRYOPEN = 2 [(gogoproto.enumvalue_customname) = "TRYOPEN"];
|
||||
// A connection end has completed the handshake.
|
||||
STATE_OPEN = 3 [(gogoproto.enumvalue_customname) = "OPEN"];
|
||||
@ -100,10 +129,18 @@ enum State {
|
||||
message Counterparty {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// identifies the client on the counterparty chain associated with a given connection.
|
||||
string client_id = 1 [(gogoproto.customname) = "ClientID", (gogoproto.moretags) = "yaml:\"client_id\""];
|
||||
// identifies the connection end on the counterparty chain associated with a given connection.
|
||||
string connection_id = 2 [(gogoproto.customname) = "ConnectionID", (gogoproto.moretags) = "yaml:\"connection_id\""];
|
||||
// identifies the client on the counterparty chain associated with a given
|
||||
// connection.
|
||||
string client_id = 1 [
|
||||
(gogoproto.customname) = "ClientID",
|
||||
(gogoproto.moretags) = "yaml:\"client_id\""
|
||||
];
|
||||
// identifies the connection end on the counterparty chain associated with a
|
||||
// given connection.
|
||||
string connection_id = 2 [
|
||||
(gogoproto.customname) = "ConnectionID",
|
||||
(gogoproto.moretags) = "yaml:\"connection_id\""
|
||||
];
|
||||
// commitment merkle prefix of the counterparty chain
|
||||
ibc.commitment.MerklePrefix prefix = 3 [(gogoproto.nullable) = false];
|
||||
}
|
||||
@ -117,7 +154,21 @@ message ClientPaths {
|
||||
// ConnectionPaths define all the connection paths for a given client state.
|
||||
message ConnectionPaths {
|
||||
// client state unique identifier
|
||||
string client_id = 1 [(gogoproto.customname) = "ClientID", (gogoproto.moretags) = "yaml:\"client_id\""];
|
||||
string client_id = 1 [
|
||||
(gogoproto.customname) = "ClientID",
|
||||
(gogoproto.moretags) = "yaml:\"client_id\""
|
||||
];
|
||||
// list of connection paths
|
||||
repeated string paths = 2;
|
||||
}
|
||||
|
||||
// Version defines the versioning scheme used to negotiate the IBC verison in
|
||||
// the connection handshake.
|
||||
message Version {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// unique version identifier
|
||||
string identifier = 1;
|
||||
// list of features compatible with the specified identifier
|
||||
repeated string features = 2;
|
||||
}
|
||||
|
||||
@ -284,7 +284,7 @@ func (chain *TestChain) createConnection(
|
||||
State: state,
|
||||
ClientID: clientID,
|
||||
Counterparty: counterparty,
|
||||
Versions: connectiontypes.GetCompatibleVersions(),
|
||||
Versions: connectiontypes.GetCompatibleEncodedVersions(),
|
||||
}
|
||||
ctx := chain.GetContext()
|
||||
chain.App.IBCKeeper.ConnectionKeeper.SetConnection(ctx, connID, connection)
|
||||
|
||||
@ -259,7 +259,7 @@ func (chain *TestChain) createConnection(
|
||||
State: state,
|
||||
ClientID: clientID,
|
||||
Counterparty: counterparty,
|
||||
Versions: connectiontypes.GetCompatibleVersions(),
|
||||
Versions: connectiontypes.GetCompatibleEncodedVersions(),
|
||||
}
|
||||
ctx := chain.GetContext()
|
||||
chain.App.IBCKeeper.ConnectionKeeper.SetConnection(ctx, connID, connection)
|
||||
|
||||
@ -195,7 +195,7 @@ func (am AppModule) OnChanOpenInit(
|
||||
}
|
||||
|
||||
if version != types.Version {
|
||||
return sdkerrors.Wrapf(types.ErrInvalidVersion, "got: %s, expected %s", version, types.Version)
|
||||
return sdkerrors.Wrapf(types.ErrInvalidVersion, "got %s, expected %s", version, types.Version)
|
||||
}
|
||||
|
||||
// Claim channel capability passed back by IBC module
|
||||
|
||||
@ -9,5 +9,5 @@ var (
|
||||
ErrInvalidPacketTimeout = sdkerrors.Register(ModuleName, 2, "invalid packet timeout")
|
||||
ErrOnlyOneDenomAllowed = sdkerrors.Register(ModuleName, 3, "only one denom allowed")
|
||||
ErrInvalidDenomForTransfer = sdkerrors.Register(ModuleName, 4, "invalid denomination for cross-chain transfer")
|
||||
ErrInvalidVersion = sdkerrors.Register(ModuleName, 5, "invalid version")
|
||||
ErrInvalidVersion = sdkerrors.Register(ModuleName, 5, "invalid ICS20 version")
|
||||
)
|
||||
|
||||
@ -50,7 +50,7 @@ func (suite *KeeperTestSuite) TestQueryConnection() {
|
||||
connB := suite.chainB.GetFirstTestConnection(clientB, clientA)
|
||||
|
||||
counterparty := types.NewCounterparty(clientB, connB.ID, suite.chainB.GetPrefix())
|
||||
expConnection = types.NewConnectionEnd(types.INIT, connA.ID, clientA, counterparty, types.GetCompatibleVersions())
|
||||
expConnection = types.NewConnectionEnd(types.INIT, connA.ID, clientA, counterparty, types.GetCompatibleEncodedVersions())
|
||||
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), connA.ID, expConnection)
|
||||
|
||||
req = &types.QueryConnectionRequest{
|
||||
@ -119,9 +119,9 @@ func (suite *KeeperTestSuite) TestQueryConnections() {
|
||||
counterparty2 := types.NewCounterparty(clientB, connB1.ID, suite.chainB.GetPrefix())
|
||||
counterparty3 := types.NewCounterparty(clientB1, connB2.ID, suite.chainB.GetPrefix())
|
||||
|
||||
conn1 := types.NewConnectionEnd(types.OPEN, connA0.ID, clientA, counterparty1, types.GetCompatibleVersions())
|
||||
conn2 := types.NewConnectionEnd(types.INIT, connA1.ID, clientA, counterparty2, types.GetCompatibleVersions())
|
||||
conn3 := types.NewConnectionEnd(types.OPEN, connA2.ID, clientA1, counterparty3, types.GetCompatibleVersions())
|
||||
conn1 := types.NewConnectionEnd(types.OPEN, connA0.ID, clientA, counterparty1, types.GetCompatibleEncodedVersions())
|
||||
conn2 := types.NewConnectionEnd(types.INIT, connA1.ID, clientA, counterparty2, types.GetCompatibleEncodedVersions())
|
||||
conn3 := types.NewConnectionEnd(types.OPEN, connA2.ID, clientA1, counterparty3, types.GetCompatibleEncodedVersions())
|
||||
|
||||
expConnections = []*types.ConnectionEnd{&conn1, &conn2, &conn3}
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ func (k Keeper) ConnOpenInit(
|
||||
}
|
||||
|
||||
// connection defines chain A's ConnectionEnd
|
||||
connection := types.NewConnectionEnd(types.INIT, connectionID, clientID, counterparty, types.GetCompatibleVersions())
|
||||
connection := types.NewConnectionEnd(types.INIT, connectionID, clientID, counterparty, types.GetCompatibleEncodedVersions())
|
||||
k.SetConnection(ctx, connectionID, connection)
|
||||
|
||||
if err := k.addConnectionToClient(ctx, clientID, connectionID); err != nil {
|
||||
@ -128,7 +128,7 @@ func (k Keeper) ConnOpenTry(
|
||||
func (k Keeper) ConnOpenAck(
|
||||
ctx sdk.Context,
|
||||
connectionID string,
|
||||
version string, // version that ChainB chose in ConnOpenTry
|
||||
encodedVersion string, // version that ChainB chose in ConnOpenTry
|
||||
proofTry []byte, // proof that connectionEnd was added to ChainB state in ConnOpenTry
|
||||
proofConsensus []byte, // proof that chainB has stored ConsensusState of chainA on its client
|
||||
proofHeight uint64, // height that relayer constructed proofTry
|
||||
@ -156,7 +156,12 @@ func (k Keeper) ConnOpenAck(
|
||||
)
|
||||
}
|
||||
|
||||
// Check that ChainB's proposed version number is supported by chainA
|
||||
version, err := types.DecodeVersion(encodedVersion)
|
||||
if err != nil {
|
||||
return sdkerrors.Wrap(err, "version negotiation failed")
|
||||
}
|
||||
|
||||
// Check that ChainB's proposed version identifier is supported by chainA
|
||||
supportedVersion, found := types.FindSupportedVersion(version, types.GetCompatibleVersions())
|
||||
if !found {
|
||||
return sdkerrors.Wrapf(
|
||||
@ -166,11 +171,8 @@ func (k Keeper) ConnOpenAck(
|
||||
}
|
||||
|
||||
// Check that ChainB's proposed feature set is supported by chainA
|
||||
if !types.VerifyProposedFeatureSet(version, supportedVersion) {
|
||||
return sdkerrors.Wrapf(
|
||||
types.ErrVersionNegotiationFailed,
|
||||
"connection version feature set provided (%s) is not supported (%s)", version, types.GetCompatibleVersions(),
|
||||
)
|
||||
if err := supportedVersion.VerifyProposedVersion(version); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Retrieve chainA's consensus state at consensusheight
|
||||
@ -181,7 +183,7 @@ func (k Keeper) ConnOpenAck(
|
||||
|
||||
prefix := k.GetCommitmentPrefix()
|
||||
expectedCounterparty := types.NewCounterparty(connection.ClientID, connectionID, commitmenttypes.NewMerklePrefix(prefix.Bytes()))
|
||||
expectedConnection := types.NewConnectionEnd(types.TRYOPEN, connection.Counterparty.ConnectionID, connection.Counterparty.ClientID, expectedCounterparty, []string{version})
|
||||
expectedConnection := types.NewConnectionEnd(types.TRYOPEN, connection.Counterparty.ConnectionID, connection.Counterparty.ClientID, expectedCounterparty, []string{encodedVersion})
|
||||
|
||||
// Ensure that ChainB stored expected connectionEnd in its state during ConnOpenTry
|
||||
if err := k.VerifyConnectionState(
|
||||
@ -202,7 +204,7 @@ func (k Keeper) ConnOpenAck(
|
||||
|
||||
// Update connection state to Open
|
||||
connection.State = types.OPEN
|
||||
connection.Versions = []string{version}
|
||||
connection.Versions = []string{encodedVersion}
|
||||
k.SetConnection(ctx, connectionID, connection)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -102,7 +102,9 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
|
||||
_, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
versions = []string{"(version won't match,[])"}
|
||||
version, err := types.NewVersion("0.0", nil).Encode()
|
||||
suite.Require().NoError(err)
|
||||
versions = []string{version}
|
||||
}, false},
|
||||
{"connection state verification failed", func() {
|
||||
clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, clientexported.Tendermint)
|
||||
@ -140,9 +142,9 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
|
||||
tc := tc
|
||||
|
||||
suite.Run(tc.msg, func() {
|
||||
suite.SetupTest() // reset
|
||||
consensusHeight = 0 // must be explicitly changed in malleate
|
||||
versions = types.GetCompatibleVersions() // must be explicitly changed in malleate
|
||||
suite.SetupTest() // reset
|
||||
consensusHeight = 0 // must be explicitly changed in malleate
|
||||
versions = types.GetCompatibleEncodedVersions() // must be explicitly changed in malleate
|
||||
|
||||
tc.malleate()
|
||||
|
||||
@ -266,6 +268,17 @@ func (suite *KeeperTestSuite) TestConnOpenAck() {
|
||||
|
||||
version = ""
|
||||
}, false},
|
||||
{"feature set verification failed - unsupported feature", func() {
|
||||
clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, clientexported.Tendermint)
|
||||
connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
version, err = types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"ORDER_ORDERED", "ORDER_UNORDERED", "ORDER_DAG"}).Encode()
|
||||
suite.Require().NoError(err)
|
||||
}, false},
|
||||
{"self consensus state not found", func() {
|
||||
clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, clientexported.Tendermint)
|
||||
connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
|
||||
@ -305,9 +318,9 @@ func (suite *KeeperTestSuite) TestConnOpenAck() {
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
suite.Run(tc.msg, func() {
|
||||
suite.SetupTest() // reset
|
||||
version = types.GetCompatibleVersions()[0] // must be explicitly changed in malleate
|
||||
consensusHeight = 0 // must be explicitly changed in malleate
|
||||
suite.SetupTest() // reset
|
||||
version = types.GetCompatibleEncodedVersions()[0] // must be explicitly changed in malleate
|
||||
consensusHeight = 0 // must be explicitly changed in malleate
|
||||
|
||||
tc.malleate()
|
||||
|
||||
|
||||
@ -47,10 +47,10 @@ func (suite *KeeperTestSuite) TestSetAndGetClientConnectionPaths() {
|
||||
_, existed := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetClientConnectionPaths(suite.chainA.GetContext(), clientA)
|
||||
suite.False(existed)
|
||||
|
||||
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetClientConnectionPaths(suite.chainA.GetContext(), clientA, types.GetCompatibleVersions())
|
||||
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetClientConnectionPaths(suite.chainA.GetContext(), clientA, types.GetCompatibleEncodedVersions())
|
||||
paths, existed := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetClientConnectionPaths(suite.chainA.GetContext(), clientA)
|
||||
suite.True(existed)
|
||||
suite.EqualValues(types.GetCompatibleVersions(), paths)
|
||||
suite.EqualValues(types.GetCompatibleEncodedVersions(), paths)
|
||||
}
|
||||
|
||||
// create 2 connections: A0 - B0, A1 - B1
|
||||
@ -61,8 +61,8 @@ func (suite KeeperTestSuite) TestGetAllConnections() {
|
||||
counterpartyB0 := types.NewCounterparty(clientB, connB0.ID, suite.chainB.GetPrefix()) // connection B0
|
||||
counterpartyB1 := types.NewCounterparty(clientB, connB1.ID, suite.chainB.GetPrefix()) // connection B1
|
||||
|
||||
conn1 := types.NewConnectionEnd(types.OPEN, connA0.ID, clientA, counterpartyB0, types.GetCompatibleVersions()) // A0 - B0
|
||||
conn2 := types.NewConnectionEnd(types.OPEN, connA1.ID, clientA, counterpartyB1, types.GetCompatibleVersions()) // A1 - B1
|
||||
conn1 := types.NewConnectionEnd(types.OPEN, connA0.ID, clientA, counterpartyB0, types.GetCompatibleEncodedVersions()) // A0 - B0
|
||||
conn2 := types.NewConnectionEnd(types.OPEN, connA1.ID, clientA, counterpartyB1, types.GetCompatibleEncodedVersions()) // A1 - B1
|
||||
expConnections := []types.ConnectionEnd{conn1, conn2}
|
||||
|
||||
connections := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetAllConnections(suite.chainA.GetContext())
|
||||
|
||||
@ -60,7 +60,7 @@ func (c ConnectionEnd) ValidateBasic() error {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrInvalidVersion, "empty connection versions")
|
||||
}
|
||||
for _, version := range c.Versions {
|
||||
if err := host.ConnectionVersionValidator(version); err != nil {
|
||||
if err := ValidateVersion(version); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,7 +34,8 @@ const (
|
||||
UNINITIALIZED State = 0
|
||||
// A connection end has just started the opening handshake.
|
||||
INIT State = 1
|
||||
// A connection end has acknowledged the handshake step on the counterparty chain.
|
||||
// A connection end has acknowledged the handshake step on the counterparty
|
||||
// chain.
|
||||
TRYOPEN State = 2
|
||||
// A connection end has completed the handshake.
|
||||
OPEN State = 3
|
||||
@ -132,14 +133,15 @@ func (m *MsgConnectionOpenInit) GetSigner() github_com_cosmos_cosmos_sdk_types.A
|
||||
return nil
|
||||
}
|
||||
|
||||
// MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a connection
|
||||
// on Chain B.
|
||||
// MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a
|
||||
// connection on Chain B.
|
||||
type MsgConnectionOpenTry struct {
|
||||
ClientID string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"`
|
||||
ConnectionID string `protobuf:"bytes,2,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"`
|
||||
Counterparty Counterparty `protobuf:"bytes,3,opt,name=counterparty,proto3" json:"counterparty"`
|
||||
CounterpartyVersions []string `protobuf:"bytes,4,rep,name=counterparty_versions,json=counterpartyVersions,proto3" json:"counterparty_versions,omitempty" yaml:"counterparty_versions"`
|
||||
// proof of the initialization the connection on Chain A: `UNITIALIZED -> INIT`
|
||||
// proof of the initialization the connection on Chain A: `UNITIALIZED ->
|
||||
// INIT`
|
||||
ProofInit []byte `protobuf:"bytes,5,opt,name=proof_init,json=proofInit,proto3" json:"proof_init,omitempty" yaml:"proof_init"`
|
||||
ProofHeight uint64 `protobuf:"varint,6,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height,omitempty"`
|
||||
// proof of client consensus state
|
||||
@ -244,12 +246,13 @@ func (m *MsgConnectionOpenTry) GetSigner() github_com_cosmos_cosmos_sdk_types.Ac
|
||||
return nil
|
||||
}
|
||||
|
||||
// MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to acknowledge
|
||||
// the change of connection state to TRYOPEN on Chain B.
|
||||
// MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to
|
||||
// acknowledge the change of connection state to TRYOPEN on Chain B.
|
||||
type MsgConnectionOpenAck struct {
|
||||
ConnectionID string `protobuf:"bytes,1,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"`
|
||||
Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
|
||||
// proof of the initialization the connection on Chain B: `UNITIALIZED -> TRYOPEN`
|
||||
// proof of the initialization the connection on Chain B: `UNITIALIZED ->
|
||||
// TRYOPEN`
|
||||
ProofTry []byte `protobuf:"bytes,3,opt,name=proof_try,json=proofTry,proto3" json:"proof_try,omitempty" yaml:"proof_try"`
|
||||
ProofHeight uint64 `protobuf:"varint,4,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height,omitempty" yaml:"proof_height"`
|
||||
// proof of client consensus state
|
||||
@ -340,8 +343,8 @@ func (m *MsgConnectionOpenAck) GetSigner() github_com_cosmos_cosmos_sdk_types.Ac
|
||||
return nil
|
||||
}
|
||||
|
||||
// MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to acknowledge
|
||||
// the change of connection state to OPEN on Chain A.
|
||||
// MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to
|
||||
// acknowledge the change of connection state to OPEN on Chain A.
|
||||
type MsgConnectionOpenConfirm struct {
|
||||
ConnectionID string `protobuf:"bytes,1,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"`
|
||||
// proof for the change of the connection state on Chain A: `INIT -> OPEN`
|
||||
@ -411,16 +414,15 @@ func (m *MsgConnectionOpenConfirm) GetSigner() github_com_cosmos_cosmos_sdk_type
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConnectionEnd defines a stateful object on a chain connected to another separate
|
||||
// one.
|
||||
// NOTE: there must only be 2 defined ConnectionEnds to establish a connection
|
||||
// between two chains.
|
||||
// ConnectionEnd defines a stateful object on a chain connected to another
|
||||
// separate one. NOTE: there must only be 2 defined ConnectionEnds to establish
|
||||
// a connection between two chains.
|
||||
type ConnectionEnd struct {
|
||||
// connection identifier.
|
||||
ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" yaml:"id"`
|
||||
// client associated with this connection.
|
||||
ClientID string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"`
|
||||
// opaque string which can be utilised to determine encodings or protocols for
|
||||
// IBC version which can be utilised to determine encodings or protocols for
|
||||
// channels or packets utilising this connection
|
||||
Versions []string `protobuf:"bytes,3,rep,name=versions,proto3" json:"versions,omitempty"`
|
||||
// current state of the connection end.
|
||||
@ -464,9 +466,11 @@ var xxx_messageInfo_ConnectionEnd proto.InternalMessageInfo
|
||||
|
||||
// Counterparty defines the counterparty chain associated with a connection end.
|
||||
type Counterparty struct {
|
||||
// identifies the client on the counterparty chain associated with a given connection.
|
||||
// identifies the client on the counterparty chain associated with a given
|
||||
// connection.
|
||||
ClientID string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"`
|
||||
// identifies the connection end on the counterparty chain associated with a given connection.
|
||||
// identifies the connection end on the counterparty chain associated with a
|
||||
// given connection.
|
||||
ConnectionID string `protobuf:"bytes,2,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"`
|
||||
// commitment merkle prefix of the counterparty chain
|
||||
Prefix types.MerklePrefix `protobuf:"bytes,3,opt,name=prefix,proto3" json:"prefix"`
|
||||
@ -606,6 +610,48 @@ func (m *ConnectionPaths) GetPaths() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Version defines the versioning scheme used to negotiate the IBC verison in
|
||||
// the connection handshake.
|
||||
type Version struct {
|
||||
// unique version identifier
|
||||
Identifier string `protobuf:"bytes,1,opt,name=identifier,proto3" json:"identifier,omitempty"`
|
||||
// list of features compatible with the specified identifier
|
||||
Features []string `protobuf:"bytes,2,rep,name=features,proto3" json:"features,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Version) Reset() { *m = Version{} }
|
||||
func (m *Version) String() string { return proto.CompactTextString(m) }
|
||||
func (*Version) ProtoMessage() {}
|
||||
func (*Version) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3bf62bacf5a27ee9, []int{8}
|
||||
}
|
||||
func (m *Version) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *Version) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_Version.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *Version) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Version.Merge(m, src)
|
||||
}
|
||||
func (m *Version) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *Version) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Version.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Version proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("ibc.connection.State", State_name, State_value)
|
||||
proto.RegisterType((*MsgConnectionOpenInit)(nil), "ibc.connection.MsgConnectionOpenInit")
|
||||
@ -616,67 +662,71 @@ func init() {
|
||||
proto.RegisterType((*Counterparty)(nil), "ibc.connection.Counterparty")
|
||||
proto.RegisterType((*ClientPaths)(nil), "ibc.connection.ClientPaths")
|
||||
proto.RegisterType((*ConnectionPaths)(nil), "ibc.connection.ConnectionPaths")
|
||||
proto.RegisterType((*Version)(nil), "ibc.connection.Version")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("ibc/connection/connection.proto", fileDescriptor_3bf62bacf5a27ee9) }
|
||||
|
||||
var fileDescriptor_3bf62bacf5a27ee9 = []byte{
|
||||
// 879 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x56, 0x4f, 0x6f, 0xe2, 0x46,
|
||||
0x14, 0xc7, 0xc6, 0xfc, 0x1b, 0x20, 0x61, 0xbd, 0xd0, 0xb5, 0xdc, 0x95, 0xed, 0x7a, 0x2f, 0xa8,
|
||||
0x55, 0xa0, 0xbb, 0x5b, 0xed, 0x01, 0xa9, 0x07, 0x20, 0x44, 0xb5, 0xd4, 0xb0, 0xc8, 0x21, 0x95,
|
||||
0xba, 0x17, 0x04, 0xb6, 0x81, 0x11, 0xc1, 0x46, 0xf6, 0xa4, 0x5a, 0xbe, 0x41, 0xc4, 0xa9, 0xd7,
|
||||
0x1e, 0x22, 0x55, 0xca, 0x97, 0xe8, 0x27, 0xa8, 0x72, 0xcc, 0xb1, 0x27, 0xab, 0x22, 0xdf, 0x00,
|
||||
0xf5, 0xd4, 0x53, 0xe5, 0x19, 0x63, 0x1b, 0x88, 0x5a, 0xa5, 0xe4, 0x50, 0xf5, 0xc4, 0xfb, 0xf3,
|
||||
0x9b, 0x37, 0xef, 0xbd, 0xdf, 0xf3, 0x63, 0x80, 0x08, 0x07, 0x5a, 0x55, 0xb3, 0x4c, 0xd3, 0xd0,
|
||||
0x10, 0xb4, 0xcc, 0x88, 0x58, 0x99, 0xd9, 0x16, 0xb2, 0xd8, 0x03, 0x38, 0xd0, 0x2a, 0xa1, 0x95,
|
||||
0x2f, 0x8e, 0xac, 0x91, 0x85, 0x5d, 0x55, 0x4f, 0x22, 0x28, 0xde, 0x0f, 0x33, 0x9d, 0x42, 0x34,
|
||||
0x35, 0x4c, 0x14, 0x11, 0x09, 0x40, 0xfe, 0x85, 0x06, 0xa5, 0x53, 0x67, 0xd4, 0x0c, 0x02, 0xbd,
|
||||
0x9f, 0x19, 0xa6, 0x62, 0x42, 0xc4, 0x7e, 0x0d, 0x32, 0xda, 0x05, 0x34, 0x4c, 0xd4, 0x83, 0x3a,
|
||||
0x47, 0x49, 0x54, 0x39, 0xd3, 0x90, 0x96, 0xae, 0x98, 0x6e, 0x62, 0xa3, 0x72, 0xbc, 0x72, 0xc5,
|
||||
0xc2, 0xbc, 0x3f, 0xbd, 0xa8, 0xc9, 0x01, 0x4c, 0x56, 0xd3, 0x44, 0x56, 0x74, 0xf6, 0x14, 0xe4,
|
||||
0xc3, 0xec, 0xbc, 0x10, 0x34, 0x0e, 0x51, 0x5e, 0xba, 0x62, 0x2e, 0xbc, 0x0d, 0x87, 0x29, 0xfa,
|
||||
0x61, 0xa2, 0x70, 0x59, 0xcd, 0x85, 0xba, 0xa2, 0xb3, 0x27, 0x20, 0xa7, 0x59, 0x97, 0x26, 0x32,
|
||||
0xec, 0x59, 0xdf, 0x46, 0x73, 0x2e, 0x2e, 0x51, 0xe5, 0xec, 0x9b, 0x97, 0x95, 0xcd, 0x2e, 0x54,
|
||||
0x9a, 0x11, 0x4c, 0x83, 0xb9, 0x75, 0xc5, 0x98, 0xba, 0x71, 0x8e, 0x55, 0x40, 0xd2, 0x81, 0x23,
|
||||
0xd3, 0xb0, 0x39, 0x46, 0xa2, 0xca, 0xb9, 0xc6, 0xeb, 0x3f, 0x5d, 0xf1, 0x68, 0x04, 0xd1, 0xf8,
|
||||
0x72, 0x50, 0xd1, 0xac, 0x69, 0x55, 0xb3, 0x9c, 0xa9, 0xe5, 0xf8, 0x3f, 0x47, 0x8e, 0x3e, 0xa9,
|
||||
0xa2, 0xf9, 0xcc, 0x70, 0x2a, 0x75, 0x4d, 0xab, 0xeb, 0xba, 0x6d, 0x38, 0x8e, 0xea, 0x07, 0x90,
|
||||
0xff, 0x60, 0x40, 0x71, 0xa7, 0x75, 0x5d, 0x7b, 0xfe, 0x3f, 0xed, 0xdc, 0x39, 0x28, 0x45, 0xf5,
|
||||
0xde, 0x0f, 0x86, 0xed, 0x40, 0xcb, 0x74, 0x38, 0x46, 0x8a, 0x7b, 0x15, 0xae, 0x5c, 0xf1, 0xe5,
|
||||
0x3a, 0x9d, 0x07, 0x60, 0xb2, 0x5a, 0x8c, 0xda, 0xbf, 0xf3, 0xcd, 0xec, 0x57, 0x00, 0xcc, 0x6c,
|
||||
0xcb, 0x1a, 0xf6, 0xa0, 0x09, 0x11, 0x97, 0xc0, 0xa4, 0x94, 0x56, 0xae, 0xf8, 0x8c, 0xc4, 0x0a,
|
||||
0x7d, 0xb2, 0x9a, 0xc1, 0x0a, 0x1e, 0xce, 0xcf, 0x40, 0x8e, 0x78, 0xc6, 0x06, 0x1c, 0x8d, 0x11,
|
||||
0x97, 0x94, 0xa8, 0x32, 0xa3, 0x66, 0xb1, 0xed, 0x1b, 0x6c, 0x62, 0x9b, 0xe0, 0x90, 0x40, 0x34,
|
||||
0xcb, 0x74, 0x0c, 0xd3, 0xb9, 0x74, 0xb8, 0x14, 0x8e, 0xce, 0xaf, 0x5c, 0xf1, 0x93, 0x68, 0xf4,
|
||||
0x00, 0x20, 0xab, 0x07, 0xd8, 0xd2, 0x5c, 0x1b, 0xd8, 0x13, 0x50, 0x08, 0xbc, 0xeb, 0xbb, 0xd2,
|
||||
0xde, 0x5d, 0x8d, 0x4f, 0x57, 0xae, 0xf8, 0x22, 0x68, 0xff, 0x06, 0x42, 0x56, 0x0f, 0x03, 0x93,
|
||||
0x9f, 0x4c, 0x38, 0x76, 0x99, 0x7d, 0xc7, 0xee, 0xd7, 0xf8, 0x03, 0x63, 0x57, 0xd7, 0x26, 0xbb,
|
||||
0x73, 0x43, 0xed, 0x35, 0x37, 0x1c, 0x48, 0xf9, 0xdc, 0x91, 0x01, 0x54, 0xd7, 0x2a, 0xfb, 0x1a,
|
||||
0x10, 0x26, 0x7a, 0xc8, 0x26, 0xe3, 0x94, 0x6b, 0x14, 0xc3, 0x99, 0x0e, 0x5c, 0xb2, 0x9a, 0xc6,
|
||||
0xb2, 0xf7, 0x49, 0xd4, 0xb6, 0xf8, 0x62, 0x70, 0x0f, 0x5f, 0xac, 0x5c, 0xf1, 0x79, 0xf4, 0xd4,
|
||||
0xba, 0x7f, 0xff, 0x44, 0x64, 0xe2, 0x49, 0x88, 0x4c, 0xee, 0x45, 0x64, 0x6a, 0x5f, 0x22, 0x6f,
|
||||
0x68, 0xc0, 0xed, 0x10, 0xd9, 0xb4, 0xcc, 0x21, 0xb4, 0xa7, 0x4f, 0x4d, 0x66, 0x40, 0x59, 0x5f,
|
||||
0x9b, 0x60, 0x3a, 0x1f, 0xa0, 0xac, 0xaf, 0x4d, 0xd6, 0x94, 0x79, 0xe3, 0xb4, 0x4d, 0x59, 0xfc,
|
||||
0x11, 0x94, 0x3d, 0xe1, 0x96, 0x5d, 0xd0, 0x20, 0x1f, 0x16, 0xdc, 0x32, 0x75, 0xf6, 0x15, 0xa0,
|
||||
0x83, 0x7e, 0x3c, 0x5f, 0xba, 0x22, 0x8d, 0xbb, 0x90, 0x21, 0x49, 0x79, 0xa5, 0xd3, 0x50, 0xdf,
|
||||
0xdc, 0xc1, 0xf4, 0xa3, 0x77, 0x30, 0x0f, 0xd2, 0xc1, 0x7e, 0x8b, 0x7b, 0xfb, 0x4d, 0x0d, 0x74,
|
||||
0xf6, 0x0b, 0x90, 0x70, 0x50, 0x1f, 0x19, 0xb8, 0xb6, 0x83, 0x37, 0xa5, 0xed, 0x4d, 0x7a, 0xe6,
|
||||
0x39, 0x55, 0x82, 0xd9, 0xd9, 0xbe, 0x89, 0x7f, 0xb7, 0x7d, 0x6b, 0xcc, 0xd5, 0xcf, 0x62, 0x4c,
|
||||
0x76, 0x29, 0x90, 0x8b, 0x42, 0xff, 0x63, 0x7f, 0x35, 0x35, 0x90, 0x9c, 0xd9, 0xc6, 0x10, 0x7e,
|
||||
0xdc, 0xfa, 0x93, 0x09, 0xde, 0x1c, 0xa7, 0x86, 0x3d, 0xb9, 0x30, 0x3a, 0x18, 0xe3, 0x97, 0xe9,
|
||||
0x9f, 0xf0, 0x0b, 0x7c, 0x05, 0xb2, 0x24, 0xf5, 0x4e, 0x1f, 0x8d, 0x1d, 0xb6, 0x08, 0x12, 0x33,
|
||||
0x4f, 0xe0, 0x28, 0xcc, 0x01, 0x51, 0xe4, 0x21, 0x38, 0x0c, 0x93, 0x23, 0xc0, 0x3d, 0xfb, 0x10,
|
||||
0xdc, 0x43, 0x47, 0xee, 0xf9, 0xfc, 0x27, 0x0a, 0x24, 0x30, 0x99, 0xec, 0x3b, 0x20, 0x9e, 0x75,
|
||||
0xeb, 0xdd, 0x56, 0xef, 0xbc, 0xad, 0xb4, 0x95, 0xae, 0x52, 0xff, 0x56, 0xf9, 0xd0, 0x3a, 0xee,
|
||||
0x9d, 0xb7, 0xcf, 0x3a, 0xad, 0xa6, 0x72, 0xa2, 0xb4, 0x8e, 0x0b, 0x31, 0xfe, 0xd9, 0xe2, 0x5a,
|
||||
0xca, 0x6f, 0x00, 0x58, 0x0e, 0x00, 0x72, 0xce, 0x33, 0x16, 0x28, 0x3e, 0xbd, 0xb8, 0x96, 0x18,
|
||||
0x4f, 0x66, 0x05, 0x90, 0x27, 0x9e, 0xae, 0xfa, 0xfd, 0xfb, 0x4e, 0xab, 0x5d, 0xa0, 0xf9, 0xec,
|
||||
0xe2, 0x5a, 0x4a, 0xf9, 0x6a, 0x78, 0x12, 0x3b, 0xe3, 0xe4, 0xa4, 0x27, 0xf3, 0xcc, 0xd5, 0x8d,
|
||||
0x10, 0x6b, 0x74, 0x6e, 0x97, 0x02, 0x75, 0xb7, 0x14, 0xa8, 0xdf, 0x97, 0x02, 0xf5, 0xe3, 0xbd,
|
||||
0x10, 0xbb, 0xbb, 0x17, 0x62, 0xbf, 0xdd, 0x0b, 0xb1, 0x0f, 0xef, 0xfe, 0xf6, 0x3b, 0xfb, 0x58,
|
||||
0xf5, 0x5e, 0x84, 0x5f, 0xbe, 0x3d, 0x8a, 0xbc, 0x2d, 0xf1, 0xb7, 0x37, 0x48, 0xe2, 0x07, 0xe1,
|
||||
0xdb, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0x37, 0x42, 0xa5, 0xea, 0x7a, 0x0a, 0x00, 0x00,
|
||||
// 914 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x56, 0xcd, 0x6e, 0xdb, 0x46,
|
||||
0x10, 0x16, 0x29, 0xea, 0x6f, 0x2c, 0xdb, 0x0a, 0x23, 0x37, 0x04, 0x1b, 0x90, 0x2c, 0x73, 0x11,
|
||||
0x5a, 0x58, 0x6a, 0x92, 0x22, 0x07, 0x03, 0x3d, 0x48, 0xb2, 0x8c, 0x12, 0xad, 0x1d, 0x81, 0x96,
|
||||
0x0b, 0x34, 0x17, 0x41, 0x26, 0x57, 0xf2, 0x42, 0x16, 0x29, 0x90, 0xeb, 0x22, 0x7e, 0x83, 0xc0,
|
||||
0xa7, 0x5e, 0x7b, 0x30, 0x50, 0x20, 0x2f, 0xd1, 0x27, 0x28, 0x72, 0xcc, 0xb1, 0x27, 0xa2, 0x90,
|
||||
0xdf, 0x40, 0xe8, 0xa9, 0xa7, 0x82, 0xbb, 0x14, 0x49, 0x59, 0x46, 0x8b, 0x54, 0x3e, 0x14, 0x39,
|
||||
0x71, 0x7e, 0xbe, 0x9d, 0xdd, 0x99, 0x6f, 0x38, 0xbb, 0xa0, 0xe2, 0x53, 0xab, 0x61, 0xb9, 0x8e,
|
||||
0x83, 0x2c, 0x82, 0x5d, 0x27, 0x25, 0xd6, 0xa7, 0x9e, 0x4b, 0x5c, 0x71, 0x0b, 0x9f, 0x5a, 0xf5,
|
||||
0xc4, 0x2a, 0x57, 0x47, 0xee, 0xc8, 0xa5, 0xae, 0x46, 0x28, 0x31, 0x94, 0x1c, 0x85, 0x99, 0x4c,
|
||||
0x30, 0x99, 0x20, 0x87, 0xa4, 0x44, 0x06, 0xd0, 0x7f, 0xe5, 0x61, 0xe7, 0xd0, 0x1f, 0xb5, 0xe3,
|
||||
0x40, 0x2f, 0xa7, 0xc8, 0x31, 0x1c, 0x4c, 0xc4, 0xaf, 0xa1, 0x64, 0x9d, 0x63, 0xe4, 0x90, 0x3e,
|
||||
0xb6, 0x25, 0x4e, 0xe3, 0x6a, 0xa5, 0x96, 0x36, 0x0b, 0xd4, 0x62, 0x9b, 0x1a, 0x8d, 0xfd, 0x79,
|
||||
0xa0, 0x56, 0x2e, 0x07, 0x93, 0xf3, 0x3d, 0x3d, 0x86, 0xe9, 0x66, 0x91, 0xc9, 0x86, 0x2d, 0x1e,
|
||||
0xc2, 0x66, 0x72, 0xba, 0x30, 0x04, 0x4f, 0x43, 0xd4, 0x66, 0x81, 0x5a, 0x4e, 0x76, 0xa3, 0x61,
|
||||
0xaa, 0x51, 0x98, 0x34, 0x5c, 0x37, 0xcb, 0x89, 0x6e, 0xd8, 0xe2, 0x01, 0x94, 0x2d, 0xf7, 0xc2,
|
||||
0x21, 0xc8, 0x9b, 0x0e, 0x3c, 0x72, 0x29, 0x65, 0x35, 0xae, 0xb6, 0xf1, 0xec, 0x71, 0x7d, 0xb9,
|
||||
0x0a, 0xf5, 0x76, 0x0a, 0xd3, 0x12, 0xde, 0x05, 0x6a, 0xc6, 0x5c, 0x5a, 0x27, 0x1a, 0x90, 0xf7,
|
||||
0xf1, 0xc8, 0x41, 0x9e, 0x24, 0x68, 0x5c, 0xad, 0xdc, 0x7a, 0xfa, 0x57, 0xa0, 0xee, 0x8e, 0x30,
|
||||
0x39, 0xbb, 0x38, 0xad, 0x5b, 0xee, 0xa4, 0x61, 0xb9, 0xfe, 0xc4, 0xf5, 0xa3, 0xcf, 0xae, 0x6f,
|
||||
0x8f, 0x1b, 0xe4, 0x72, 0x8a, 0xfc, 0x7a, 0xd3, 0xb2, 0x9a, 0xb6, 0xed, 0x21, 0xdf, 0x37, 0xa3,
|
||||
0x00, 0xfa, 0x9f, 0x02, 0x54, 0x57, 0x4a, 0xd7, 0xf3, 0x2e, 0x3f, 0xd2, 0xca, 0x9d, 0xc0, 0x4e,
|
||||
0x5a, 0xef, 0xff, 0x88, 0x3c, 0x1f, 0xbb, 0x8e, 0x2f, 0x09, 0x5a, 0x36, 0xcc, 0x70, 0x1e, 0xa8,
|
||||
0x8f, 0x17, 0xc7, 0xb9, 0x03, 0xa6, 0x9b, 0xd5, 0xb4, 0xfd, 0xfb, 0xc8, 0x2c, 0x7e, 0x05, 0x30,
|
||||
0xf5, 0x5c, 0x77, 0xd8, 0xc7, 0x0e, 0x26, 0x52, 0x8e, 0x92, 0xb2, 0x33, 0x0f, 0xd4, 0x07, 0x2c,
|
||||
0x56, 0xe2, 0xd3, 0xcd, 0x12, 0x55, 0x68, 0x73, 0x7e, 0x06, 0x65, 0xe6, 0x39, 0x43, 0x78, 0x74,
|
||||
0x46, 0xa4, 0xbc, 0xc6, 0xd5, 0x04, 0x73, 0x83, 0xda, 0xbe, 0xa1, 0x26, 0xb1, 0x0d, 0xdb, 0x0c,
|
||||
0x62, 0xb9, 0x8e, 0x8f, 0x1c, 0xff, 0xc2, 0x97, 0x0a, 0x34, 0xba, 0x3c, 0x0f, 0xd4, 0x4f, 0xd2,
|
||||
0xd1, 0x63, 0x80, 0x6e, 0x6e, 0x51, 0x4b, 0x7b, 0x61, 0x10, 0x0f, 0xa0, 0x12, 0x7b, 0x17, 0x7b,
|
||||
0x15, 0xc3, 0xbd, 0x5a, 0x9f, 0xce, 0x03, 0xf5, 0x51, 0x5c, 0xfe, 0x25, 0x84, 0x6e, 0x6e, 0xc7,
|
||||
0xa6, 0xe8, 0x30, 0x49, 0xdb, 0x95, 0xd6, 0x6d, 0xbb, 0xdf, 0xb2, 0x77, 0xb4, 0x5d, 0xd3, 0x1a,
|
||||
0xaf, 0xf6, 0x0d, 0xb7, 0x56, 0xdf, 0x48, 0x50, 0x88, 0xb8, 0x63, 0x0d, 0x68, 0x2e, 0x54, 0xf1,
|
||||
0x29, 0x30, 0x26, 0xfa, 0xc4, 0x63, 0xed, 0x54, 0x6e, 0x55, 0x93, 0x9e, 0x8e, 0x5d, 0xba, 0x59,
|
||||
0xa4, 0x72, 0xf8, 0x4b, 0xec, 0xdd, 0xe2, 0x4b, 0xa0, 0x35, 0x7c, 0x34, 0x0f, 0xd4, 0x87, 0xe9,
|
||||
0x55, 0x8b, 0xfa, 0xfd, 0x1b, 0x91, 0xb9, 0x7b, 0x21, 0x32, 0xbf, 0x16, 0x91, 0x85, 0x75, 0x89,
|
||||
0x7c, 0xcb, 0x83, 0xb4, 0x42, 0x64, 0xdb, 0x75, 0x86, 0xd8, 0x9b, 0xdc, 0x37, 0x99, 0x31, 0x65,
|
||||
0x03, 0x6b, 0x4c, 0xe9, 0xbc, 0x83, 0xb2, 0x81, 0x35, 0x5e, 0x50, 0x16, 0xb6, 0xd3, 0x6d, 0xca,
|
||||
0xb2, 0x1f, 0x40, 0xd9, 0x3d, 0x4e, 0xd9, 0x2b, 0x1e, 0x36, 0x93, 0x84, 0x3b, 0x8e, 0x2d, 0x3e,
|
||||
0x01, 0x3e, 0xae, 0xc7, 0xc3, 0x59, 0xa0, 0xf2, 0xb4, 0x0a, 0x25, 0x76, 0xa8, 0x30, 0x75, 0x1e,
|
||||
0xdb, 0xcb, 0x33, 0x98, 0xff, 0xe0, 0x19, 0x2c, 0x43, 0x31, 0x9e, 0x6f, 0xd9, 0x70, 0xbe, 0x99,
|
||||
0xb1, 0x2e, 0x7e, 0x01, 0x39, 0x9f, 0x0c, 0x08, 0xa2, 0xb9, 0x6d, 0x3d, 0xdb, 0xb9, 0x3d, 0x49,
|
||||
0x8f, 0x43, 0xa7, 0xc9, 0x30, 0x2b, 0xd3, 0x37, 0xf7, 0xdf, 0xa6, 0xef, 0x9e, 0xf0, 0xe6, 0x17,
|
||||
0x35, 0xa3, 0x07, 0x1c, 0x94, 0xd3, 0xd0, 0xff, 0xd9, 0x55, 0xb3, 0x07, 0xf9, 0xa9, 0x87, 0x86,
|
||||
0xf8, 0xf5, 0xad, 0x4b, 0x26, 0x7e, 0x73, 0x1c, 0x22, 0x6f, 0x7c, 0x8e, 0xba, 0x14, 0x13, 0xa5,
|
||||
0x19, 0xad, 0x88, 0x12, 0x7c, 0x02, 0x1b, 0xec, 0xe8, 0xdd, 0x01, 0x39, 0xf3, 0xc5, 0x2a, 0xe4,
|
||||
0xa6, 0xa1, 0x20, 0x71, 0x94, 0x03, 0xa6, 0xe8, 0x43, 0xd8, 0x4e, 0x0e, 0xc7, 0x80, 0x6b, 0xd6,
|
||||
0x21, 0xde, 0x87, 0x4f, 0xef, 0xf3, 0x2d, 0x14, 0xa2, 0x6b, 0x4a, 0x54, 0x00, 0xb0, 0x8d, 0x1c,
|
||||
0x82, 0x87, 0x18, 0x79, 0x6c, 0x03, 0x33, 0x65, 0x09, 0xfb, 0x65, 0x88, 0x06, 0xe4, 0xc2, 0x43,
|
||||
0x8b, 0x18, 0xb1, 0xce, 0x32, 0xfb, 0xfc, 0x67, 0x0e, 0x72, 0xb4, 0x33, 0xc4, 0x17, 0xa0, 0x1e,
|
||||
0xf7, 0x9a, 0xbd, 0x4e, 0xff, 0xe4, 0xc8, 0x38, 0x32, 0x7a, 0x46, 0xf3, 0x3b, 0xe3, 0x55, 0x67,
|
||||
0xbf, 0x7f, 0x72, 0x74, 0xdc, 0xed, 0xb4, 0x8d, 0x03, 0xa3, 0xb3, 0x5f, 0xc9, 0xc8, 0x0f, 0xae,
|
||||
0xae, 0xb5, 0xcd, 0x25, 0x80, 0x28, 0x01, 0xb0, 0x75, 0xa1, 0xb1, 0xc2, 0xc9, 0xc5, 0xab, 0x6b,
|
||||
0x4d, 0x08, 0x65, 0x51, 0x81, 0x4d, 0xe6, 0xe9, 0x99, 0x3f, 0xbc, 0xec, 0x76, 0x8e, 0x2a, 0xbc,
|
||||
0xbc, 0x71, 0x75, 0xad, 0x15, 0x22, 0x35, 0x59, 0x49, 0x9d, 0x59, 0xb6, 0x32, 0x94, 0x65, 0xe1,
|
||||
0xcd, 0x5b, 0x25, 0xd3, 0xea, 0xbe, 0x9b, 0x29, 0xdc, 0xfb, 0x99, 0xc2, 0xfd, 0x31, 0x53, 0xb8,
|
||||
0x9f, 0x6e, 0x94, 0xcc, 0xfb, 0x1b, 0x25, 0xf3, 0xfb, 0x8d, 0x92, 0x79, 0xf5, 0xe2, 0x1f, 0x7f,
|
||||
0xda, 0xd7, 0x8d, 0xf0, 0x79, 0xf9, 0xe5, 0xf3, 0xdd, 0xd4, 0x43, 0x95, 0xfe, 0xc8, 0xa7, 0x79,
|
||||
0xfa, 0xba, 0x7c, 0xfe, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaf, 0x4e, 0x8d, 0xdb, 0xc7, 0x0a,
|
||||
0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *MsgConnectionOpenInit) Marshal() (dAtA []byte, err error) {
|
||||
@ -1116,6 +1166,45 @@ func (m *ConnectionPaths) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *Version) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Version) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *Version) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Features) > 0 {
|
||||
for iNdEx := len(m.Features) - 1; iNdEx >= 0; iNdEx-- {
|
||||
i -= len(m.Features[iNdEx])
|
||||
copy(dAtA[i:], m.Features[iNdEx])
|
||||
i = encodeVarintConnection(dAtA, i, uint64(len(m.Features[iNdEx])))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
}
|
||||
if len(m.Identifier) > 0 {
|
||||
i -= len(m.Identifier)
|
||||
copy(dAtA[i:], m.Identifier)
|
||||
i = encodeVarintConnection(dAtA, i, uint64(len(m.Identifier)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintConnection(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovConnection(v)
|
||||
base := offset
|
||||
@ -1333,6 +1422,25 @@ func (m *ConnectionPaths) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *Version) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Identifier)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovConnection(uint64(l))
|
||||
}
|
||||
if len(m.Features) > 0 {
|
||||
for _, s := range m.Features {
|
||||
l = len(s)
|
||||
n += 1 + l + sovConnection(uint64(l))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovConnection(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
@ -2827,6 +2935,123 @@ func (m *ConnectionPaths) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *Version) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowConnection
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Version: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Version: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Identifier", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowConnection
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthConnection
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthConnection
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Identifier = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Features", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowConnection
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthConnection
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthConnection
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Features = append(m.Features, string(dAtA[iNdEx:postIndex]))
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipConnection(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthConnection
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthConnection
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipConnection(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
|
||||
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
|
||||
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -24,17 +25,17 @@ func TestConnectionValidateBasic(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
"valid connection",
|
||||
types.ConnectionEnd{connectionID, clientID, []string{types.DefaultIBCVersion}, types.INIT, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}},
|
||||
types.ConnectionEnd{connectionID, clientID, []string{ibctesting.ConnectionVersion}, types.INIT, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid connection id",
|
||||
types.ConnectionEnd{"(connectionIDONE)", clientID, []string{types.DefaultIBCVersion}, types.INIT, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}},
|
||||
types.ConnectionEnd{"(connectionIDONE)", clientID, []string{ibctesting.ConnectionVersion}, types.INIT, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid client id",
|
||||
types.ConnectionEnd{connectionID, "(clientID1)", []string{types.DefaultIBCVersion}, types.INIT, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}},
|
||||
types.ConnectionEnd{connectionID, "(clientID1)", []string{ibctesting.ConnectionVersion}, types.INIT, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
@ -49,7 +50,7 @@ func TestConnectionValidateBasic(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"invalid counterparty",
|
||||
types.ConnectionEnd{connectionID, clientID, []string{types.DefaultIBCVersion}, types.INIT, types.Counterparty{clientID2, connectionID2, emptyPrefix}},
|
||||
types.ConnectionEnd{connectionID, clientID, []string{ibctesting.ConnectionVersion}, types.INIT, types.Counterparty{clientID2, connectionID2, emptyPrefix}},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
|
||||
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
|
||||
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
|
||||
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
|
||||
)
|
||||
|
||||
func TestValidateGenesis(t *testing.T) {
|
||||
@ -26,7 +27,7 @@ func TestValidateGenesis(t *testing.T) {
|
||||
name: "valid genesis",
|
||||
genState: types.NewGenesisState(
|
||||
[]types.ConnectionEnd{
|
||||
types.NewConnectionEnd(types.INIT, connectionID, clientID, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{types.DefaultIBCVersion}),
|
||||
types.NewConnectionEnd(types.INIT, connectionID, clientID, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{ibctesting.ConnectionVersion}),
|
||||
},
|
||||
[]types.ConnectionPaths{
|
||||
{clientID, []string{host.ConnectionPath(connectionID)}},
|
||||
@ -38,7 +39,7 @@ func TestValidateGenesis(t *testing.T) {
|
||||
name: "invalid connection",
|
||||
genState: types.NewGenesisState(
|
||||
[]types.ConnectionEnd{
|
||||
types.NewConnectionEnd(types.INIT, connectionID, "(CLIENTIDONE)", types.Counterparty{clientID, connectionID, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{types.DefaultIBCVersion}),
|
||||
types.NewConnectionEnd(types.INIT, connectionID, "(CLIENTIDONE)", types.Counterparty{clientID, connectionID, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{ibctesting.ConnectionVersion}),
|
||||
},
|
||||
[]types.ConnectionPaths{
|
||||
{clientID, []string{host.ConnectionPath(connectionID)}},
|
||||
@ -50,7 +51,7 @@ func TestValidateGenesis(t *testing.T) {
|
||||
name: "invalid client id",
|
||||
genState: types.NewGenesisState(
|
||||
[]types.ConnectionEnd{
|
||||
types.NewConnectionEnd(types.INIT, connectionID, clientID, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{types.DefaultIBCVersion}),
|
||||
types.NewConnectionEnd(types.INIT, connectionID, clientID, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{ibctesting.ConnectionVersion}),
|
||||
},
|
||||
[]types.ConnectionPaths{
|
||||
{"(CLIENTIDONE)", []string{host.ConnectionPath(connectionID)}},
|
||||
@ -62,7 +63,7 @@ func TestValidateGenesis(t *testing.T) {
|
||||
name: "invalid path",
|
||||
genState: types.NewGenesisState(
|
||||
[]types.ConnectionEnd{
|
||||
types.NewConnectionEnd(types.INIT, connectionID, clientID, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{types.DefaultIBCVersion}),
|
||||
types.NewConnectionEnd(types.INIT, connectionID, clientID, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []string{ibctesting.ConnectionVersion}),
|
||||
},
|
||||
[]types.ConnectionPaths{
|
||||
{clientID, []string{connectionID}},
|
||||
|
||||
@ -102,9 +102,9 @@ func (msg MsgConnectionOpenTry) ValidateBasic() error {
|
||||
if len(msg.CounterpartyVersions) == 0 {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrInvalidVersion, "empty counterparty versions")
|
||||
}
|
||||
for _, version := range msg.CounterpartyVersions {
|
||||
if err := host.ConnectionVersionValidator(version); err != nil {
|
||||
return err
|
||||
for i, version := range msg.CounterpartyVersions {
|
||||
if err := ValidateVersion(version); err != nil {
|
||||
return sdkerrors.Wrapf(err, "basic validation failed on version with index %d", i)
|
||||
}
|
||||
}
|
||||
if len(msg.ProofInit) == 0 {
|
||||
@ -169,7 +169,7 @@ func (msg MsgConnectionOpenAck) ValidateBasic() error {
|
||||
if err := host.ConnectionIdentifierValidator(msg.ConnectionID); err != nil {
|
||||
return sdkerrors.Wrap(err, "invalid connection ID")
|
||||
}
|
||||
if err := host.ConnectionVersionValidator(msg.Version); err != nil {
|
||||
if err := ValidateVersion(msg.Version); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(msg.ProofTry) == 0 {
|
||||
|
||||
@ -16,6 +16,7 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
|
||||
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
|
||||
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -103,18 +104,19 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() {
|
||||
signer, _ := sdk.AccAddressFromBech32("cosmos1ckgw5d7jfj7wwxjzs9fdrdev9vc8dzcw3n2lht")
|
||||
|
||||
testMsgs := []*types.MsgConnectionOpenTry{
|
||||
types.NewMsgConnectionOpenTry("test/conn1", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{types.DefaultIBCVersion}, suite.proof, suite.proof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "test/iris", "connectiontotest", "clienttotest", prefix, []string{types.DefaultIBCVersion}, suite.proof, suite.proof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "ibc/test", "clienttotest", prefix, []string{types.DefaultIBCVersion}, suite.proof, suite.proof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "test/conn1", prefix, []string{types.DefaultIBCVersion}, suite.proof, suite.proof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", emptyPrefix, []string{types.DefaultIBCVersion}, suite.proof, suite.proof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("test/conn1", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "test/iris", "connectiontotest", "clienttotest", prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "ibc/test", "clienttotest", prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "test/conn1", prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", emptyPrefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{}, suite.proof, suite.proof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{types.DefaultIBCVersion}, emptyProof, suite.proof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{types.DefaultIBCVersion}, suite.proof, emptyProof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{types.DefaultIBCVersion}, suite.proof, suite.proof, 0, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{types.DefaultIBCVersion}, suite.proof, suite.proof, 10, 0, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{types.DefaultIBCVersion}, suite.proof, suite.proof, 10, 10, nil),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{types.DefaultIBCVersion}, suite.proof, suite.proof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{ibctesting.ConnectionVersion}, emptyProof, suite.proof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{ibctesting.ConnectionVersion}, suite.proof, emptyProof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, 0, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, 10, 0, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, 10, 10, nil),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, 10, 10, signer),
|
||||
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"(invalid version)"}, suite.proof, suite.proof, 10, 10, signer),
|
||||
}
|
||||
|
||||
var testCases = []struct {
|
||||
@ -134,6 +136,7 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() {
|
||||
{testMsgs[9], false, "invalid consensusHeight"},
|
||||
{testMsgs[10], false, "empty singer"},
|
||||
{testMsgs[11], true, "success"},
|
||||
{testMsgs[12], false, "invalid version"},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
@ -150,14 +153,14 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenAck() {
|
||||
signer, _ := sdk.AccAddressFromBech32("cosmos1ckgw5d7jfj7wwxjzs9fdrdev9vc8dzcw3n2lht")
|
||||
|
||||
testMsgs := []*types.MsgConnectionOpenAck{
|
||||
types.NewMsgConnectionOpenAck("test/conn1", suite.proof, suite.proof, 10, 10, types.DefaultIBCVersion, signer),
|
||||
types.NewMsgConnectionOpenAck("ibcconntest", emptyProof, suite.proof, 10, 10, types.DefaultIBCVersion, signer),
|
||||
types.NewMsgConnectionOpenAck("ibcconntest", suite.proof, emptyProof, 10, 10, types.DefaultIBCVersion, signer),
|
||||
types.NewMsgConnectionOpenAck("ibcconntest", suite.proof, suite.proof, 0, 10, types.DefaultIBCVersion, signer),
|
||||
types.NewMsgConnectionOpenAck("ibcconntest", suite.proof, suite.proof, 10, 0, types.DefaultIBCVersion, signer),
|
||||
types.NewMsgConnectionOpenAck("test/conn1", suite.proof, suite.proof, 10, 10, ibctesting.ConnectionVersion, signer),
|
||||
types.NewMsgConnectionOpenAck("ibcconntest", emptyProof, suite.proof, 10, 10, ibctesting.ConnectionVersion, signer),
|
||||
types.NewMsgConnectionOpenAck("ibcconntest", suite.proof, emptyProof, 10, 10, ibctesting.ConnectionVersion, signer),
|
||||
types.NewMsgConnectionOpenAck("ibcconntest", suite.proof, suite.proof, 0, 10, ibctesting.ConnectionVersion, signer),
|
||||
types.NewMsgConnectionOpenAck("ibcconntest", suite.proof, suite.proof, 10, 0, ibctesting.ConnectionVersion, signer),
|
||||
types.NewMsgConnectionOpenAck("ibcconntest", suite.proof, suite.proof, 10, 10, "", signer),
|
||||
types.NewMsgConnectionOpenAck("ibcconntest", suite.proof, suite.proof, 10, 10, types.DefaultIBCVersion, nil),
|
||||
types.NewMsgConnectionOpenAck("ibcconntest", suite.proof, suite.proof, 10, 10, types.DefaultIBCVersion, signer),
|
||||
types.NewMsgConnectionOpenAck("ibcconntest", suite.proof, suite.proof, 10, 10, ibctesting.ConnectionVersion, nil),
|
||||
types.NewMsgConnectionOpenAck("ibcconntest", suite.proof, suite.proof, 10, 10, ibctesting.ConnectionVersion, signer),
|
||||
}
|
||||
var testCases = []struct {
|
||||
msg *types.MsgConnectionOpenAck
|
||||
|
||||
@ -1,127 +1,184 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultIBCVersion represents the latest supported version of IBC.
|
||||
// The current version supports only ORDERED and UNORDERED channels.
|
||||
DefaultIBCVersion = CreateVersionString("1", []string{"ORDER_ORDERED", "ORDER_UNORDERED"})
|
||||
// DefaultIBCVersion represents the latest supported version of IBC used
|
||||
// in connection version negotiation. The current version supports only
|
||||
// ORDERED and UNORDERED channels and requires at least one channel type
|
||||
// to be agreed upon.
|
||||
DefaultIBCVersion = NewVersion(DefaultIBCVersionIdentifier, []string{"ORDER_ORDERED", "ORDER_UNORDERED"})
|
||||
|
||||
// DefaultIBCVersionIdentifier is the IBC v1.0.0 protocol version identifier
|
||||
DefaultIBCVersionIdentifier = "1"
|
||||
|
||||
// AllowNilFeatureSet is a helper map to indicate if a specified version
|
||||
// identifier is allowed to have a nil feature set. Any versions supported,
|
||||
// but not included in the map default to not supporting nil feature sets.
|
||||
allowNilFeatureSet = map[string]bool{
|
||||
DefaultIBCVersionIdentifier: false,
|
||||
}
|
||||
)
|
||||
|
||||
// NewVersion returns a new instance of Version.
|
||||
func NewVersion(identifier string, features []string) Version {
|
||||
return Version{
|
||||
Identifier: identifier,
|
||||
Features: features,
|
||||
}
|
||||
}
|
||||
|
||||
// GetIdentifier implements the VersionI interface
|
||||
func (version Version) GetIdentifier() string {
|
||||
return version.Identifier
|
||||
}
|
||||
|
||||
// GetFeatures implements the VersionI interface
|
||||
func (version Version) GetFeatures() []string {
|
||||
return version.Features
|
||||
}
|
||||
|
||||
// ValidateVersion does basic validation of the version identifier and
|
||||
// features. It unmarshals the version string into a Version object.
|
||||
func ValidateVersion(encodedVersion string) error {
|
||||
var version Version
|
||||
if err := SubModuleCdc.UnmarshalBinaryBare([]byte(encodedVersion), &version); err != nil {
|
||||
return sdkerrors.Wrapf(err, "failed to unmarshal version string %s", encodedVersion)
|
||||
}
|
||||
|
||||
if strings.TrimSpace(version.Identifier) == "" {
|
||||
return sdkerrors.Wrap(ErrInvalidVersion, "version identifier cannot be blank")
|
||||
}
|
||||
for i, feature := range version.Features {
|
||||
if strings.TrimSpace(feature) == "" {
|
||||
return sdkerrors.Wrapf(ErrInvalidVersion, "feature cannot be blank, index %d", i)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode proto encodes the version and returns the bytes as a string.
|
||||
func (version Version) Encode() (string, error) {
|
||||
encodedVersion, err := SubModuleCdc.MarshalBinaryBare(&version)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(encodedVersion), nil
|
||||
}
|
||||
|
||||
// EncodeVersions iterates over the provided versions and marshals each
|
||||
// into proto encoded strings. This represents the stored value of the version
|
||||
// in the connection end as well as the value passed over the wire.
|
||||
func EncodeVersions(versions []Version) ([]string, error) {
|
||||
encodedVersions := make([]string, len(versions))
|
||||
|
||||
for i, version := range versions {
|
||||
ver, err := version.Encode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encodedVersions[i] = ver
|
||||
}
|
||||
|
||||
return encodedVersions, nil
|
||||
}
|
||||
|
||||
// DecodeVersion unmarshals a proto encoded version into a Version struct.
|
||||
func DecodeVersion(encodedVersion string) (Version, error) {
|
||||
var version Version
|
||||
if err := SubModuleCdc.UnmarshalBinaryBare([]byte(encodedVersion), &version); err != nil {
|
||||
return Version{}, sdkerrors.Wrapf(err, "failed to unmarshal version string %s", encodedVersion)
|
||||
}
|
||||
|
||||
return version, nil
|
||||
}
|
||||
|
||||
// DecodeVersions returns the supplied list of proto encoded version strings
|
||||
// as unmarshalled Version structs.
|
||||
func DecodeVersions(encodedVersions []string) ([]Version, error) {
|
||||
versions := make([]Version, len(encodedVersions))
|
||||
|
||||
for i, encodedVersion := range encodedVersions {
|
||||
version, err := DecodeVersion(encodedVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
versions[i] = version
|
||||
}
|
||||
|
||||
return versions, nil
|
||||
}
|
||||
|
||||
// GetCompatibleVersions returns a descending ordered set of compatible IBC
|
||||
// versions for the caller chain's connection end. The latest supported
|
||||
// version should be first element and the set should descend to the oldest
|
||||
// supported version.
|
||||
func GetCompatibleVersions() []string {
|
||||
return []string{DefaultIBCVersion}
|
||||
func GetCompatibleVersions() []Version {
|
||||
return []Version{DefaultIBCVersion}
|
||||
}
|
||||
|
||||
// CreateVersionString constructs a valid connection version given a
|
||||
// version identifier and feature set. The format is written as:
|
||||
//
|
||||
// ([version_identifier],[feature_0,feature_1,feature_2...])
|
||||
//
|
||||
// A connection version is considered invalid if it is not in this format
|
||||
// or violates one of these rules:
|
||||
// - the version identifier is empty or contains commas
|
||||
// - a specified feature contains commas
|
||||
func CreateVersionString(identifier string, featureSet []string) string {
|
||||
return fmt.Sprintf("(%s,[%s])", identifier, strings.Join(featureSet, ","))
|
||||
}
|
||||
|
||||
// UnpackVersion parses a version string and returns the identifier and the
|
||||
// feature set of a version. An error is returned if the version is not valid.
|
||||
func UnpackVersion(version string) (string, []string, error) {
|
||||
// validate version so valid splitting assumptions can be made
|
||||
if err := host.ConnectionVersionValidator(version); err != nil {
|
||||
return "", nil, err
|
||||
// GetCompatibleEncodedVersions returns the return value from GetCompatibleVersions
|
||||
// as a proto encoded string.
|
||||
func GetCompatibleEncodedVersions() []string {
|
||||
versions, err := EncodeVersions(GetCompatibleVersions())
|
||||
if err != nil {
|
||||
panic(err) // should not occur with properly set hardcoded versions
|
||||
}
|
||||
|
||||
// peel off prefix and suffix of the tuple
|
||||
version = strings.TrimPrefix(version, "(")
|
||||
version = strings.TrimSuffix(version, ")")
|
||||
|
||||
// split into identifier and feature set
|
||||
splitVersion := strings.SplitN(version, ",", 2)
|
||||
if splitVersion[0] == version {
|
||||
return "", nil, sdkerrors.Wrapf(ErrInvalidVersion, "failed to split version '%s' into identifier and features", version)
|
||||
}
|
||||
identifier := splitVersion[0]
|
||||
|
||||
// peel off prefix and suffix of features
|
||||
featureSet := strings.TrimPrefix(splitVersion[1], "[")
|
||||
featureSet = strings.TrimSuffix(featureSet, "]")
|
||||
|
||||
// check if features are empty
|
||||
if len(featureSet) == 0 {
|
||||
return identifier, []string{}, nil
|
||||
}
|
||||
|
||||
features := strings.Split(featureSet, ",")
|
||||
|
||||
return identifier, features, nil
|
||||
return versions
|
||||
}
|
||||
|
||||
// FindSupportedVersion returns the version with a matching version identifier
|
||||
// if it exists. The returned boolean is true if the version is found and
|
||||
// false otherwise.
|
||||
func FindSupportedVersion(version string, supportedVersions []string) (string, bool) {
|
||||
identifier, _, err := UnpackVersion(version)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
func FindSupportedVersion(version Version, supportedVersions []Version) (Version, bool) {
|
||||
for _, supportedVersion := range supportedVersions {
|
||||
supportedIdentifier, _, err := UnpackVersion(supportedVersion)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if identifier == supportedIdentifier {
|
||||
if version.GetIdentifier() == supportedVersion.GetIdentifier() {
|
||||
return supportedVersion, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
return Version{}, false
|
||||
}
|
||||
|
||||
// PickVersion iterates over the descending ordered set of compatible IBC
|
||||
// versions and selects the first version with a version identifier that is
|
||||
// supported by the counterparty. The returned version contains a feature
|
||||
// set with the intersection of the features supported by the source and
|
||||
// counterparty chains. This function is called in the ConnOpenTry handshake
|
||||
// procedure.
|
||||
func PickVersion(counterpartyVersions []string) (string, error) {
|
||||
versions := GetCompatibleVersions()
|
||||
// counterparty chains. If the feature set intersection is nil and this is
|
||||
// not allowed for the chosen version identifier then the search for a
|
||||
// compatible version continues. This function is called in the ConnOpenTry
|
||||
// handshake procedure.
|
||||
func PickVersion(encodedCounterpartyVersions []string) (string, error) {
|
||||
counterpartyVersions, err := DecodeVersions(encodedCounterpartyVersions)
|
||||
if err != nil {
|
||||
return "", sdkerrors.Wrapf(err, "failed to unmarshal counterparty versions (%s) when attempting to pick compatible version", encodedCounterpartyVersions)
|
||||
}
|
||||
supportedVersions := GetCompatibleVersions()
|
||||
|
||||
for _, ver := range versions {
|
||||
for _, supportedVersion := range supportedVersions {
|
||||
// check if the source version is supported by the counterparty
|
||||
if counterpartyVer, found := FindSupportedVersion(ver, counterpartyVersions); found {
|
||||
sourceIdentifier, sourceFeatures, err := UnpackVersion(ver)
|
||||
if err != nil {
|
||||
return "", err
|
||||
if counterpartyVersion, found := FindSupportedVersion(supportedVersion, counterpartyVersions); found {
|
||||
|
||||
featureSet := GetFeatureSetIntersection(supportedVersion.GetFeatures(), counterpartyVersion.GetFeatures())
|
||||
if len(featureSet) == 0 && !allowNilFeatureSet[supportedVersion.GetIdentifier()] {
|
||||
continue
|
||||
}
|
||||
|
||||
_, counterpartyFeatures, err := UnpackVersion(counterpartyVer)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
featureSet := GetFeatureSetIntersection(sourceFeatures, counterpartyFeatures)
|
||||
|
||||
version := CreateVersionString(sourceIdentifier, featureSet)
|
||||
return version, nil
|
||||
return NewVersion(supportedVersion.GetIdentifier(), featureSet).Encode()
|
||||
}
|
||||
}
|
||||
|
||||
return "", sdkerrors.Wrapf(
|
||||
ErrVersionNegotiationFailed,
|
||||
"failed to find a matching counterparty version (%s) from the supported version list (%s)", counterpartyVersions, versions,
|
||||
"failed to find a matching counterparty version (%s) from the supported version list (%s)", counterpartyVersions, supportedVersions,
|
||||
)
|
||||
}
|
||||
|
||||
@ -139,37 +196,46 @@ func GetFeatureSetIntersection(sourceFeatureSet, counterpartyFeatureSet []string
|
||||
return featureSet
|
||||
}
|
||||
|
||||
// VerifyProposedFeatureSet verifies that the entire feature set in the
|
||||
// proposed version is supported by this chain.
|
||||
func VerifyProposedFeatureSet(proposedVersion, supportedVersion string) bool {
|
||||
_, proposedFeatureSet, err := UnpackVersion(proposedVersion)
|
||||
if err != nil {
|
||||
return false
|
||||
// VerifyProposedVersion verifies that the entire feature set in the
|
||||
// proposed version is supported by this chain. If the feature set is
|
||||
// empty it verifies that this is allowed for the specified version
|
||||
// identifier.
|
||||
func (version Version) VerifyProposedVersion(proposedVersion Version) error {
|
||||
if proposedVersion.GetIdentifier() != version.GetIdentifier() {
|
||||
return sdkerrors.Wrapf(
|
||||
ErrVersionNegotiationFailed,
|
||||
"proposed version identifier does not equal supported version identifier (%s != %s)", proposedVersion.GetIdentifier(), version.GetIdentifier(),
|
||||
)
|
||||
}
|
||||
|
||||
_, supportedFeatureSet, err := UnpackVersion(supportedVersion)
|
||||
if err != nil {
|
||||
return false
|
||||
if len(proposedVersion.GetFeatures()) == 0 && !allowNilFeatureSet[proposedVersion.GetIdentifier()] {
|
||||
return sdkerrors.Wrapf(
|
||||
ErrVersionNegotiationFailed,
|
||||
"nil feature sets are not supported for version identifier (%s)", proposedVersion.GetIdentifier(),
|
||||
)
|
||||
}
|
||||
|
||||
for _, proposedFeature := range proposedFeatureSet {
|
||||
if !contains(proposedFeature, supportedFeatureSet) {
|
||||
return false
|
||||
for _, proposedFeature := range proposedVersion.GetFeatures() {
|
||||
if !contains(proposedFeature, version.GetFeatures()) {
|
||||
return sdkerrors.Wrapf(
|
||||
ErrVersionNegotiationFailed,
|
||||
"proposed feature (%s) is not a supported feature set (%s)", proposedFeature, version.GetFeatures(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
// VerifySupportedFeature takes in a version string and feature string and returns
|
||||
// VerifySupportedFeature takes in a version and feature string and returns
|
||||
// true if the feature is supported by the version and false otherwise.
|
||||
func VerifySupportedFeature(version, feature string) bool {
|
||||
_, featureSet, err := UnpackVersion(version)
|
||||
func VerifySupportedFeature(encodedVersion, feature string) bool {
|
||||
version, err := DecodeVersion(encodedVersion)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, f := range featureSet {
|
||||
for _, f := range version.GetFeatures() {
|
||||
if f == feature {
|
||||
return true
|
||||
}
|
||||
@ -181,7 +247,7 @@ func VerifySupportedFeature(version, feature string) bool {
|
||||
// string set.
|
||||
func contains(elem string, set []string) bool {
|
||||
for _, element := range set {
|
||||
if strings.TrimSpace(elem) == strings.TrimSpace(element) {
|
||||
if elem == element {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,61 +6,79 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
|
||||
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
|
||||
)
|
||||
|
||||
// testing of invalid version formats exist within 24-host/validate_test.go
|
||||
func TestUnpackVersion(t *testing.T) {
|
||||
func TestValidateVersion(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
version string
|
||||
expIdentifier string
|
||||
expFeatures []string
|
||||
expPass bool
|
||||
name string
|
||||
version types.Version
|
||||
expPass bool
|
||||
}{
|
||||
{"valid version", "(1,[ORDERED channel,UNORDERED channel])", "1", []string{"ORDERED channel", "UNORDERED channel"}, true},
|
||||
{"valid empty features", "(1,[])", "1", []string{}, true},
|
||||
{"empty identifier", "(,[features])", "", []string{}, false},
|
||||
{"invalid version", "identifier,[features]", "", []string{}, false},
|
||||
{"empty string", " ", "", []string{}, false},
|
||||
{"valid version", types.DefaultIBCVersion, true},
|
||||
{"valid empty feature set", types.NewVersion(types.DefaultIBCVersionIdentifier, []string{}), true},
|
||||
{"empty version identifier", types.NewVersion(" ", []string{"ORDER_UNORDERED"}), false},
|
||||
{"empty feature", types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"ORDER_UNORDERED", " "}), false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
for i, tc := range testCases {
|
||||
encodedVersion, err := tc.version.Encode()
|
||||
require.NoError(t, err, "test case %d failed to marshal version string: %s", i, tc.name)
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
identifier, features, err := types.UnpackVersion(tc.version)
|
||||
err = types.ValidateVersion(encodedVersion)
|
||||
|
||||
if tc.expPass {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.expIdentifier, identifier)
|
||||
require.Equal(t, tc.expFeatures, features)
|
||||
} else {
|
||||
require.Error(t, err)
|
||||
}
|
||||
})
|
||||
if tc.expPass {
|
||||
require.NoError(t, err, "valid test case %d failed: %s", i, tc.name)
|
||||
} else {
|
||||
require.Error(t, err, "invalid test case %d passed: %s", i, tc.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeVersion(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
version string
|
||||
expVersion types.Version
|
||||
expPass bool
|
||||
}{
|
||||
{"valid version", ibctesting.ConnectionVersion, types.DefaultIBCVersion, true},
|
||||
{"invalid version", "not a proto encoded version", types.Version{}, false},
|
||||
{"empty string", " ", types.Version{}, false},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
version, err := types.DecodeVersion(tc.version)
|
||||
|
||||
if tc.expPass {
|
||||
require.NoError(t, err, "valid test case %d failed: %s", i, tc.name)
|
||||
require.Equal(t, tc.expVersion, version)
|
||||
} else {
|
||||
require.Error(t, err, "invalid test case %d passed: %s", i, tc.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindSupportedVersion(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
version string
|
||||
supportedVersions []string
|
||||
expVersion string
|
||||
version types.Version
|
||||
supportedVersions []types.Version
|
||||
expVersion types.Version
|
||||
expFound bool
|
||||
}{
|
||||
{"valid supported version", types.DefaultIBCVersion, types.GetCompatibleVersions(), types.DefaultIBCVersion, true},
|
||||
{"empty (invalid) version", "", types.GetCompatibleVersions(), "", false},
|
||||
{"empty supported versions", types.DefaultIBCVersion, []string{}, "", false},
|
||||
{"desired version is last", types.DefaultIBCVersion, []string{"(validversion,[])", "(2,[feature])", "(3,[])", types.DefaultIBCVersion}, types.DefaultIBCVersion, true},
|
||||
{"desired version identifier with different feature set", "(1,[features])", types.GetCompatibleVersions(), types.DefaultIBCVersion, true},
|
||||
{"version not supported", "(2,[DAG])", types.GetCompatibleVersions(), "", false},
|
||||
{"empty (invalid) version", types.Version{}, types.GetCompatibleVersions(), types.Version{}, false},
|
||||
{"empty supported versions", types.DefaultIBCVersion, []types.Version{}, types.Version{}, false},
|
||||
{"desired version is last", types.DefaultIBCVersion, []types.Version{types.NewVersion("1.1", nil), types.NewVersion("2", []string{"ORDER_UNORDERED"}), types.NewVersion("3", nil), types.DefaultIBCVersion}, types.DefaultIBCVersion, true},
|
||||
{"desired version identifier with different feature set", types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"ORDER_DAG"}), types.GetCompatibleVersions(), types.DefaultIBCVersion, true},
|
||||
{"version not supported", types.NewVersion("2", []string{"ORDER_DAG"}), types.GetCompatibleVersions(), types.Version{}, false},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
version, found := types.FindSupportedVersion(tc.version, tc.supportedVersions)
|
||||
|
||||
require.Equal(t, tc.expVersion, version, "test case %d: %s", i, tc.name)
|
||||
require.Equal(t, tc.expVersion.GetIdentifier(), version.GetIdentifier(), "test case %d: %s", i, tc.name)
|
||||
require.Equal(t, tc.expFound, found, "test case %d: %s", i, tc.name)
|
||||
}
|
||||
}
|
||||
@ -68,62 +86,77 @@ func TestFindSupportedVersion(t *testing.T) {
|
||||
func TestPickVersion(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
counterpartyVersions []string
|
||||
expVer string
|
||||
counterpartyVersions []types.Version
|
||||
expVer types.Version
|
||||
expPass bool
|
||||
}{
|
||||
{"valid default ibc version", types.GetCompatibleVersions(), types.DefaultIBCVersion, true},
|
||||
{"valid version in counterparty versions", []string{"(version1,[])", "(2.0.0,[DAG,ZK])", types.DefaultIBCVersion}, types.DefaultIBCVersion, true},
|
||||
{"valid identifier match but empty feature set", []string{"(1,[DAG,ORDERED-ZK,UNORDERED-zk])"}, "(1,[])", true},
|
||||
{"empty counterparty versions", []string{}, "", false},
|
||||
{"non-matching counterparty versions", []string{"(2.0.0,[])"}, "", false},
|
||||
{"valid version in counterparty versions", []types.Version{types.NewVersion("version1", nil), types.NewVersion("2.0.0", []string{"ORDER_UNORDERED-ZK"}), types.DefaultIBCVersion}, types.DefaultIBCVersion, true},
|
||||
{"valid identifier match but empty feature set not allowed", []types.Version{types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"DAG", "ORDERED-ZK", "UNORDERED-zk]"})}, types.NewVersion(types.DefaultIBCVersionIdentifier, nil), false},
|
||||
{"empty counterparty versions", []types.Version{}, types.Version{}, false},
|
||||
{"non-matching counterparty versions", []types.Version{types.NewVersion("2.0.0", nil)}, types.Version{}, false},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
version, err := types.PickVersion(tc.counterpartyVersions)
|
||||
encodedCounterpartyVersions, err := types.EncodeVersions(tc.counterpartyVersions)
|
||||
require.NoError(t, err)
|
||||
|
||||
encodedVersion, err := types.PickVersion(encodedCounterpartyVersions)
|
||||
|
||||
if tc.expPass {
|
||||
require.NoError(t, err, "valid test case %d failed: %s", i, tc.name)
|
||||
|
||||
version, err := types.DecodeVersion(encodedVersion)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.expVer, version, "valid test case %d falied: %s", i, tc.name)
|
||||
} else {
|
||||
require.Error(t, err, "invalid test case %d passed: %s", i, tc.name)
|
||||
require.Equal(t, "", version, "invalid test case %d passed: %s", i, tc.name)
|
||||
require.Equal(t, "", encodedVersion, "invalid test case %d passed: %s", i, tc.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyProposedFeatureSet(t *testing.T) {
|
||||
func TestVerifyProposedVersion(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
proposedVersion string
|
||||
supportedVersion string
|
||||
proposedVersion types.Version
|
||||
supportedVersion types.Version
|
||||
expPass bool
|
||||
}{
|
||||
{"entire feature set supported", types.DefaultIBCVersion, types.CreateVersionString("1", []string{"ORDER_ORDERED", "ORDER_UNORDERED", "ORDER_DAG"}), true},
|
||||
{"empty feature sets", types.CreateVersionString("1", []string{}), types.DefaultIBCVersion, true},
|
||||
{"one feature missing", types.DefaultIBCVersion, types.CreateVersionString("1", []string{"ORDER_UNORDERED", "ORDER_DAG"}), false},
|
||||
{"both features missing", types.DefaultIBCVersion, types.CreateVersionString("1", []string{"ORDER_DAG"}), false},
|
||||
{"entire feature set supported", types.DefaultIBCVersion, types.NewVersion("1", []string{"ORDER_ORDERED", "ORDER_UNORDERED", "ORDER_DAG"}), true},
|
||||
{"empty feature sets not supported", types.NewVersion("1", []string{}), types.DefaultIBCVersion, false},
|
||||
{"one feature missing", types.DefaultIBCVersion, types.NewVersion("1", []string{"ORDER_UNORDERED", "ORDER_DAG"}), false},
|
||||
{"both features missing", types.DefaultIBCVersion, types.NewVersion("1", []string{"ORDER_DAG"}), false},
|
||||
{"identifiers do not match", types.NewVersion("2", []string{"ORDER_UNORDERED", "ORDER_ORDERED"}), types.DefaultIBCVersion, false},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
supported := types.VerifyProposedFeatureSet(tc.proposedVersion, tc.supportedVersion)
|
||||
err := tc.supportedVersion.VerifyProposedVersion(tc.proposedVersion)
|
||||
|
||||
require.Equal(t, tc.expPass, supported, "test case %d: %s", i, tc.name)
|
||||
if tc.expPass {
|
||||
require.NoError(t, err, "test case %d: %s", i, tc.name)
|
||||
} else {
|
||||
require.Error(t, err, "test case %d: %s", i, tc.name)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestVerifySupportedFeature(t *testing.T) {
|
||||
nilFeatures, err := types.NewVersion(types.DefaultIBCVersionIdentifier, nil).Encode()
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
version string
|
||||
feature string
|
||||
expPass bool
|
||||
}{
|
||||
{"check ORDERED supported", types.DefaultIBCVersion, "ORDER_ORDERED", true},
|
||||
{"check UNORDERED supported", types.DefaultIBCVersion, "ORDER_UNORDERED", true},
|
||||
{"check DAG unsupported", types.DefaultIBCVersion, "ORDER_DAG", false},
|
||||
{"check empty feature set returns false", types.CreateVersionString("1", []string{}), "ORDER_ORDERED", false},
|
||||
{"check ORDERED supported", ibctesting.ConnectionVersion, "ORDER_ORDERED", true},
|
||||
{"check UNORDERED supported", ibctesting.ConnectionVersion, "ORDER_UNORDERED", true},
|
||||
{"check DAG unsupported", ibctesting.ConnectionVersion, "ORDER_DAG", false},
|
||||
{"check empty feature set returns false", nilFeatures, "ORDER_ORDERED", false},
|
||||
{"failed to unmarshal version", "not an encoded version", "ORDER_ORDERED", false},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc-transfer/types"
|
||||
connectionutils "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/client/utils"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
|
||||
)
|
||||
@ -54,7 +55,7 @@ func NewChannelOpenInitCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
cmd.Flags().Bool(FlagOrdered, true, "Pass flag for opening ordered channels")
|
||||
cmd.Flags().String(FlagIBCVersion, types.DefaultChannelVersion, "supported IBC version")
|
||||
cmd.Flags().String(FlagIBCVersion, ibctransfertypes.Version, "IBC application version")
|
||||
flags.AddTxFlagsToCmd(cmd)
|
||||
|
||||
return cmd
|
||||
@ -107,7 +108,7 @@ func NewChannelOpenTryCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
cmd.Flags().Bool(FlagOrdered, true, "Pass flag for opening ordered channels")
|
||||
cmd.Flags().String(FlagIBCVersion, types.DefaultChannelVersion, "supported IBC version")
|
||||
cmd.Flags().String(FlagIBCVersion, ibctransfertypes.Version, "IBC application version")
|
||||
flags.AddTxFlagsToCmd(cmd)
|
||||
|
||||
return cmd
|
||||
@ -152,8 +153,7 @@ func NewChannelOpenAckCmd() *cobra.Command {
|
||||
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().String(FlagIBCVersion, types.DefaultChannelVersion, "supported IBC version")
|
||||
cmd.Flags().String(FlagIBCVersion, ibctransfertypes.Version, "IBC application version")
|
||||
flags.AddTxFlagsToCmd(cmd)
|
||||
|
||||
return cmd
|
||||
|
||||
@ -66,7 +66,11 @@ func (suite *KeeperTestSuite) TestChanOpenInit() {
|
||||
|
||||
// modify connA versions
|
||||
conn := suite.chainA.GetConnection(connA)
|
||||
conn.Versions = append(conn.Versions, connectiontypes.CreateVersionString("2", []string{"ORDER_ORDERED", "ORDER_UNORDERED"}))
|
||||
|
||||
version, err := connectiontypes.NewVersion("2", []string{"ORDER_ORDERED", "ORDER_UNORDERED"}).Encode()
|
||||
suite.Require().NoError(err)
|
||||
conn.Versions = append(conn.Versions, version)
|
||||
|
||||
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(
|
||||
suite.chainA.GetContext(),
|
||||
connA.ID, conn,
|
||||
@ -80,7 +84,11 @@ func (suite *KeeperTestSuite) TestChanOpenInit() {
|
||||
|
||||
// modify connA versions to only support UNORDERED channels
|
||||
conn := suite.chainA.GetConnection(connA)
|
||||
conn.Versions = []string{connectiontypes.CreateVersionString("1", []string{"ORDER_UNORDERED"})}
|
||||
|
||||
version, err := connectiontypes.NewVersion("1", []string{"ORDER_UNORDERED"}).Encode()
|
||||
suite.Require().NoError(err)
|
||||
conn.Versions = []string{version}
|
||||
|
||||
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(
|
||||
suite.chainA.GetContext(),
|
||||
connA.ID, conn,
|
||||
@ -207,7 +215,11 @@ func (suite *KeeperTestSuite) TestChanOpenTry() {
|
||||
|
||||
// modify connB versions
|
||||
conn := suite.chainB.GetConnection(connB)
|
||||
conn.Versions = append(conn.Versions, connectiontypes.CreateVersionString("2", []string{"ORDER_ORDERED", "ORDER_UNORDERED"}))
|
||||
|
||||
version, err := connectiontypes.NewVersion("2", []string{"ORDER_ORDERED", "ORDER_UNORDERED"}).Encode()
|
||||
suite.Require().NoError(err)
|
||||
conn.Versions = append(conn.Versions, version)
|
||||
|
||||
suite.chainB.App.IBCKeeper.ConnectionKeeper.SetConnection(
|
||||
suite.chainB.GetContext(),
|
||||
connB.ID, conn,
|
||||
@ -221,7 +233,11 @@ func (suite *KeeperTestSuite) TestChanOpenTry() {
|
||||
|
||||
// modify connA versions to only support UNORDERED channels
|
||||
conn := suite.chainA.GetConnection(connA)
|
||||
conn.Versions = []string{connectiontypes.CreateVersionString("1", []string{"ORDER_UNORDERED"})}
|
||||
|
||||
version, err := connectiontypes.NewVersion("1", []string{"ORDER_UNORDERED"}).Encode()
|
||||
suite.Require().NoError(err)
|
||||
conn.Versions = []string{version}
|
||||
|
||||
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(
|
||||
suite.chainA.GetContext(),
|
||||
connA.ID, conn,
|
||||
@ -364,6 +380,7 @@ func (suite *KeeperTestSuite) TestChanOpenAck() {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
suite.SetupTest() // reset
|
||||
heightDiff = 0 // must be explicitly changed
|
||||
|
||||
tc.malleate()
|
||||
|
||||
channelA := connA.FirstOrNextTestChannel()
|
||||
|
||||
@ -13,9 +13,6 @@ var (
|
||||
_ exported.CounterpartyI = (*Counterparty)(nil)
|
||||
)
|
||||
|
||||
// DefaultChannelVersion defines the default channel version used during handshake.
|
||||
const DefaultChannelVersion = "1.0.0"
|
||||
|
||||
// NewChannel creates a new Channel instance
|
||||
func NewChannel(
|
||||
state State, ordering Order, counterparty Counterparty,
|
||||
|
||||
@ -14,15 +14,6 @@ import (
|
||||
// - `[`, `]`, `<`, `>`
|
||||
var IsValidID = regexp.MustCompile(`^[a-zA-Z0-9\.\_\+\-\#\[\]\<\>]+$`).MatchString
|
||||
|
||||
// IsValidConnectionVersion defines the regular expression to check if the
|
||||
// string is in the form of a tuple consisting of a string identifier and
|
||||
// a set of features. The entire version tuple must be enclosed in parentheses.
|
||||
// The version identifier must not contain any commas. The set of features
|
||||
// must be enclosed in brackets and separated by commas.
|
||||
//
|
||||
// valid connection version = ([version_identifier], [feature_0, feature_1, etc])
|
||||
var IsValidConnectionVersion = regexp.MustCompile(`^\([^,]+\,\[([^,]+(\,[^,]+)*)?\]\)$`).MatchString
|
||||
|
||||
// ICS 024 Identifier and Path Validation Implementation
|
||||
//
|
||||
// This file defines ValidateFn to validate identifier and path strings
|
||||
@ -83,24 +74,6 @@ func PortIdentifierValidator(id string) error {
|
||||
return defaultIdentifierValidator(id, 2, 20)
|
||||
}
|
||||
|
||||
// ConnectionVersionValidator is the default validator function for Connection
|
||||
// versions. A valid version must be in semantic versioning form and contain
|
||||
// only non-negative integers.
|
||||
func ConnectionVersionValidator(version string) error {
|
||||
if strings.TrimSpace(version) == "" {
|
||||
return sdkerrors.Wrap(ErrInvalidVersion, "version cannot be blank")
|
||||
}
|
||||
|
||||
if !IsValidConnectionVersion(version) {
|
||||
return sdkerrors.Wrapf(
|
||||
ErrInvalidVersion,
|
||||
"version '%s' must be in '(version_identifier,[feature_0, feature_1])' with no extra spacing", version,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewPathValidator takes in a Identifier Validator function and returns
|
||||
// a Path Validator function which requires path only has valid identifiers
|
||||
// alphanumeric character strings, and "/" separators
|
||||
|
||||
@ -111,31 +111,3 @@ func TestCustomPathValidator(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnectionVersionValidator(t *testing.T) {
|
||||
testCases := []testCase{
|
||||
{"valid connection version", "(my-test-version 1.0,[feature0, feature1])", true},
|
||||
{"valid random character version, no commas", "(a!@!#$%^&34,[)(*&^),....,feature_2])", true},
|
||||
{"valid: empty features", "(identifier,[])", true},
|
||||
{"invalid: empty features with spacing", "(identifier, [ ])", false},
|
||||
{"missing identifier", "( , [feature_0])", false},
|
||||
{"no features bracket", "(identifier, feature_0, feature_1)", false},
|
||||
{"no tuple parentheses", "identifier, [feature$%#]", false},
|
||||
{"string with only spaces", " ", false},
|
||||
{"empty string", "", false},
|
||||
{"no comma", "(idenitifer [features])", false},
|
||||
{"invalid comma usage in features", "(identifier, [feature_0,,feature_1])", false},
|
||||
{"empty features with comma", "(identifier, [ , ])", false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
err := ConnectionVersionValidator(tc.id)
|
||||
|
||||
if tc.expPass {
|
||||
require.NoError(t, err, tc.msg)
|
||||
} else {
|
||||
require.Error(t, err, tc.msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/09-localhost/types"
|
||||
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
|
||||
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
|
||||
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/types"
|
||||
)
|
||||
|
||||
@ -47,7 +48,7 @@ func (suite *IBCTestSuite) TestValidateGenesis() {
|
||||
),
|
||||
ConnectionGenesis: connectiontypes.NewGenesisState(
|
||||
[]connectiontypes.ConnectionEnd{
|
||||
connectiontypes.NewConnectionEnd(connectiontypes.INIT, connectionID, clientID, connectiontypes.NewCounterparty(clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))), []string{connectiontypes.DefaultIBCVersion}),
|
||||
connectiontypes.NewConnectionEnd(connectiontypes.INIT, connectionID, clientID, connectiontypes.NewCounterparty(clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))), []string{ibctesting.ConnectionVersion}),
|
||||
},
|
||||
[]connectiontypes.ConnectionPaths{
|
||||
connectiontypes.NewConnectionPaths(clientID, []string{host.ConnectionPath(connectionID)}),
|
||||
|
||||
@ -45,3 +45,35 @@ identifier, but differing feature sets. This will result in undefined behavior
|
||||
with regards to version selection in `ConnOpenTry`. Each version in a set of
|
||||
versions should have a unique version identifier.
|
||||
:::
|
||||
|
||||
### Channel Version Negotation
|
||||
|
||||
During the channel handshake procedure a version must be agreed upon between
|
||||
the two parties. The selection process is largely left to the callers and
|
||||
the verification of valid versioning must be handled by application developers
|
||||
in the channel handshake callbacks.
|
||||
|
||||
During `ChanOpenInit`, a version string is passed in and set in party A's
|
||||
channel state.
|
||||
|
||||
During `ChanOpenTry`, a version string for party A and for party B are passed
|
||||
in. The party A version string must match the version string used in
|
||||
`ChanOpenInit` otherwise channel state verification will fail. The party B
|
||||
version string could be anything (even different than the proposed one by
|
||||
party A). However, the proposed version by party B is expected to be fully
|
||||
supported by party A.
|
||||
|
||||
During the `ChanOpenAck` callback, the application module is expected to verify
|
||||
the version proposed by party B using the `MsgChanOpenAck` `CounterpartyVersion`
|
||||
field. The application module should throw an error if the version string is
|
||||
not valid.
|
||||
|
||||
Application modules may implement their own versioning system, such as semantic
|
||||
versioning, or they may lean upon the versioning system used for in connection
|
||||
version negotiation. To use the connection version semantics the application
|
||||
would simply pass the proto encoded version into each of the handshake calls
|
||||
and decode the version string into a `Version` instance to do version verification
|
||||
in the handshake callbacks.
|
||||
|
||||
Implementations which do not feel they would benefit from versioning can do
|
||||
basic string matching using a single compatible version.
|
||||
|
||||
@ -21,6 +21,7 @@ import (
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
|
||||
ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc-transfer/types"
|
||||
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
|
||||
connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
|
||||
channelexported "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported"
|
||||
@ -38,7 +39,7 @@ const (
|
||||
UnbondingPeriod time.Duration = time.Hour * 24 * 7 * 3
|
||||
MaxClockDrift time.Duration = time.Second * 10
|
||||
|
||||
ChannelVersion = "ics20-1"
|
||||
ChannelVersion = ibctransfertypes.Version
|
||||
InvalidID = "IDisInvalid"
|
||||
|
||||
ConnectionIDPrefix = "connectionid"
|
||||
@ -50,7 +51,7 @@ var (
|
||||
DefaultTrustLevel tmmath.Fraction = lite.DefaultTrustLevel
|
||||
TestHash = []byte("TESTING HASH")
|
||||
|
||||
ConnectionVersion = connectiontypes.DefaultIBCVersion
|
||||
ConnectionVersion = connectiontypes.GetCompatibleEncodedVersions()[0]
|
||||
)
|
||||
|
||||
// TestChain is a testing struct that wraps a simapp with the last TM Header, the current ABCI
|
||||
|
||||
Loading…
Reference in New Issue
Block a user