Verify Client on Connection Handshake (#7057)

* verify client state

* add client state to msgs and retrieve in handler

* fix connection msgs

* fixed handshake tests

* fix tests

* fix sim tests

* revert pb edit

* add ValidateClient tests

* Apply suggestions from code review

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* fix tests

* fixed msgs test

* use ibctesting for client state consts

* Apply suggestions from code review

Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>
Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* address rest of comments

* rename to ValidateSelfClient and update spec

* lint

* Update x/ibc/02-client/keeper/keeper_test.go

* Update x/ibc/02-client/keeper/keeper_test.go

* complete rest of review

* improve cov

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>
This commit is contained in:
Aditya 2020-08-20 18:05:41 -04:00 committed by GitHub
parent ac93d08dce
commit 97df8b605c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 1459 additions and 480 deletions

View File

@ -4,6 +4,7 @@ package ibc.connection;
option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types";
import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
import "ibc/commitment/commitment.proto";
// MsgConnectionOpenInit defines the msg sent by an account on Chain A to
@ -29,18 +30,23 @@ message MsgConnectionOpenTry {
string connection_id = 2 [
(gogoproto.moretags) = "yaml:\"connection_id\""
];
Counterparty counterparty = 3 [(gogoproto.nullable) = false];
repeated string counterparty_versions = 4
google.protobuf.Any client_state = 3 [
(gogoproto.moretags) = "yaml:\"client_state\""
];
Counterparty counterparty = 4 [(gogoproto.nullable) = false];
repeated string counterparty_versions = 5
[(gogoproto.moretags) = "yaml:\"counterparty_versions\""];
uint64 proof_height = 6 [(gogoproto.moretags) = "yaml:\"proof_height\""];
// proof of the initialization the connection on Chain A: `UNITIALIZED ->
// INIT`
bytes proof_init = 5 [(gogoproto.moretags) = "yaml:\"proof_init\""];
uint64 proof_height = 6;
bytes proof_init = 7 [(gogoproto.moretags) = "yaml:\"proof_init\""];
// proof of client state included in message
bytes proof_client = 8 [(gogoproto.moretags) = "yaml:\"proof_client\""];
// proof of client consensus state
bytes proof_consensus = 7 [(gogoproto.moretags) = "yaml:\"proof_consensus\""];
uint64 consensus_height = 8
bytes proof_consensus = 9 [(gogoproto.moretags) = "yaml:\"proof_consensus\""];
uint64 consensus_height = 10
[(gogoproto.moretags) = "yaml:\"consensus_height\""];
bytes signer = 9
bytes signer = 11
[(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
}
@ -51,15 +57,20 @@ message MsgConnectionOpenAck {
(gogoproto.moretags) = "yaml:\"connection_id\""
];
string version = 2;
google.protobuf.Any client_state = 3 [
(gogoproto.moretags) = "yaml:\"client_state\""
];
uint64 proof_height = 4 [(gogoproto.moretags) = "yaml:\"proof_height\""];
// 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\""];
bytes proof_try = 5 [(gogoproto.moretags) = "yaml:\"proof_try\""];
// proof of client state included in message
bytes proof_client = 6 [(gogoproto.moretags) = "yaml:\"proof_client\""];
// proof of client consensus state
bytes proof_consensus = 5 [(gogoproto.moretags) = "yaml:\"proof_consensus\""];
uint64 consensus_height = 6
bytes proof_consensus = 7 [(gogoproto.moretags) = "yaml:\"proof_consensus\""];
uint64 consensus_height = 8
[(gogoproto.moretags) = "yaml:\"consensus_height\""];
bytes signer = 7
bytes signer = 9
[(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
}

View File

@ -319,7 +319,7 @@ func CheckBalance(t *testing.T, app *SimApp, addr sdk.AccAddress, balances sdk.C
// returned.
func SignCheckDeliver(
t *testing.T, txGen client.TxConfig, app *bam.BaseApp, header tmproto.Header, msgs []sdk.Msg,
accNums, seq []uint64, expSimPass, expPass bool, priv ...crypto.PrivKey,
chainID string, accNums, seq []uint64, expSimPass, expPass bool, priv ...crypto.PrivKey,
) (sdk.GasInfo, *sdk.Result, error) {
tx, err := helpers.GenTx(
@ -327,7 +327,7 @@ func SignCheckDeliver(
msgs,
sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)},
helpers.DefaultGenTxGas,
"",
chainID,
accNums,
seq,
priv...,

View File

@ -106,7 +106,6 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Account_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -109,7 +109,7 @@ func TestSendNotEnoughBalance(t *testing.T) {
sendMsg := types.NewMsgSend(addr1, addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 100)})
header := tmproto.Header{Height: app.LastBlockHeight() + 1}
txGen := simapp.MakeEncodingConfig().TxConfig
_, _, err = simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{sendMsg}, []uint64{origAccNum}, []uint64{origSeq}, false, false, priv1)
_, _, err = simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{sendMsg}, "", []uint64{origAccNum}, []uint64{origSeq}, false, false, priv1)
require.Error(t, err)
simapp.CheckBalance(t, app, addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 67)})
@ -177,7 +177,7 @@ func TestSendToModuleAcc(t *testing.T) {
header := tmproto.Header{Height: app.LastBlockHeight() + 1}
txGen := simapp.MakeEncodingConfig().TxConfig
_, _, err = simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{test.msg}, []uint64{origAccNum}, []uint64{origSeq}, test.expSimPass, test.expPass, priv1)
_, _, err = simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{test.msg}, "", []uint64{origAccNum}, []uint64{origSeq}, test.expSimPass, test.expPass, priv1)
if test.expPass {
require.NoError(t, err)
} else {
@ -248,7 +248,7 @@ func TestMsgMultiSendWithAccounts(t *testing.T) {
for _, tc := range testCases {
header := tmproto.Header{Height: app.LastBlockHeight() + 1}
txGen := simapp.MakeEncodingConfig().TxConfig
_, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, tc.msgs, tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
_, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, tc.msgs, "", tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
if tc.expPass {
require.NoError(t, err)
} else {
@ -300,7 +300,7 @@ func TestMsgMultiSendMultipleOut(t *testing.T) {
for _, tc := range testCases {
header := tmproto.Header{Height: app.LastBlockHeight() + 1}
txGen := simapp.MakeEncodingConfig().TxConfig
_, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, tc.msgs, tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
_, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, tc.msgs, "", tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
require.NoError(t, err)
for _, eb := range tc.expectedBalances {
@ -355,7 +355,7 @@ func TestMsgMultiSendMultipleInOut(t *testing.T) {
for _, tc := range testCases {
header := tmproto.Header{Height: app.LastBlockHeight() + 1}
txGen := simapp.MakeEncodingConfig().TxConfig
_, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, tc.msgs, tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
_, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, tc.msgs, "", tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
require.NoError(t, err)
for _, eb := range tc.expectedBalances {
@ -408,7 +408,7 @@ func TestMsgMultiSendDependent(t *testing.T) {
for _, tc := range testCases {
header := tmproto.Header{Height: app.LastBlockHeight() + 1}
txGen := simapp.MakeEncodingConfig().TxConfig
_, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, tc.msgs, tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
_, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, tc.msgs, "", tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...)
require.NoError(t, err)
for _, eb := range tc.expectedBalances {

View File

@ -272,7 +272,6 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Balance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -488,7 +488,6 @@ func local_request_Query_CommunityPool_0(ctx context.Context, marshaler runtime.
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -124,7 +124,6 @@ func local_request_Query_AllEvidence_0(ctx context.Context, marshaler runtime.Ma
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Evidence_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -528,7 +528,6 @@ func local_request_Query_TallyResult_0(ctx context.Context, marshaler runtime.Ma
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Proposal_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -142,7 +142,6 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_DenomTrace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -32,6 +32,16 @@ type ClientState interface {
// State verification functions
VerifyClientState(
store sdk.KVStore,
cdc codec.BinaryMarshaler,
root commitmentexported.Root,
height uint64,
prefix commitmentexported.Prefix,
counterpartyClientIdentifier string,
proof []byte,
clientState ClientState,
) error
VerifyClientConsensusState(
store sdk.KVStore,
cdc codec.BinaryMarshaler,

View File

@ -2,14 +2,17 @@ package keeper
import (
"fmt"
"reflect"
"strings"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/light"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
@ -197,6 +200,52 @@ func (k Keeper) GetSelfConsensusState(ctx sdk.Context, height uint64) (exported.
return consensusState, true
}
// ValidateSelfClient validates the client parameters for a client of the running chain
// This function is only used to validate the client state the counterparty stores for this chain
func (k Keeper) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error {
tmClient, ok := clientState.(*ibctmtypes.ClientState)
if !ok {
return sdkerrors.Wrapf(types.ErrInvalidClient, "client must be a Tendermint client, expected: %T, got: %T",
&ibctmtypes.ClientState{}, tmClient)
}
if clientState.IsFrozen() {
return types.ErrClientFrozen
}
if ctx.ChainID() != tmClient.ChainId {
return sdkerrors.Wrapf(types.ErrInvalidClient, "invalid chain-id. expected: %s, got: %s",
ctx.ChainID(), tmClient.ChainId)
}
if tmClient.LatestHeight > uint64(ctx.BlockHeight()) {
return sdkerrors.Wrapf(types.ErrInvalidClient, "client has LatestHeight %d greater than chain height %d",
tmClient.LatestHeight, ctx.BlockHeight())
}
expectedProofSpecs := commitmenttypes.GetSDKSpecs()
if !reflect.DeepEqual(expectedProofSpecs, tmClient.ProofSpecs) {
return sdkerrors.Wrapf(types.ErrInvalidClient, "client has invalid proof specs. expected: %v got: %v",
expectedProofSpecs, tmClient.ProofSpecs)
}
if err := light.ValidateTrustLevel(tmClient.TrustLevel.ToTendermint()); err != nil {
return sdkerrors.Wrapf(types.ErrInvalidClient, "trust-level invalid: %v", err)
}
expectedUbdPeriod := k.stakingKeeper.UnbondingTime(ctx)
if expectedUbdPeriod != tmClient.UnbondingPeriod {
return sdkerrors.Wrapf(types.ErrInvalidClient, "invalid unbonding period. expected: %s, got: %s",
expectedUbdPeriod, tmClient.UnbondingPeriod)
}
if tmClient.UnbondingPeriod < tmClient.TrustingPeriod {
return sdkerrors.Wrapf(types.ErrInvalidClient, "unbonding period must be greater than trusting period. unbonding period (%d) < trusting period (%d)",
tmClient.UnbondingPeriod, tmClient.TrustingPeriod)
}
return nil
}
// IterateClients provides an iterator over all stored light client State
// objects. For each State object, cb will be called. If the cb returns true,
// the iterator will close and stop.

View File

@ -15,9 +15,11 @@ import (
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/keeper"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/09-localhost/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)
@ -124,6 +126,72 @@ func (suite *KeeperTestSuite) TestSetClientConsensusState() {
suite.Require().Equal(suite.consensusState, tmConsState, "ConsensusState not stored correctly")
}
func (suite *KeeperTestSuite) TestValidateSelfClient() {
testCases := []struct {
name string
clientState clientexported.ClientState
expPass bool
}{
{
"success",
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, uint64(testClientHeight), commitmenttypes.GetSDKSpecs()),
true,
},
{
"invalid client type",
localhosttypes.NewClientState(testChainID, testClientHeight),
false,
},
{
"frozen client",
ibctmtypes.ClientState{testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, uint64(testClientHeight), uint64(testClientHeight), commitmenttypes.GetSDKSpecs()},
false,
},
{
"incorrect chainID",
ibctmtypes.NewClientState("gaiatestnet", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, uint64(testClientHeight), commitmenttypes.GetSDKSpecs()),
false,
},
{
"invalid client height",
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, uint64(testClientHeight)+10, commitmenttypes.GetSDKSpecs()),
false,
},
{
"invalid proof specs",
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, uint64(testClientHeight), nil),
false,
},
{
"invalid trust level",
ibctmtypes.NewClientState(testChainID, ibctmtypes.Fraction{0, 1}, trustingPeriod, ubdPeriod, maxClockDrift, uint64(testClientHeight), commitmenttypes.GetSDKSpecs()),
false,
},
{
"invalid unbonding period",
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+10, maxClockDrift, uint64(testClientHeight), commitmenttypes.GetSDKSpecs()),
false,
},
{
"invalid trusting period",
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, ubdPeriod+10, ubdPeriod, maxClockDrift, uint64(testClientHeight), commitmenttypes.GetSDKSpecs()),
false,
},
}
ctx := suite.ctx.WithChainID(testChainID)
ctx = ctx.WithBlockHeight(testClientHeight)
for _, tc := range testCases {
err := suite.keeper.ValidateSelfClient(ctx, tc.clientState)
if tc.expPass {
suite.Require().NoError(err, "expected valid client for case: %s", tc.name)
} else {
suite.Require().Error(err, "expected invalid client for case: %s", tc.name)
}
}
}
func (suite KeeperTestSuite) TestGetAllClients() {
clientIDs := []string{
testClientID2, testClientID3, testClientID,

View File

@ -70,6 +70,16 @@ func PackClientState(clientState exported.ClientState) (*codectypes.Any, error)
return anyClientState, nil
}
// MustPackClientState calls PackClientState and panics on error.
func MustPackClientState(clientState exported.ClientState) *codectypes.Any {
anyClientState, err := PackClientState(clientState)
if err != nil {
panic(err)
}
return anyClientState
}
// UnpackClientState unpacks an Any into a ClientState. It returns an error if the
// client state can't be unpacked into a ClientState.
func UnpackClientState(any *codectypes.Any) (exported.ClientState, error) {

View File

@ -0,0 +1,42 @@
package types_test
import (
"testing"
"time"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/09-localhost/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
"github.com/stretchr/testify/require"
)
func TestPackClientState(t *testing.T) {
clientState := localhosttypes.NewClientState(chainID, height)
clientAny, err := types.PackClientState(clientState)
require.NoError(t, err, "pack clientstate should not return error")
cs, err := types.UnpackClientState(clientAny)
require.NoError(t, err, "unpack clientstate should not return error")
require.Equal(t, clientState, cs, "client states are not equal after packing and unpacking")
_, err = types.PackClientState(nil)
require.Error(t, err, "did not error after packing nil")
}
func TestPackConsensusState(t *testing.T) {
consensusState := ibctmtypes.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("root")), height, []byte("nextvalshash"))
consensusAny, err := types.PackConsensusState(consensusState)
require.NoError(t, err, "pack consensusstate should not return error")
cs, err := types.UnpackConsensusState(consensusAny)
require.NoError(t, err, "unpack consensusstate should not return error")
require.Equal(t, consensusState, cs, "consensus states are not equal after packing and unpacking")
_, err = types.PackConsensusState(nil)
require.Error(t, err, "did not error after packing nil")
}

View File

@ -7,21 +7,23 @@ import (
// IBC client sentinel errors
var (
ErrClientExists = sdkerrors.Register(SubModuleName, 2, "light client already exists")
ErrClientNotFound = sdkerrors.Register(SubModuleName, 3, "light client not found")
ErrClientFrozen = sdkerrors.Register(SubModuleName, 4, "light client is frozen due to misbehaviour")
ErrConsensusStateNotFound = sdkerrors.Register(SubModuleName, 5, "consensus state not found")
ErrInvalidConsensus = sdkerrors.Register(SubModuleName, 6, "invalid consensus state")
ErrClientTypeNotFound = sdkerrors.Register(SubModuleName, 7, "client type not found")
ErrInvalidClientType = sdkerrors.Register(SubModuleName, 8, "invalid client type")
ErrRootNotFound = sdkerrors.Register(SubModuleName, 9, "commitment root not found")
ErrInvalidHeader = sdkerrors.Register(SubModuleName, 10, "invalid client header")
ErrInvalidEvidence = sdkerrors.Register(SubModuleName, 11, "invalid light client misbehaviour evidence")
ErrFailedClientConsensusStateVerification = sdkerrors.Register(SubModuleName, 12, "client consensus state verification failed")
ErrFailedConnectionStateVerification = sdkerrors.Register(SubModuleName, 13, "connection state verification failed")
ErrFailedChannelStateVerification = sdkerrors.Register(SubModuleName, 14, "channel state verification failed")
ErrFailedPacketCommitmentVerification = sdkerrors.Register(SubModuleName, 15, "packet commitment verification failed")
ErrFailedPacketAckVerification = sdkerrors.Register(SubModuleName, 16, "packet acknowledgement verification failed")
ErrFailedPacketAckAbsenceVerification = sdkerrors.Register(SubModuleName, 17, "packet acknowledgement absence verification failed")
ErrFailedNextSeqRecvVerification = sdkerrors.Register(SubModuleName, 18, "next sequence receive verification failed")
ErrSelfConsensusStateNotFound = sdkerrors.Register(SubModuleName, 19, "self consensus state not found")
ErrInvalidClient = sdkerrors.Register(SubModuleName, 3, "light client is invalid")
ErrClientNotFound = sdkerrors.Register(SubModuleName, 4, "light client not found")
ErrClientFrozen = sdkerrors.Register(SubModuleName, 5, "light client is frozen due to misbehaviour")
ErrConsensusStateNotFound = sdkerrors.Register(SubModuleName, 6, "consensus state not found")
ErrInvalidConsensus = sdkerrors.Register(SubModuleName, 7, "invalid consensus state")
ErrClientTypeNotFound = sdkerrors.Register(SubModuleName, 8, "client type not found")
ErrInvalidClientType = sdkerrors.Register(SubModuleName, 9, "invalid client type")
ErrRootNotFound = sdkerrors.Register(SubModuleName, 10, "commitment root not found")
ErrInvalidHeader = sdkerrors.Register(SubModuleName, 11, "invalid client header")
ErrInvalidEvidence = sdkerrors.Register(SubModuleName, 12, "invalid light client misbehaviour evidence")
ErrFailedClientStateVerification = sdkerrors.Register(SubModuleName, 13, "client state verification failed")
ErrFailedClientConsensusStateVerification = sdkerrors.Register(SubModuleName, 14, "client consensus state verification failed")
ErrFailedConnectionStateVerification = sdkerrors.Register(SubModuleName, 15, "connection state verification failed")
ErrFailedChannelStateVerification = sdkerrors.Register(SubModuleName, 16, "channel state verification failed")
ErrFailedPacketCommitmentVerification = sdkerrors.Register(SubModuleName, 17, "packet commitment verification failed")
ErrFailedPacketAckVerification = sdkerrors.Register(SubModuleName, 18, "packet acknowledgement verification failed")
ErrFailedPacketAckAbsenceVerification = sdkerrors.Register(SubModuleName, 19, "packet acknowledgement absence verification failed")
ErrFailedNextSeqRecvVerification = sdkerrors.Register(SubModuleName, 20, "next sequence receive verification failed")
ErrSelfConsensusStateNotFound = sdkerrors.Register(SubModuleName, 21, "self consensus state not found")
)

View File

@ -67,17 +67,17 @@ func NewConnectionOpenInitCmd() *cobra.Command {
func NewConnectionOpenTryCmd() *cobra.Command {
cmd := &cobra.Command{
Use: strings.TrimSpace(`open-try [connection-id] [client-id]
[counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json]
[counterparty-versions] [path/to/proof_init.json] [path/to/proof_consensus.json]`),
[counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json] [path/to/client_state.json]
[counterparty-versions] [path/to/proof_init.json] [path/to/proof_client.json] [path/to/proof_consensus.json]`),
Short: "initiate connection handshake between two chains",
Long: "Initialize a connection on chain A with a given counterparty chain B",
Example: fmt.Sprintf(
`%s tx %s %s open-try connection-id] [client-id] \
[counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json] \
[counterparty-versions] [path/to/proof_init.json] [path/tp/proof_consensus.json]`,
[counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json] [path/to/client_state.json]\
[counterparty-versions] [path/to/proof_init.json] [path/to/proof_client.json] [path/tp/proof_consensus.json]`,
version.AppName, host.ModuleName, types.SubModuleName,
),
Args: cobra.ExactArgs(8),
Args: cobra.ExactArgs(10),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
@ -95,15 +95,25 @@ func NewConnectionOpenTryCmd() *cobra.Command {
return err
}
// TODO: parse strings?
counterpartyVersions := args[5]
proofInit, err := utils.ParseProof(clientCtx.LegacyAmino, args[6])
counterpartyClient, err := utils.ParseClientState(clientCtx.LegacyAmino, args[5])
if err != nil {
return err
}
proofConsensus, err := utils.ParseProof(clientCtx.LegacyAmino, args[7])
// TODO: parse strings?
counterpartyVersions := args[6]
proofInit, err := utils.ParseProof(clientCtx.LegacyAmino, args[7])
if err != nil {
return err
}
proofClient, err := utils.ParseProof(clientCtx.LegacyAmino, args[8])
if err != nil {
return err
}
proofConsensus, err := utils.ParseProof(clientCtx.LegacyAmino, args[9])
if err != nil {
return err
}
@ -116,7 +126,8 @@ func NewConnectionOpenTryCmd() *cobra.Command {
msg := types.NewMsgConnectionOpenTry(
connectionID, clientID, counterpartyConnectionID, counterpartyClientID,
counterpartyPrefix, []string{counterpartyVersions}, proofInit, proofConsensus, proofHeight,
counterpartyClient, counterpartyPrefix, []string{counterpartyVersions},
proofInit, proofClient, proofConsensus, proofHeight,
consensusHeight, clientCtx.GetFromAddress(),
)
@ -137,14 +148,14 @@ func NewConnectionOpenTryCmd() *cobra.Command {
// connection open attempt from chain B to chain A
func NewConnectionOpenAckCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "open-ack [connection-id] [path/to/proof_try.json] [path/to/proof_consensus.json] [version]",
Use: "open-ack [connection-id] [path/to/client_state.json] [path/to/proof_try.json] [path/to/proof_client.json] [path/to/proof_consensus.json] [version]",
Short: "relay the acceptance of a connection open attempt",
Long: "Relay the acceptance of a connection open attempt from chain B to chain A",
Example: fmt.Sprintf(
"%s tx %s %s open-ack [connection-id] [path/to/proof_try.json] [path/to/proof_consensus.json] [version]",
"%s tx %s %s open-ack [connection-id] [path/to/client_state.json] [path/to/proof_try.json] [path/to/proof_client.json] [path/to/proof_consensus.json] [version]",
version.AppName, host.ModuleName, types.SubModuleName,
),
Args: cobra.ExactArgs(4),
Args: cobra.ExactArgs(6),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
@ -154,12 +165,22 @@ func NewConnectionOpenAckCmd() *cobra.Command {
connectionID := args[0]
proofTry, err := utils.ParseProof(clientCtx.LegacyAmino, args[1])
counterpartyClient, err := utils.ParseClientState(clientCtx.LegacyAmino, args[1])
if err != nil {
return err
}
proofConsensus, err := utils.ParseProof(clientCtx.LegacyAmino, args[2])
proofTry, err := utils.ParseProof(clientCtx.LegacyAmino, args[2])
if err != nil {
return err
}
proofClient, err := utils.ParseProof(clientCtx.LegacyAmino, args[3])
if err != nil {
return err
}
proofConsensus, err := utils.ParseProof(clientCtx.LegacyAmino, args[4])
if err != nil {
return err
}
@ -170,10 +191,10 @@ func NewConnectionOpenAckCmd() *cobra.Command {
return err
}
version := args[3]
version := args[5]
msg := types.NewMsgConnectionOpenAck(
connectionID, proofTry, proofConsensus, proofHeight,
connectionID, counterpartyClient, proofTry, proofClient, proofConsensus, proofHeight,
consensusHeight, version, clientCtx.GetFromAddress(),
)

View File

@ -12,6 +12,7 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
clientutils "github.com/cosmos/cosmos-sdk/x/ibc/02-client/client/utils"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
@ -174,6 +175,23 @@ func QueryConnectionConsensusState(
return res, nil
}
// ParseClientState unmarshals a cmd input argument from a JSON string to a client state
// If the input is not a JSON, it looks for a path to the JSON file
func ParseClientState(cdc *codec.LegacyAmino, arg string) (clientexported.ClientState, error) {
var clientState clientexported.ClientState
if err := cdc.UnmarshalJSON([]byte(arg), &clientState); err != nil {
// check for file path if JSON input is not provided
contents, err := ioutil.ReadFile(arg)
if err != nil {
return nil, errors.New("either JSON input nor path to .json file were provided")
}
if err := cdc.UnmarshalJSON(contents, &clientState); err != nil {
return nil, errors.Wrap(err, "error unmarshalling client state")
}
}
return clientState, nil
}
// ParsePrefix unmarshals an cmd input argument from a JSON string to a commitment
// Prefix. If the input is not a JSON, it looks for a path to the JSON file.
func ParsePrefix(cdc *codec.LegacyAmino, arg string) (commitmenttypes.MerklePrefix, error) {

View File

@ -3,6 +3,7 @@ package connection
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/keeper"
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
)
@ -36,9 +37,14 @@ func HandleMsgConnectionOpenInit(ctx sdk.Context, k keeper.Keeper, msg *types.Ms
// HandleMsgConnectionOpenTry defines the sdk.Handler for MsgConnectionOpenTry
func HandleMsgConnectionOpenTry(ctx sdk.Context, k keeper.Keeper, msg *types.MsgConnectionOpenTry) (*sdk.Result, error) {
targetClient, err := clienttypes.UnpackClientState(msg.ClientState)
if err != nil {
return nil, sdkerrors.Wrapf(err, "client in msg is not exported.ClientState. invalid client: %v.", targetClient)
}
if err := k.ConnOpenTry(
ctx, msg.ConnectionId, msg.Counterparty, msg.ClientId,
msg.CounterpartyVersions, msg.ProofInit, msg.ProofConsensus,
ctx, msg.ConnectionId, msg.Counterparty, msg.ClientId, targetClient,
msg.CounterpartyVersions, msg.ProofInit, msg.ProofClient, msg.ProofConsensus,
msg.ProofHeight, msg.ConsensusHeight,
); err != nil {
return nil, sdkerrors.Wrap(err, "connection handshake open try failed")
@ -65,8 +71,14 @@ func HandleMsgConnectionOpenTry(ctx sdk.Context, k keeper.Keeper, msg *types.Msg
// HandleMsgConnectionOpenAck defines the sdk.Handler for MsgConnectionOpenAck
func HandleMsgConnectionOpenAck(ctx sdk.Context, k keeper.Keeper, msg *types.MsgConnectionOpenAck) (*sdk.Result, error) {
targetClient, err := clienttypes.UnpackClientState(msg.ClientState)
if err != nil {
return nil, sdkerrors.Wrapf(err, "client in msg is not exported.ClientState. invalid client: %v", targetClient)
}
if err := k.ConnOpenAck(
ctx, msg.ConnectionId, msg.Version, msg.ProofTry, msg.ProofConsensus,
ctx, msg.ConnectionId, targetClient, msg.Version,
msg.ProofTry, msg.ProofClient, msg.ProofConsensus,
msg.ProofHeight, msg.ConsensusHeight,
); err != nil {
return nil, sdkerrors.Wrap(err, "connection handshake open ack failed")

View File

@ -6,6 +6,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
@ -48,8 +49,10 @@ func (k Keeper) ConnOpenTry(
connectionID string, // desiredIdentifier
counterparty types.Counterparty, // counterpartyConnectionIdentifier, counterpartyPrefix and counterpartyClientIdentifier
clientID string, // clientID of chainA
clientState clientexported.ClientState, // clientState that chainA has for chainB
counterpartyVersions []string, // supported versions of chain A
proofInit []byte, // proof that chainA stored connectionEnd in state (on ConnOpenInit)
proofClient []byte, // proof that chainA stored a light client of chainB
proofConsensus []byte, // proof that chainA stored chainB's consensus state at consensus height
proofHeight uint64, // height at which relayer constructs proof of A storing connectionEnd in state
consensusHeight uint64, // latest height of chain B which chain A has stored in its chain B client
@ -61,6 +64,11 @@ func (k Keeper) ConnOpenTry(
)
}
// validate client parameters of a chainB client stored on chainA
if err := k.clientKeeper.ValidateSelfClient(ctx, clientState); err != nil {
return err
}
expectedConsensusState, found := k.clientKeeper.GetSelfConsensusState(ctx, consensusHeight)
if !found {
return clienttypes.ErrSelfConsensusStateNotFound
@ -90,6 +98,11 @@ func (k Keeper) ConnOpenTry(
return err
}
// Check that ChainA stored the clientState provided in the msg
if err := k.VerifyClientState(ctx, connection, proofHeight, proofClient, clientState); err != nil {
return err
}
// Check that ChainA stored the correct ConsensusState of chainB at the given consensusHeight
if err := k.VerifyClientConsensusState(
ctx, connection, proofHeight, consensusHeight, proofConsensus, expectedConsensusState,
@ -128,8 +141,10 @@ func (k Keeper) ConnOpenTry(
func (k Keeper) ConnOpenAck(
ctx sdk.Context,
connectionID string,
clientState clientexported.ClientState, // client state for chainA on chainB
encodedVersion string, // version that ChainB chose in ConnOpenTry
proofTry []byte, // proof that connectionEnd was added to ChainB state in ConnOpenTry
proofClient []byte, // proof of client state on chainB for chainA
proofConsensus []byte, // proof that chainB has stored ConsensusState of chainA on its client
proofHeight uint64, // height that relayer constructed proofTry
consensusHeight uint64, // latest height of chainA that chainB has stored on its chainA client
@ -175,6 +190,11 @@ func (k Keeper) ConnOpenAck(
return err
}
// validate client parameters of a chainA client stored on chainB
if err := k.clientKeeper.ValidateSelfClient(ctx, clientState); err != nil {
return err
}
// Retrieve chainA's consensus state at consensusheight
expectedConsensusState, found := k.clientKeeper.GetSelfConsensusState(ctx, consensusHeight)
if !found {
@ -193,6 +213,11 @@ func (k Keeper) ConnOpenAck(
return err
}
// Check that ChainB stored the clientState provided in the msg
if err := k.VerifyClientState(ctx, connection, proofHeight, proofClient, clientState); err != nil {
return err
}
// Ensure that ChainB has stored the correct ConsensusState for chainA at the consensusHeight
if err := k.VerifyClientConsensusState(
ctx, connection, proofHeight, consensusHeight, proofConsensus, expectedConsensusState,

View File

@ -60,10 +60,11 @@ func (suite *KeeperTestSuite) TestConnOpenInit() {
// connection on chainA is INIT
func (suite *KeeperTestSuite) TestConnOpenTry() {
var (
clientA string
clientB string
versions []string
consensusHeight uint64
clientA string
clientB string
versions []string
consensusHeight uint64
counterpartyClient clientexported.ClientState
)
testCases := []struct {
@ -75,12 +76,33 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, clientexported.Tendermint)
_, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
suite.Require().NoError(err)
// retrieve client state of chainA to pass as counterpartyClient
counterpartyClient = suite.chainA.GetClientState(clientA)
}, true},
{"invalid counterparty client", func() {
clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, clientexported.Tendermint)
_, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
suite.Require().NoError(err)
// retrieve client state of chainB to pass as counterpartyClient
counterpartyClient = suite.chainA.GetClientState(clientA)
// Set an invalid client of chainA on chainB
tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState)
suite.Require().True(ok)
tmClient.ChainId = "wrongchainid"
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientA, tmClient)
}, false},
{"consensus height >= latest height", func() {
clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, clientexported.Tendermint)
_, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
suite.Require().NoError(err)
// retrieve client state of chainA to pass as counterpartyClient
counterpartyClient = suite.chainA.GetClientState(clientA)
consensusHeight = uint64(suite.chainB.GetContext().BlockHeight())
}, false},
{"self consensus state not found", func() {
@ -88,6 +110,9 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
_, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
suite.Require().NoError(err)
// retrieve client state of chainA to pass as counterpartyClient
counterpartyClient = suite.chainA.GetClientState(clientA)
consensusHeight = 1
}, false},
{"counterparty versions is empty", func() {
@ -95,6 +120,9 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
_, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
suite.Require().NoError(err)
// retrieve client state of chainA to pass as counterpartyClient
counterpartyClient = suite.chainA.GetClientState(clientA)
versions = nil
}, false},
{"counterparty versions don't have a match", func() {
@ -102,6 +130,9 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
_, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
suite.Require().NoError(err)
// retrieve client state of chainA to pass as counterpartyClient
counterpartyClient = suite.chainA.GetClientState(clientA)
version, err := types.NewVersion("0.0", nil).Encode()
suite.Require().NoError(err)
versions = []string{version}
@ -109,9 +140,29 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
{"connection state verification failed", func() {
clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, clientexported.Tendermint)
// chainA connection not created
// retrieve client state of chainA to pass as counterpartyClient
counterpartyClient = suite.chainA.GetClientState(clientA)
}, false},
{"client state verification failed", func() {
clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, clientexported.Tendermint)
_, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
suite.Require().NoError(err)
// retrieve client state of chainA to pass as counterpartyClient
counterpartyClient = suite.chainA.GetClientState(clientA)
// modify counterparty client without setting in store so it still passes validate but fails proof verification
tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState)
suite.Require().True(ok)
tmClient.LatestHeight++
}, false},
{"consensus state verification failed", func() {
clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, clientexported.Tendermint)
// retrieve client state of chainA to pass as counterpartyClient
counterpartyClient = suite.chainA.GetClientState(clientA)
// give chainA wrong consensus state for chainB
consState, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetLatestClientConsensusState(suite.chainA.GetContext(), clientA)
suite.Require().True(found)
@ -128,6 +179,9 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
{"invalid previous connection is in TRYOPEN", func() {
clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, clientexported.Tendermint)
// retrieve client state of chainA to pass as counterpartyClient
counterpartyClient = suite.chainA.GetClientState(clientA)
// open init chainA
connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
suite.Require().NoError(err)
@ -165,9 +219,13 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
consensusKey := host.FullKeyClientPath(clientA, host.KeyConsensusState(consensusHeight))
proofConsensus, _ := suite.chainA.QueryProof(consensusKey)
// retrieve proof of counterparty clientstate on chainA
clientKey := host.FullKeyClientPath(clientA, host.KeyClientState())
proofClient, _ := suite.chainA.QueryProof(clientKey)
err := suite.chainB.App.IBCKeeper.ConnectionKeeper.ConnOpenTry(
suite.chainB.GetContext(), connB.ID, counterparty, clientB,
versions, proofInit, proofConsensus,
suite.chainB.GetContext(), connB.ID, counterparty, clientB, counterpartyClient,
versions, proofInit, proofClient, proofConsensus,
proofHeight, consensusHeight,
)
@ -184,10 +242,11 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
// the initialization (TRYINIT) of the connection on Chain B (ID #2).
func (suite *KeeperTestSuite) TestConnOpenAck() {
var (
clientA string
clientB string
consensusHeight uint64
version string
clientA string
clientB string
consensusHeight uint64
version string
counterpartyClient clientexported.ClientState
)
testCases := []struct {
@ -200,6 +259,9 @@ func (suite *KeeperTestSuite) TestConnOpenAck() {
connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
suite.Require().NoError(err)
// retrieve client state of chainB to pass as counterpartyClient
counterpartyClient = suite.chainB.GetClientState(clientB)
err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA)
suite.Require().NoError(err)
}, true},
@ -220,12 +282,36 @@ func (suite *KeeperTestSuite) TestConnOpenAck() {
suite.coordinator.UpdateClient(suite.chainB, suite.chainA, clientB, clientexported.Tendermint)
suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, clientexported.Tendermint)
// retrieve client state of chainB to pass as counterpartyClient
counterpartyClient = suite.chainB.GetClientState(clientB)
}, true},
{"invalid counterparty client", 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)
// retrieve client state of chainB to pass as counterpartyClient
counterpartyClient = suite.chainB.GetClientState(clientB)
// Set an invalid client of chainA on chainB
tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState)
suite.Require().True(ok)
tmClient.ChainId = "wrongchainid"
suite.chainB.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainB.GetContext(), clientB, tmClient)
err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA)
suite.Require().NoError(err)
}, false},
{"consensus height >= latest height", 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)
// retrieve client state of chainB to pass as counterpartyClient
counterpartyClient = suite.chainB.GetClientState(clientB)
err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA)
suite.Require().NoError(err)
@ -234,6 +320,9 @@ func (suite *KeeperTestSuite) TestConnOpenAck() {
{"connection not found", func() {
// connections are never created
clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, clientexported.Tendermint)
// retrieve client state of chainB to pass as counterpartyClient
counterpartyClient = suite.chainB.GetClientState(clientB)
}, false},
{"connection state is not INIT", func() {
// connection state is already OPEN on chainA
@ -241,6 +330,9 @@ func (suite *KeeperTestSuite) TestConnOpenAck() {
connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
suite.Require().NoError(err)
// retrieve client state of chainB to pass as counterpartyClient
counterpartyClient = suite.chainB.GetClientState(clientB)
err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA)
suite.Require().NoError(err)
@ -252,6 +344,9 @@ func (suite *KeeperTestSuite) TestConnOpenAck() {
connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
suite.Require().NoError(err)
// retrieve client state of chainB to pass as counterpartyClient
counterpartyClient = suite.chainB.GetClientState(clientB)
err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA)
suite.Require().NoError(err)
@ -263,6 +358,9 @@ func (suite *KeeperTestSuite) TestConnOpenAck() {
connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
suite.Require().NoError(err)
// retrieve client state of chainB to pass as counterpartyClient
counterpartyClient = suite.chainB.GetClientState(clientB)
err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA)
suite.Require().NoError(err)
@ -273,6 +371,9 @@ func (suite *KeeperTestSuite) TestConnOpenAck() {
connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
suite.Require().NoError(err)
// retrieve client state of chainB to pass as counterpartyClient
counterpartyClient = suite.chainB.GetClientState(clientB)
err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA)
suite.Require().NoError(err)
@ -284,6 +385,9 @@ func (suite *KeeperTestSuite) TestConnOpenAck() {
connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
suite.Require().NoError(err)
// retrieve client state of chainB to pass as counterpartyClient
counterpartyClient = suite.chainB.GetClientState(clientB)
err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA)
suite.Require().NoError(err)
@ -294,12 +398,34 @@ func (suite *KeeperTestSuite) TestConnOpenAck() {
clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, clientexported.Tendermint)
_, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB)
suite.Require().NoError(err)
// retrieve client state of chainB to pass as counterpartyClient
counterpartyClient = suite.chainB.GetClientState(clientB)
}, false},
{"client state verification failed", 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)
// retrieve client state of chainB to pass as counterpartyClient
counterpartyClient = suite.chainB.GetClientState(clientB)
// modify counterparty client without setting in store so it still passes validate but fails proof verification
tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState)
suite.Require().True(ok)
tmClient.LatestHeight++
err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA)
suite.Require().NoError(err)
}, false},
{"consensus state verification failed", 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)
// retrieve client state of chainB to pass as counterpartyClient
counterpartyClient = suite.chainB.GetClientState(clientB)
// give chainB wrong consensus state for chainA
consState, found := suite.chainB.App.IBCKeeper.ClientKeeper.GetLatestClientConsensusState(suite.chainB.GetContext(), clientB)
suite.Require().True(found)
@ -340,9 +466,13 @@ func (suite *KeeperTestSuite) TestConnOpenAck() {
consensusKey := host.FullKeyClientPath(clientB, host.KeyConsensusState(consensusHeight))
proofConsensus, _ := suite.chainB.QueryProof(consensusKey)
// retrieve proof of counterparty clientstate on chainA
clientKey := host.FullKeyClientPath(clientB, host.KeyClientState())
proofClient, _ := suite.chainB.QueryProof(clientKey)
err := suite.chainA.App.IBCKeeper.ConnectionKeeper.ConnOpenAck(
suite.chainA.GetContext(), connA.ID, version,
proofTry, proofConsensus, proofHeight, consensusHeight,
suite.chainA.GetContext(), connA.ID, counterpartyClient, version,
proofTry, proofClient, proofConsensus, proofHeight, consensusHeight,
)
if tc.expPass {

View File

@ -9,6 +9,35 @@ import (
channelexported "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported"
)
// VerifyClientState verifies a proof of a client state of the running machine
// stored on the target machine
func (k Keeper) VerifyClientState(
ctx sdk.Context,
connection exported.ConnectionI,
height uint64,
proof []byte,
clientState clientexported.ClientState,
) error {
clientID := connection.GetClientID()
targetClient, found := k.clientKeeper.GetClientState(ctx, clientID)
if !found {
return sdkerrors.Wrap(clienttypes.ErrClientNotFound, clientID)
}
targetConsState, found := k.clientKeeper.GetClientConsensusState(ctx, clientID, height)
if !found {
return sdkerrors.Wrapf(clienttypes.ErrConsensusStateNotFound, "clientID: %s with height: %d", clientID, height)
}
if err := targetClient.VerifyClientState(
k.clientKeeper.ClientStore(ctx, clientID), k.cdc, targetConsState.GetRoot(), height,
connection.GetCounterparty().GetPrefix(), connection.GetCounterparty().GetClientID(), proof, clientState); err != nil {
return sdkerrors.Wrapf(err, "failed client state verification for target client: %s", connection.GetClientID())
}
return nil
}
// VerifyClientConsensusState verifies a proof of the consensus state of the
// specified client stored on the target machine.
func (k Keeper) VerifyClientConsensusState(

View File

@ -12,6 +12,57 @@ import (
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
)
// TestVerifyClientState verifies a client state of chainA
// stored on clientB (which is on chainB)
func (suite *KeeperTestSuite) TestVerifyClientState() {
cases := []struct {
msg string
changeClientID bool
heightDiff uint64
malleateCounterparty bool
expPass bool
}{
{"verification success", false, 0, false, true},
{"client state not found", true, 0, false, false},
{"consensus state for proof height not found", false, 5, false, false},
{"verification failed", false, 0, true, false},
}
for _, tc := range cases {
tc := tc
suite.Run(tc.msg, func() {
suite.SetupTest() // reset
_, clientB, connA, _ := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, clientexported.Tendermint)
counterpartyClient, clientProof := suite.chainB.QueryClientStateProof(clientB)
proofHeight := uint64(suite.chainB.GetContext().BlockHeight() - 1)
if tc.malleateCounterparty {
tmClient, _ := counterpartyClient.(*ibctmtypes.ClientState)
tmClient.ChainId = "wrongChainID"
}
connection := suite.chainA.GetConnection(connA)
if tc.changeClientID {
connection.ClientId = ibctesting.InvalidID
}
err := suite.chainA.App.IBCKeeper.ConnectionKeeper.VerifyClientState(
suite.chainA.GetContext(), connection,
proofHeight+tc.heightDiff, clientProof, counterpartyClient,
)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
// TestVerifyClientConsensusState verifies that the consensus state of
// chainA stored on clientB (which is on chainB) matches the consensus
// state for chainA at that height.
@ -74,7 +125,7 @@ func (suite *KeeperTestSuite) TestVerifyClientConsensusState() {
}
proof, consensusHeight := suite.chainB.QueryConsensusStateProof(connB.ClientID)
proofHeight := uint64(suite.chainA.GetContext().BlockHeight() - 1)
proofHeight := uint64(suite.chainB.GetContext().BlockHeight() - 1)
consensusState, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetSelfConsensusState(suite.chainA.GetContext(), consensusHeight)
suite.Require().True(found)

View File

@ -5,8 +5,9 @@ package types
import (
fmt "fmt"
types "github.com/cosmos/cosmos-sdk/codec/types"
github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types"
types "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
types1 "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
@ -138,16 +139,19 @@ func (m *MsgConnectionOpenInit) GetSigner() github_com_cosmos_cosmos_sdk_types.A
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"`
ClientState *types.Any `protobuf:"bytes,3,opt,name=client_state,json=clientState,proto3" json:"client_state,omitempty" yaml:"client_state"`
Counterparty Counterparty `protobuf:"bytes,4,opt,name=counterparty,proto3" json:"counterparty"`
CounterpartyVersions []string `protobuf:"bytes,5,rep,name=counterparty_versions,json=counterpartyVersions,proto3" json:"counterparty_versions,omitempty" yaml:"counterparty_versions"`
ProofHeight uint64 `protobuf:"varint,6,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height,omitempty" yaml:"proof_height"`
// 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"`
ProofInit []byte `protobuf:"bytes,7,opt,name=proof_init,json=proofInit,proto3" json:"proof_init,omitempty" yaml:"proof_init"`
// proof of client state included in message
ProofClient []byte `protobuf:"bytes,8,opt,name=proof_client,json=proofClient,proto3" json:"proof_client,omitempty" yaml:"proof_client"`
// proof of client consensus state
ProofConsensus []byte `protobuf:"bytes,7,opt,name=proof_consensus,json=proofConsensus,proto3" json:"proof_consensus,omitempty" yaml:"proof_consensus"`
ConsensusHeight uint64 `protobuf:"varint,8,opt,name=consensus_height,json=consensusHeight,proto3" json:"consensus_height,omitempty" yaml:"consensus_height"`
Signer github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,9,opt,name=signer,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"signer,omitempty"`
ProofConsensus []byte `protobuf:"bytes,9,opt,name=proof_consensus,json=proofConsensus,proto3" json:"proof_consensus,omitempty" yaml:"proof_consensus"`
ConsensusHeight uint64 `protobuf:"varint,10,opt,name=consensus_height,json=consensusHeight,proto3" json:"consensus_height,omitempty" yaml:"consensus_height"`
Signer github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,11,opt,name=signer,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"signer,omitempty"`
}
func (m *MsgConnectionOpenTry) Reset() { *m = MsgConnectionOpenTry{} }
@ -197,6 +201,13 @@ func (m *MsgConnectionOpenTry) GetConnectionId() string {
return ""
}
func (m *MsgConnectionOpenTry) GetClientState() *types.Any {
if m != nil {
return m.ClientState
}
return nil
}
func (m *MsgConnectionOpenTry) GetCounterparty() Counterparty {
if m != nil {
return m.Counterparty
@ -211,6 +222,13 @@ func (m *MsgConnectionOpenTry) GetCounterpartyVersions() []string {
return nil
}
func (m *MsgConnectionOpenTry) GetProofHeight() uint64 {
if m != nil {
return m.ProofHeight
}
return 0
}
func (m *MsgConnectionOpenTry) GetProofInit() []byte {
if m != nil {
return m.ProofInit
@ -218,11 +236,11 @@ func (m *MsgConnectionOpenTry) GetProofInit() []byte {
return nil
}
func (m *MsgConnectionOpenTry) GetProofHeight() uint64 {
func (m *MsgConnectionOpenTry) GetProofClient() []byte {
if m != nil {
return m.ProofHeight
return m.ProofClient
}
return 0
return nil
}
func (m *MsgConnectionOpenTry) GetProofConsensus() []byte {
@ -249,16 +267,19 @@ func (m *MsgConnectionOpenTry) GetSigner() github_com_cosmos_cosmos_sdk_types.Ac
// 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"`
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"`
ClientState *types.Any `protobuf:"bytes,3,opt,name=client_state,json=clientState,proto3" json:"client_state,omitempty" yaml:"client_state"`
ProofHeight uint64 `protobuf:"varint,4,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height,omitempty" yaml:"proof_height"`
// 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"`
ProofTry []byte `protobuf:"bytes,5,opt,name=proof_try,json=proofTry,proto3" json:"proof_try,omitempty" yaml:"proof_try"`
// proof of client state included in message
ProofClient []byte `protobuf:"bytes,6,opt,name=proof_client,json=proofClient,proto3" json:"proof_client,omitempty" yaml:"proof_client"`
// proof of client consensus state
ProofConsensus []byte `protobuf:"bytes,5,opt,name=proof_consensus,json=proofConsensus,proto3" json:"proof_consensus,omitempty" yaml:"proof_consensus"`
ConsensusHeight uint64 `protobuf:"varint,6,opt,name=consensus_height,json=consensusHeight,proto3" json:"consensus_height,omitempty" yaml:"consensus_height"`
Signer github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,7,opt,name=signer,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"signer,omitempty"`
ProofConsensus []byte `protobuf:"bytes,7,opt,name=proof_consensus,json=proofConsensus,proto3" json:"proof_consensus,omitempty" yaml:"proof_consensus"`
ConsensusHeight uint64 `protobuf:"varint,8,opt,name=consensus_height,json=consensusHeight,proto3" json:"consensus_height,omitempty" yaml:"consensus_height"`
Signer github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,9,opt,name=signer,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"signer,omitempty"`
}
func (m *MsgConnectionOpenAck) Reset() { *m = MsgConnectionOpenAck{} }
@ -308,9 +329,9 @@ func (m *MsgConnectionOpenAck) GetVersion() string {
return ""
}
func (m *MsgConnectionOpenAck) GetProofTry() []byte {
func (m *MsgConnectionOpenAck) GetClientState() *types.Any {
if m != nil {
return m.ProofTry
return m.ClientState
}
return nil
}
@ -322,6 +343,20 @@ func (m *MsgConnectionOpenAck) GetProofHeight() uint64 {
return 0
}
func (m *MsgConnectionOpenAck) GetProofTry() []byte {
if m != nil {
return m.ProofTry
}
return nil
}
func (m *MsgConnectionOpenAck) GetProofClient() []byte {
if m != nil {
return m.ProofClient
}
return nil
}
func (m *MsgConnectionOpenAck) GetProofConsensus() []byte {
if m != nil {
return m.ProofConsensus
@ -520,7 +555,7 @@ type Counterparty struct {
// 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"`
Prefix types1.MerklePrefix `protobuf:"bytes,3,opt,name=prefix,proto3" json:"prefix"`
}
func (m *Counterparty) Reset() { *m = Counterparty{} }
@ -716,65 +751,69 @@ func init() {
func init() { proto.RegisterFile("ibc/connection/connection.proto", fileDescriptor_3bf62bacf5a27ee9) }
var fileDescriptor_3bf62bacf5a27ee9 = []byte{
// 919 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0xcd, 0x6e, 0xe3, 0x54,
0x14, 0x8e, 0x1d, 0xe7, 0xef, 0x34, 0x69, 0x33, 0x26, 0x65, 0xac, 0x30, 0xd8, 0xc6, 0x6c, 0x22,
0x50, 0x13, 0x66, 0x06, 0xcd, 0xa2, 0x12, 0x8b, 0x24, 0x93, 0x0a, 0x0b, 0xa6, 0x13, 0xb9, 0x29,
0x12, 0xdd, 0x44, 0xa9, 0x7d, 0x93, 0x5e, 0xa5, 0xb1, 0x23, 0xfb, 0x16, 0x4d, 0xdf, 0x60, 0xd4,
0x15, 0x12, 0x2b, 0x24, 0x2a, 0x21, 0xf1, 0x0e, 0x3c, 0x00, 0xab, 0x59, 0xce, 0x72, 0xd8, 0x58,
0xa8, 0x7d, 0x83, 0x2c, 0xd9, 0x80, 0x7c, 0xaf, 0xff, 0x9a, 0x16, 0x50, 0x9b, 0x91, 0xd0, 0xac,
0x72, 0xfe, 0x7d, 0xcf, 0xf9, 0xbe, 0x9c, 0x7b, 0x41, 0xc1, 0x87, 0x66, 0xcb, 0x74, 0x6c, 0x1b,
0x99, 0x04, 0x3b, 0x76, 0x4a, 0x6c, 0xce, 0x5d, 0x87, 0x38, 0xe2, 0x3a, 0x3e, 0x34, 0x9b, 0x89,
0xb5, 0x5e, 0x9b, 0x38, 0x13, 0x87, 0xba, 0x5a, 0x81, 0xc4, 0xa2, 0xea, 0x61, 0x99, 0xd9, 0x0c,
0x93, 0x19, 0xb2, 0x49, 0x4a, 0x64, 0x01, 0xda, 0x4f, 0x3c, 0x6c, 0x3e, 0xf3, 0x26, 0xdd, 0xb8,
0xd0, 0xf3, 0x39, 0xb2, 0x75, 0x1b, 0x13, 0xf1, 0x21, 0x94, 0xcc, 0x63, 0x8c, 0x6c, 0x32, 0xc4,
0x96, 0xc4, 0xa9, 0x5c, 0xa3, 0xd4, 0xa9, 0x2d, 0x7c, 0xa5, 0x7a, 0x3a, 0x9a, 0x1d, 0x6f, 0x6b,
0xb1, 0x4b, 0x33, 0x8a, 0x4c, 0xd6, 0x2d, 0xf1, 0x0b, 0xa8, 0x24, 0x27, 0x0a, 0xd2, 0x78, 0x9a,
0x26, 0x2d, 0x7c, 0xa5, 0x16, 0xa6, 0xa5, 0xdd, 0x9a, 0x51, 0x4e, 0x74, 0xdd, 0x12, 0x77, 0xa0,
0x6c, 0x3a, 0x27, 0x36, 0x41, 0xee, 0x7c, 0xe4, 0x92, 0x53, 0x29, 0xab, 0x72, 0x8d, 0xb5, 0x47,
0x0f, 0x9a, 0x57, 0x3b, 0x6d, 0x76, 0x53, 0x31, 0x1d, 0xe1, 0x95, 0xaf, 0x64, 0x8c, 0x2b, 0x79,
0xa2, 0x0e, 0x79, 0x0f, 0x4f, 0x6c, 0xe4, 0x4a, 0x82, 0xca, 0x35, 0xca, 0x9d, 0x87, 0x7f, 0xfa,
0xca, 0xd6, 0x04, 0x93, 0xa3, 0x93, 0xc3, 0xa6, 0xe9, 0xcc, 0x5a, 0xa6, 0xe3, 0xcd, 0x1c, 0x2f,
0xfc, 0xd9, 0xf2, 0xac, 0x69, 0x8b, 0x9c, 0xce, 0x91, 0xd7, 0x6c, 0x9b, 0x66, 0xdb, 0xb2, 0x5c,
0xe4, 0x79, 0x46, 0x58, 0x40, 0x7b, 0x23, 0x40, 0xed, 0xda, 0x78, 0x06, 0xee, 0xe9, 0x3b, 0x3c,
0x9d, 0x7d, 0xd8, 0x4c, 0xeb, 0xc3, 0xef, 0x90, 0xeb, 0x61, 0xc7, 0xf6, 0x24, 0x41, 0xcd, 0x36,
0x4a, 0x1d, 0x75, 0xe1, 0x2b, 0x0f, 0xa2, 0xe3, 0xdc, 0x10, 0xa6, 0x19, 0xb5, 0xb4, 0xfd, 0x9b,
0xd0, 0x2c, 0x7e, 0x0e, 0x30, 0x77, 0x1d, 0x67, 0x3c, 0xc4, 0x36, 0x26, 0x52, 0x8e, 0x0e, 0x7e,
0x73, 0xe1, 0x2b, 0xf7, 0x58, 0xad, 0xc4, 0xa7, 0x19, 0x25, 0xaa, 0x50, 0x92, 0x7d, 0x04, 0x65,
0xe6, 0x39, 0x42, 0x78, 0x72, 0x44, 0xa4, 0xbc, 0xca, 0x35, 0x04, 0x63, 0x8d, 0xda, 0xbe, 0xa4,
0x26, 0xb1, 0x0b, 0x1b, 0x2c, 0xc4, 0x74, 0x6c, 0x0f, 0xd9, 0xde, 0x89, 0x27, 0x15, 0x68, 0xf5,
0xfa, 0xc2, 0x57, 0xde, 0x4f, 0x57, 0x8f, 0x03, 0x34, 0x63, 0x9d, 0x5a, 0xba, 0x91, 0x41, 0xdc,
0x81, 0x6a, 0xec, 0x8d, 0xbe, 0x55, 0x0c, 0xbe, 0xd5, 0xf9, 0x60, 0xe1, 0x2b, 0xf7, 0xe3, 0xf1,
0x5f, 0x89, 0xd0, 0x8c, 0x8d, 0xd8, 0x14, 0x1e, 0x26, 0xa1, 0x56, 0x69, 0x55, 0x6a, 0xfd, 0x9a,
0xbd, 0x81, 0x5a, 0x6d, 0x73, 0x7a, 0x9d, 0x27, 0xdc, 0xad, 0x78, 0x22, 0x41, 0x21, 0xc4, 0x8a,
0x11, 0xcc, 0x88, 0xd4, 0x80, 0xb3, 0x6c, 0x50, 0xc4, 0x65, 0xf4, 0x29, 0xa7, 0x39, 0x1b, 0xbb,
0x34, 0xa3, 0x48, 0xe5, 0x80, 0xe6, 0xdb, 0x4b, 0xf8, 0x08, 0x74, 0x66, 0xf7, 0x17, 0xbe, 0xf2,
0x5e, 0x3a, 0x2b, 0x9a, 0xd7, 0x7f, 0x01, 0x97, 0x7b, 0x2b, 0xc0, 0xe5, 0x57, 0x02, 0xae, 0xb0,
0x2a, 0x70, 0x3f, 0xf0, 0x20, 0x5d, 0x03, 0xae, 0xeb, 0xd8, 0x63, 0xec, 0xce, 0x56, 0x05, 0x2f,
0x86, 0x68, 0x64, 0x4e, 0x29, 0x7c, 0x37, 0x40, 0x34, 0x32, 0xa7, 0x11, 0x44, 0x01, 0x5d, 0x96,
0x21, 0xca, 0xde, 0x02, 0xa2, 0xb7, 0xb8, 0x29, 0x7f, 0xe7, 0xa0, 0x92, 0x8c, 0xa4, 0x67, 0x5b,
0x77, 0x59, 0x91, 0x75, 0x28, 0xc6, 0xeb, 0x88, 0x0f, 0xd6, 0x91, 0x11, 0xeb, 0xe2, 0xa7, 0x90,
0xf3, 0xc8, 0x88, 0x20, 0xda, 0xe0, 0xfa, 0xa3, 0xcd, 0xe5, 0xc5, 0xb7, 0x17, 0x38, 0x0d, 0x16,
0x73, 0x6d, 0x59, 0x0a, 0x77, 0x5b, 0x96, 0xdb, 0xc2, 0xcb, 0x9f, 0x95, 0x8c, 0xf6, 0x17, 0x07,
0x35, 0xdd, 0x42, 0x36, 0xc1, 0x63, 0x8c, 0xac, 0xa4, 0x4b, 0xf1, 0x43, 0xe0, 0xe3, 0xde, 0x2a,
0x0b, 0x5f, 0x29, 0xb1, 0xde, 0x82, 0xa6, 0x78, 0xbc, 0x34, 0x01, 0xfe, 0xd6, 0x13, 0xc8, 0xfe,
0xd3, 0x04, 0x84, 0x3b, 0x4c, 0x20, 0xb7, 0xd2, 0x04, 0x7e, 0xe3, 0xa0, 0x9c, 0x0e, 0xfd, 0x1f,
0xee, 0xbf, 0x6d, 0xc8, 0xcf, 0x5d, 0x34, 0xc6, 0x2f, 0x96, 0x6e, 0xbe, 0xf8, 0x41, 0xf3, 0x0c,
0xb9, 0xd3, 0x63, 0xd4, 0xa7, 0x31, 0x61, 0x2b, 0x61, 0x46, 0xd8, 0xc4, 0xc7, 0xb0, 0xd6, 0xa5,
0x87, 0xe9, 0x8f, 0xc8, 0x91, 0x27, 0xd6, 0x20, 0x37, 0x0f, 0x04, 0x89, 0xa3, 0x73, 0x66, 0x8a,
0x76, 0x00, 0x1b, 0x09, 0xc0, 0x2c, 0xf0, 0x0e, 0xbd, 0xc6, 0xb5, 0xf9, 0x74, 0xed, 0xaf, 0xa0,
0x10, 0xde, 0x97, 0xa2, 0x0c, 0x80, 0x23, 0x46, 0xb9, 0xac, 0xa8, 0x91, 0xb2, 0x04, 0x3c, 0x18,
0xa3, 0x11, 0x39, 0x71, 0x51, 0xfc, 0x4f, 0x88, 0x74, 0xd6, 0xcd, 0x27, 0x3f, 0x72, 0x90, 0xa3,
0x88, 0x8b, 0x4f, 0x40, 0xd9, 0x1b, 0xb4, 0x07, 0xbd, 0xe1, 0xfe, 0xae, 0xbe, 0xab, 0x0f, 0xf4,
0xf6, 0xd7, 0xfa, 0x41, 0xef, 0xe9, 0x70, 0x7f, 0x77, 0xaf, 0xdf, 0xeb, 0xea, 0x3b, 0x7a, 0xef,
0x69, 0x35, 0x53, 0xbf, 0x77, 0x76, 0xae, 0x56, 0xae, 0x04, 0x88, 0x12, 0x00, 0xcb, 0x0b, 0x8c,
0x55, 0xae, 0x5e, 0x3c, 0x3b, 0x57, 0x85, 0x40, 0x16, 0x65, 0xa8, 0x30, 0xcf, 0xc0, 0xf8, 0xf6,
0x79, 0xbf, 0xb7, 0x5b, 0xe5, 0xeb, 0x6b, 0x67, 0xe7, 0x6a, 0x21, 0x54, 0x93, 0x4c, 0xea, 0xcc,
0xb2, 0xcc, 0x40, 0xae, 0x0b, 0x2f, 0x7f, 0x91, 0x33, 0x9d, 0xfe, 0xab, 0x0b, 0x99, 0x7b, 0x7d,
0x21, 0x73, 0x7f, 0x5c, 0xc8, 0xdc, 0xf7, 0x97, 0x72, 0xe6, 0xf5, 0xa5, 0x9c, 0x79, 0x73, 0x29,
0x67, 0x0e, 0x9e, 0xfc, 0xeb, 0x76, 0x79, 0xd1, 0x0a, 0xde, 0xab, 0x9f, 0x3d, 0xde, 0x4a, 0xbd,
0x7c, 0xe9, 0xc6, 0x39, 0xcc, 0xd3, 0xe7, 0xea, 0xe3, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xe7,
0x61, 0x72, 0x2b, 0x18, 0x0b, 0x00, 0x00,
// 989 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x57, 0x4f, 0x6f, 0xe2, 0x46,
0x14, 0xc7, 0xc4, 0xfc, 0x7b, 0x40, 0xc2, 0xba, 0xa4, 0xeb, 0xd2, 0x2d, 0x46, 0xee, 0x05, 0xb5,
0x0a, 0x34, 0xbb, 0xd5, 0x1e, 0x22, 0xf5, 0x00, 0x2c, 0x51, 0xad, 0x76, 0xb3, 0xc8, 0x21, 0x95,
0x9a, 0x0b, 0x02, 0x33, 0x90, 0x11, 0x61, 0x8c, 0xec, 0xa1, 0x5a, 0xbe, 0xc1, 0x2a, 0xa7, 0x4a,
0x3d, 0x55, 0x6a, 0xa4, 0x4a, 0xfd, 0x26, 0x55, 0x0f, 0x7b, 0xdc, 0x63, 0x7b, 0xb1, 0xaa, 0xe4,
0x1b, 0x70, 0xec, 0x65, 0x2b, 0xcf, 0xd8, 0xc6, 0x40, 0x5a, 0x29, 0x21, 0xab, 0x3d, 0xf1, 0x7e,
0xf3, 0xde, 0x9b, 0xf1, 0xfb, 0xcd, 0xef, 0xcd, 0x0c, 0xa0, 0xe0, 0x9e, 0x51, 0x35, 0x4c, 0x42,
0x90, 0x41, 0xb1, 0x49, 0x42, 0x66, 0x65, 0x62, 0x99, 0xd4, 0x94, 0xb6, 0x71, 0xcf, 0xa8, 0x2c,
0x46, 0x0b, 0xf9, 0xa1, 0x39, 0x34, 0x99, 0xab, 0xea, 0x5a, 0x3c, 0xaa, 0xf0, 0xd1, 0xd0, 0x34,
0x87, 0xe7, 0xa8, 0xca, 0x50, 0x6f, 0x3a, 0xa8, 0x76, 0xc9, 0xcc, 0x73, 0x79, 0x2b, 0x8c, 0xc7,
0x98, 0x8e, 0x11, 0xa1, 0x21, 0x93, 0x07, 0xa8, 0xbf, 0x44, 0x61, 0xf7, 0xb9, 0x3d, 0x6c, 0x04,
0x6b, 0xbc, 0x98, 0x20, 0xa2, 0x11, 0x4c, 0xa5, 0x7d, 0x48, 0x19, 0xe7, 0x18, 0x11, 0xda, 0xc1,
0x7d, 0x59, 0x28, 0x09, 0xe5, 0x54, 0x3d, 0x3f, 0x77, 0x94, 0xdc, 0xac, 0x3b, 0x3e, 0x3f, 0x50,
0x03, 0x97, 0xaa, 0x27, 0xb9, 0xad, 0xf5, 0xa5, 0xaf, 0x20, 0xbb, 0xf8, 0x58, 0x37, 0x2d, 0xca,
0xd2, 0xe4, 0xb9, 0xa3, 0xe4, 0xbd, 0xb4, 0xb0, 0x5b, 0xd5, 0x33, 0x0b, 0xac, 0xf5, 0xa5, 0x43,
0xc8, 0x18, 0xe6, 0x94, 0x50, 0x64, 0x4d, 0xba, 0x16, 0x9d, 0xc9, 0x5b, 0x25, 0xa1, 0x9c, 0x7e,
0xfc, 0xa8, 0xb2, 0x4c, 0x42, 0xa5, 0x11, 0x8a, 0xa9, 0x8b, 0xaf, 0x1d, 0x25, 0xa2, 0x2f, 0xe5,
0x49, 0x1a, 0xc4, 0x6d, 0x3c, 0x24, 0xc8, 0x92, 0xc5, 0x92, 0x50, 0xce, 0xd4, 0xf7, 0xff, 0x71,
0x94, 0xbd, 0x21, 0xa6, 0x67, 0xd3, 0x5e, 0xc5, 0x30, 0xc7, 0x55, 0xc3, 0xb4, 0xc7, 0xa6, 0xed,
0xfd, 0xec, 0xd9, 0xfd, 0x51, 0x95, 0xce, 0x26, 0xc8, 0xae, 0xd4, 0x0c, 0xa3, 0xd6, 0xef, 0x5b,
0xc8, 0xb6, 0x75, 0x6f, 0x02, 0xf5, 0x6d, 0x0c, 0xf2, 0x6b, 0xf4, 0xb4, 0xad, 0xd9, 0x7b, 0x60,
0xa7, 0x05, 0x19, 0x6f, 0x5a, 0x9b, 0x76, 0x29, 0xf2, 0xd8, 0xc9, 0x57, 0xf8, 0xe6, 0x57, 0xfc,
0xcd, 0xaf, 0xd4, 0xc8, 0xac, 0xfe, 0x70, 0xee, 0x28, 0x1f, 0x2c, 0x7d, 0x0a, 0xcb, 0x51, 0xf5,
0x34, 0x87, 0xc7, 0x2e, 0x5a, 0xe3, 0x5b, 0xbc, 0x23, 0xdf, 0x27, 0xb0, 0x1b, 0xc6, 0x9d, 0x1f,
0x90, 0x65, 0x63, 0x93, 0xd8, 0x72, 0xac, 0xb4, 0x55, 0x4e, 0xd5, 0x4b, 0x73, 0x47, 0x79, 0xe4,
0x17, 0x78, 0x43, 0x98, 0xaa, 0xe7, 0xc3, 0xe3, 0xdf, 0x79, 0xc3, 0xd2, 0x01, 0x64, 0x26, 0x96,
0x69, 0x0e, 0x3a, 0x67, 0x08, 0x0f, 0xcf, 0xa8, 0x1c, 0x2f, 0x09, 0x65, 0x31, 0x5c, 0x5a, 0xd8,
0xab, 0xea, 0x69, 0x06, 0xbf, 0x66, 0x48, 0xfa, 0x12, 0x80, 0x7b, 0x31, 0xc1, 0x54, 0x4e, 0x30,
0x19, 0xec, 0xce, 0x1d, 0xe5, 0x41, 0x38, 0xd3, 0xf5, 0xa9, 0x7a, 0x8a, 0x01, 0x26, 0xf9, 0x60,
0x45, 0xce, 0x92, 0x9c, 0x64, 0x79, 0x6b, 0x2b, 0x72, 0xaf, 0xbf, 0x62, 0x83, 0x21, 0xa9, 0x01,
0x3b, 0x9e, 0xd7, 0x24, 0x36, 0x22, 0xf6, 0xd4, 0x96, 0x53, 0x2c, 0xbd, 0x30, 0x77, 0x94, 0x0f,
0x97, 0xd2, 0xfd, 0x00, 0x55, 0xdf, 0xe6, 0x33, 0xf8, 0x03, 0xd2, 0x21, 0xe4, 0x02, 0xaf, 0x5f,
0x36, 0xb0, 0xb2, 0x3f, 0x9e, 0x3b, 0xca, 0xc3, 0x40, 0x25, 0x4b, 0x11, 0xaa, 0xbe, 0x13, 0x0c,
0x79, 0xe5, 0x2f, 0x3a, 0x20, 0xbd, 0x69, 0x07, 0xfc, 0x21, 0xde, 0xd0, 0x01, 0x35, 0x63, 0xb4,
0x2e, 0x67, 0xe1, 0x56, 0x72, 0x96, 0x21, 0xe1, 0x09, 0x80, 0xf7, 0x81, 0xee, 0xc3, 0x77, 0x20,
0xf4, 0x55, 0x25, 0x89, 0xb7, 0x50, 0xd2, 0x3e, 0x70, 0x81, 0x74, 0xa8, 0x35, 0x93, 0x63, 0x8c,
0xcd, 0x50, 0xa3, 0x07, 0x2e, 0x55, 0x4f, 0x32, 0xdb, 0x3d, 0x1b, 0x56, 0x65, 0x14, 0xdf, 0x4c,
0x46, 0x89, 0x7b, 0x91, 0x51, 0x72, 0x23, 0x19, 0xa5, 0x36, 0x95, 0xd1, 0x4f, 0x51, 0x90, 0xd7,
0x64, 0xd4, 0x30, 0xc9, 0x00, 0x5b, 0xe3, 0x4d, 0xa5, 0x14, 0x6c, 0x51, 0xd7, 0x18, 0x31, 0x31,
0xdd, 0xb0, 0x45, 0x5d, 0x63, 0xe4, 0x6f, 0x91, 0x2b, 0xde, 0x55, 0x45, 0x6c, 0xdd, 0x42, 0x11,
0xf7, 0x78, 0xbd, 0xfc, 0x25, 0x40, 0x76, 0x41, 0x49, 0x93, 0xf4, 0xef, 0x72, 0xaf, 0x14, 0x20,
0x19, 0x9c, 0xb8, 0x51, 0xf7, 0xc4, 0xd5, 0x03, 0x2c, 0x7d, 0x0e, 0xb1, 0x45, 0x13, 0x6d, 0x3f,
0xde, 0x5d, 0x3d, 0xdb, 0x59, 0x7f, 0xe8, 0x3c, 0xe6, 0xbe, 0xee, 0x83, 0x03, 0xf1, 0xd5, 0xaf,
0x4a, 0x44, 0x7d, 0x2b, 0x40, 0x5e, 0xeb, 0x23, 0x42, 0xf1, 0x00, 0xa3, 0xfe, 0xa2, 0x4a, 0xe9,
0x13, 0x88, 0x06, 0xb5, 0x65, 0xe7, 0x8e, 0x92, 0xe2, 0xb5, 0xb9, 0x45, 0x45, 0xf1, 0x0a, 0x03,
0xd1, 0x5b, 0x33, 0xb0, 0xf5, 0x5f, 0x0c, 0x88, 0x77, 0x60, 0x20, 0xb6, 0x11, 0x03, 0xbf, 0x0b,
0x90, 0x09, 0x87, 0xbe, 0x87, 0x47, 0xc3, 0x01, 0xc4, 0x27, 0x16, 0x1a, 0xe0, 0x97, 0x2b, 0x8f,
0xa9, 0xe0, 0x15, 0xf8, 0x1c, 0x59, 0xa3, 0x73, 0xd4, 0x62, 0x31, 0x5e, 0x29, 0x5e, 0x86, 0x57,
0xc4, 0xa7, 0x90, 0xe6, 0x47, 0x53, 0xab, 0x4b, 0xcf, 0x6c, 0x29, 0x0f, 0xb1, 0x89, 0x6b, 0xc8,
0x02, 0xe3, 0x99, 0x03, 0xf5, 0x14, 0x76, 0x16, 0x1b, 0xcc, 0x03, 0xef, 0x50, 0x6b, 0x30, 0x77,
0x34, 0x3c, 0xf7, 0x37, 0x90, 0xf0, 0x9e, 0x04, 0x52, 0x11, 0x00, 0xfb, 0x8a, 0xb2, 0xf8, 0xa4,
0x7a, 0x68, 0xc4, 0xd5, 0xc1, 0x00, 0x75, 0xe9, 0xd4, 0x42, 0x41, 0x27, 0xf8, 0x98, 0x57, 0xf3,
0xd9, 0xcf, 0x02, 0xc4, 0xf8, 0x9d, 0xf0, 0x14, 0x94, 0xe3, 0x76, 0xad, 0xdd, 0xec, 0x9c, 0x1c,
0x69, 0x47, 0x5a, 0x5b, 0xab, 0x7d, 0xab, 0x9d, 0x36, 0x9f, 0x75, 0x4e, 0x8e, 0x8e, 0x5b, 0xcd,
0x86, 0x76, 0xa8, 0x35, 0x9f, 0xe5, 0x22, 0x85, 0x07, 0x17, 0x97, 0xa5, 0xec, 0x52, 0x80, 0x24,
0x03, 0xf0, 0x3c, 0x77, 0x30, 0x27, 0x14, 0x92, 0x17, 0x97, 0x25, 0xd1, 0xb5, 0xa5, 0x22, 0x64,
0xb9, 0xa7, 0xad, 0x7f, 0xff, 0xa2, 0xd5, 0x3c, 0xca, 0x45, 0x0b, 0xe9, 0x8b, 0xcb, 0x52, 0xc2,
0x83, 0x8b, 0x4c, 0xe6, 0xdc, 0xe2, 0x99, 0xae, 0x5d, 0x10, 0x5f, 0xfd, 0x56, 0x8c, 0xd4, 0x5b,
0xaf, 0xaf, 0x8a, 0xc2, 0x9b, 0xab, 0xa2, 0xf0, 0xf7, 0x55, 0x51, 0xf8, 0xf1, 0xba, 0x18, 0x79,
0x73, 0x5d, 0x8c, 0xfc, 0x79, 0x5d, 0x8c, 0x9c, 0x3e, 0xfd, 0xdf, 0xd3, 0xe5, 0x65, 0xd5, 0x7d,
0xe4, 0x7f, 0xf1, 0x64, 0x2f, 0xf4, 0x4f, 0x82, 0x9d, 0x38, 0xbd, 0x38, 0xbb, 0x2b, 0x9f, 0xfc,
0x1b, 0x00, 0x00, 0xff, 0xff, 0xff, 0x74, 0xb1, 0x7f, 0x68, 0x0c, 0x00, 0x00,
}
func (m *MsgConnectionOpenInit) Marshal() (dAtA []byte, err error) {
@ -856,18 +895,32 @@ func (m *MsgConnectionOpenTry) MarshalToSizedBuffer(dAtA []byte) (int, error) {
copy(dAtA[i:], m.Signer)
i = encodeVarintConnection(dAtA, i, uint64(len(m.Signer)))
i--
dAtA[i] = 0x4a
dAtA[i] = 0x5a
}
if m.ConsensusHeight != 0 {
i = encodeVarintConnection(dAtA, i, uint64(m.ConsensusHeight))
i--
dAtA[i] = 0x40
dAtA[i] = 0x50
}
if len(m.ProofConsensus) > 0 {
i -= len(m.ProofConsensus)
copy(dAtA[i:], m.ProofConsensus)
i = encodeVarintConnection(dAtA, i, uint64(len(m.ProofConsensus)))
i--
dAtA[i] = 0x4a
}
if len(m.ProofClient) > 0 {
i -= len(m.ProofClient)
copy(dAtA[i:], m.ProofClient)
i = encodeVarintConnection(dAtA, i, uint64(len(m.ProofClient)))
i--
dAtA[i] = 0x42
}
if len(m.ProofInit) > 0 {
i -= len(m.ProofInit)
copy(dAtA[i:], m.ProofInit)
i = encodeVarintConnection(dAtA, i, uint64(len(m.ProofInit)))
i--
dAtA[i] = 0x3a
}
if m.ProofHeight != 0 {
@ -875,20 +928,13 @@ func (m *MsgConnectionOpenTry) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i--
dAtA[i] = 0x30
}
if len(m.ProofInit) > 0 {
i -= len(m.ProofInit)
copy(dAtA[i:], m.ProofInit)
i = encodeVarintConnection(dAtA, i, uint64(len(m.ProofInit)))
i--
dAtA[i] = 0x2a
}
if len(m.CounterpartyVersions) > 0 {
for iNdEx := len(m.CounterpartyVersions) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.CounterpartyVersions[iNdEx])
copy(dAtA[i:], m.CounterpartyVersions[iNdEx])
i = encodeVarintConnection(dAtA, i, uint64(len(m.CounterpartyVersions[iNdEx])))
i--
dAtA[i] = 0x22
dAtA[i] = 0x2a
}
}
{
@ -900,7 +946,19 @@ func (m *MsgConnectionOpenTry) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i = encodeVarintConnection(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x1a
dAtA[i] = 0x22
if m.ClientState != nil {
{
size, err := m.ClientState.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintConnection(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x1a
}
if len(m.ConnectionId) > 0 {
i -= len(m.ConnectionId)
copy(dAtA[i:], m.ConnectionId)
@ -943,18 +1001,32 @@ func (m *MsgConnectionOpenAck) MarshalToSizedBuffer(dAtA []byte) (int, error) {
copy(dAtA[i:], m.Signer)
i = encodeVarintConnection(dAtA, i, uint64(len(m.Signer)))
i--
dAtA[i] = 0x3a
dAtA[i] = 0x4a
}
if m.ConsensusHeight != 0 {
i = encodeVarintConnection(dAtA, i, uint64(m.ConsensusHeight))
i--
dAtA[i] = 0x30
dAtA[i] = 0x40
}
if len(m.ProofConsensus) > 0 {
i -= len(m.ProofConsensus)
copy(dAtA[i:], m.ProofConsensus)
i = encodeVarintConnection(dAtA, i, uint64(len(m.ProofConsensus)))
i--
dAtA[i] = 0x3a
}
if len(m.ProofClient) > 0 {
i -= len(m.ProofClient)
copy(dAtA[i:], m.ProofClient)
i = encodeVarintConnection(dAtA, i, uint64(len(m.ProofClient)))
i--
dAtA[i] = 0x32
}
if len(m.ProofTry) > 0 {
i -= len(m.ProofTry)
copy(dAtA[i:], m.ProofTry)
i = encodeVarintConnection(dAtA, i, uint64(len(m.ProofTry)))
i--
dAtA[i] = 0x2a
}
if m.ProofHeight != 0 {
@ -962,10 +1034,15 @@ func (m *MsgConnectionOpenAck) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i--
dAtA[i] = 0x20
}
if len(m.ProofTry) > 0 {
i -= len(m.ProofTry)
copy(dAtA[i:], m.ProofTry)
i = encodeVarintConnection(dAtA, i, uint64(len(m.ProofTry)))
if m.ClientState != nil {
{
size, err := m.ClientState.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintConnection(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x1a
}
@ -1355,6 +1432,10 @@ func (m *MsgConnectionOpenTry) Size() (n int) {
if l > 0 {
n += 1 + l + sovConnection(uint64(l))
}
if m.ClientState != nil {
l = m.ClientState.Size()
n += 1 + l + sovConnection(uint64(l))
}
l = m.Counterparty.Size()
n += 1 + l + sovConnection(uint64(l))
if len(m.CounterpartyVersions) > 0 {
@ -1363,12 +1444,16 @@ func (m *MsgConnectionOpenTry) Size() (n int) {
n += 1 + l + sovConnection(uint64(l))
}
}
if m.ProofHeight != 0 {
n += 1 + sovConnection(uint64(m.ProofHeight))
}
l = len(m.ProofInit)
if l > 0 {
n += 1 + l + sovConnection(uint64(l))
}
if m.ProofHeight != 0 {
n += 1 + sovConnection(uint64(m.ProofHeight))
l = len(m.ProofClient)
if l > 0 {
n += 1 + l + sovConnection(uint64(l))
}
l = len(m.ProofConsensus)
if l > 0 {
@ -1398,13 +1483,21 @@ func (m *MsgConnectionOpenAck) Size() (n int) {
if l > 0 {
n += 1 + l + sovConnection(uint64(l))
}
l = len(m.ProofTry)
if l > 0 {
if m.ClientState != nil {
l = m.ClientState.Size()
n += 1 + l + sovConnection(uint64(l))
}
if m.ProofHeight != 0 {
n += 1 + sovConnection(uint64(m.ProofHeight))
}
l = len(m.ProofTry)
if l > 0 {
n += 1 + l + sovConnection(uint64(l))
}
l = len(m.ProofClient)
if l > 0 {
n += 1 + l + sovConnection(uint64(l))
}
l = len(m.ProofConsensus)
if l > 0 {
n += 1 + l + sovConnection(uint64(l))
@ -1851,6 +1944,42 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error {
m.ConnectionId = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ClientState", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowConnection
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthConnection
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthConnection
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.ClientState == nil {
m.ClientState = &types.Any{}
}
if err := m.ClientState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Counterparty", wireType)
}
@ -1883,7 +2012,7 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error {
return err
}
iNdEx = postIndex
case 4:
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field CounterpartyVersions", wireType)
}
@ -1915,7 +2044,26 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error {
}
m.CounterpartyVersions = append(m.CounterpartyVersions, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex
case 5:
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", wireType)
}
m.ProofHeight = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowConnection
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.ProofHeight |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 7:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ProofInit", wireType)
}
@ -1949,11 +2097,11 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error {
m.ProofInit = []byte{}
}
iNdEx = postIndex
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", wireType)
case 8:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ProofClient", wireType)
}
m.ProofHeight = 0
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowConnection
@ -1963,12 +2111,27 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
m.ProofHeight |= uint64(b&0x7F) << shift
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 7:
if byteLen < 0 {
return ErrInvalidLengthConnection
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthConnection
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ProofClient = append(m.ProofClient[:0], dAtA[iNdEx:postIndex]...)
if m.ProofClient == nil {
m.ProofClient = []byte{}
}
iNdEx = postIndex
case 9:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ProofConsensus", wireType)
}
@ -2002,7 +2165,7 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error {
m.ProofConsensus = []byte{}
}
iNdEx = postIndex
case 8:
case 10:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ConsensusHeight", wireType)
}
@ -2021,7 +2184,7 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error {
break
}
}
case 9:
case 11:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType)
}
@ -2173,6 +2336,61 @@ func (m *MsgConnectionOpenAck) Unmarshal(dAtA []byte) error {
m.Version = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ClientState", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowConnection
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthConnection
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthConnection
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.ClientState == nil {
m.ClientState = &types.Any{}
}
if err := m.ClientState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", wireType)
}
m.ProofHeight = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowConnection
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.ProofHeight |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ProofTry", wireType)
}
@ -2206,11 +2424,11 @@ func (m *MsgConnectionOpenAck) Unmarshal(dAtA []byte) error {
m.ProofTry = []byte{}
}
iNdEx = postIndex
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", wireType)
case 6:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ProofClient", wireType)
}
m.ProofHeight = 0
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowConnection
@ -2220,12 +2438,27 @@ func (m *MsgConnectionOpenAck) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
m.ProofHeight |= uint64(b&0x7F) << shift
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 5:
if byteLen < 0 {
return ErrInvalidLengthConnection
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthConnection
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ProofClient = append(m.ProofClient[:0], dAtA[iNdEx:postIndex]...)
if m.ProofClient == nil {
m.ProofClient = []byte{}
}
iNdEx = postIndex
case 7:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ProofConsensus", wireType)
}
@ -2259,7 +2492,7 @@ func (m *MsgConnectionOpenAck) Unmarshal(dAtA []byte) error {
m.ProofConsensus = []byte{}
}
iNdEx = postIndex
case 6:
case 8:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ConsensusHeight", wireType)
}
@ -2278,7 +2511,7 @@ func (m *MsgConnectionOpenAck) Unmarshal(dAtA []byte) error {
break
}
}
case 7:
case 9:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType)
}

View File

@ -11,10 +11,12 @@ import (
)
var (
chainID = "gaiamainnet"
connectionID = "connectionidone"
clientID = "clientidone"
connectionID2 = "connectionidtwo"
clientID2 = "clientidtwo"
clientHeight = uint64(6)
)
func TestConnectionValidateBasic(t *testing.T) {

View File

@ -10,6 +10,7 @@ type ClientKeeper interface {
GetClientState(ctx sdk.Context, clientID string) (clientexported.ClientState, bool)
GetClientConsensusState(ctx sdk.Context, clientID string, height uint64) (clientexported.ConsensusState, bool)
GetSelfConsensusState(ctx sdk.Context, height uint64) (clientexported.ConsensusState, bool)
ValidateSelfClient(ctx sdk.Context, clientState clientexported.ClientState) error
IterateClients(ctx sdk.Context, cb func(string, clientexported.ClientState) bool)
ClientStore(ctx sdk.Context, clientID string) sdk.KVStore
}

View File

@ -3,6 +3,8 @@ package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
)
@ -63,17 +65,21 @@ var _ sdk.Msg = &MsgConnectionOpenTry{}
// NewMsgConnectionOpenTry creates a new MsgConnectionOpenTry instance
func NewMsgConnectionOpenTry(
connectionID, clientID, counterpartyConnectionID,
counterpartyClientID string, counterpartyPrefix commitmenttypes.MerklePrefix,
counterpartyVersions []string, proofInit, proofConsensus []byte,
counterpartyClientID string, counterpartyClient clientexported.ClientState,
counterpartyPrefix commitmenttypes.MerklePrefix, counterpartyVersions []string,
proofInit, proofClient, proofConsensus []byte,
proofHeight, consensusHeight uint64, signer sdk.AccAddress,
) *MsgConnectionOpenTry {
counterparty := NewCounterparty(counterpartyClientID, counterpartyConnectionID, counterpartyPrefix)
csAny, _ := clienttypes.PackClientState(counterpartyClient)
return &MsgConnectionOpenTry{
ConnectionId: connectionID,
ClientId: clientID,
ClientState: csAny,
Counterparty: counterparty,
CounterpartyVersions: counterpartyVersions,
ProofInit: proofInit,
ProofClient: proofClient,
ProofConsensus: proofConsensus,
ProofHeight: proofHeight,
ConsensusHeight: consensusHeight,
@ -99,6 +105,16 @@ func (msg MsgConnectionOpenTry) ValidateBasic() error {
if err := host.ClientIdentifierValidator(msg.ClientId); err != nil {
return sdkerrors.Wrap(err, "invalid client ID")
}
if msg.ClientState == nil {
return sdkerrors.Wrap(clienttypes.ErrInvalidClient, "counterparty client is nil")
}
clientState, err := clienttypes.UnpackClientState(msg.ClientState)
if err != nil {
return sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "unpack err: %v", err)
}
if err := clientState.Validate(); err != nil {
return sdkerrors.Wrap(err, "counterparty client is invalid")
}
if len(msg.CounterpartyVersions) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidVersion, "empty counterparty versions")
}
@ -110,6 +126,9 @@ func (msg MsgConnectionOpenTry) ValidateBasic() error {
if len(msg.ProofInit) == 0 {
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof init")
}
if len(msg.ProofClient) == 0 {
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit empty proof client")
}
if len(msg.ProofConsensus) == 0 {
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof of consensus state")
}
@ -139,13 +158,17 @@ var _ sdk.Msg = &MsgConnectionOpenAck{}
// NewMsgConnectionOpenAck creates a new MsgConnectionOpenAck instance
func NewMsgConnectionOpenAck(
connectionID string, proofTry, proofConsensus []byte,
connectionID string, counterpartyClient clientexported.ClientState,
proofTry, proofClient, proofConsensus []byte,
proofHeight, consensusHeight uint64, version string,
signer sdk.AccAddress,
) *MsgConnectionOpenAck {
csAny, _ := clienttypes.PackClientState(counterpartyClient)
return &MsgConnectionOpenAck{
ConnectionId: connectionID,
ClientState: csAny,
ProofTry: proofTry,
ProofClient: proofClient,
ProofConsensus: proofConsensus,
ProofHeight: proofHeight,
ConsensusHeight: consensusHeight,
@ -172,9 +195,22 @@ func (msg MsgConnectionOpenAck) ValidateBasic() error {
if err := ValidateVersion(msg.Version); err != nil {
return err
}
if msg.ClientState == nil {
return sdkerrors.Wrap(clienttypes.ErrInvalidClient, "counterparty client is nil")
}
clientState, err := clienttypes.UnpackClientState(msg.ClientState)
if err != nil {
return sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "unpack err: %v", err)
}
if err := clientState.Validate(); err != nil {
return sdkerrors.Wrap(err, "counterparty client is invalid")
}
if len(msg.ProofTry) == 0 {
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof try")
}
if len(msg.ProofClient) == 0 {
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit empty proof client")
}
if len(msg.ProofConsensus) == 0 {
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof of consensus state")
}

View File

@ -3,6 +3,7 @@ package types_test
import (
"fmt"
"testing"
"time"
"github.com/stretchr/testify/suite"
@ -14,7 +15,9 @@ import (
"github.com/cosmos/cosmos-sdk/store/rootmulti"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
)
@ -103,20 +106,40 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() {
prefix := commitmenttypes.NewMerklePrefix([]byte("storePrefixKey"))
signer, _ := sdk.AccAddressFromBech32("cosmos1ckgw5d7jfj7wwxjzs9fdrdev9vc8dzcw3n2lht")
clientState := ibctmtypes.NewClientState(
chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(),
)
// Pack consensus state into any to test unpacking error
consState := ibctmtypes.NewConsensusState(
time.Now(), commitmenttypes.NewMerkleRoot([]byte("root")), clientHeight, []byte("nextValsHash"),
)
invalidAny := clienttypes.MustPackConsensusState(consState)
counterparty := types.NewCounterparty("connectiontotest", "clienttotest", prefix)
// invalidClientState fails validateBasic
invalidClient := ibctmtypes.NewClientState(
chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, 0, commitmenttypes.GetSDKSpecs(),
)
testMsgs := []*types.MsgConnectionOpenTry{
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{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),
types.NewMsgConnectionOpenTry("test/conn1", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, 10, 10, signer),
types.NewMsgConnectionOpenTry("ibcconntest", "test/iris", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, 10, 10, signer),
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "ibc/test", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, 10, 10, signer),
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "test/conn1", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, 10, 10, signer),
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", nil, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, 10, 10, signer),
&types.MsgConnectionOpenTry{"ibcconntest", "clienttotesta", invalidAny, counterparty, []string{ibctesting.ConnectionVersion}, 10, suite.proof, suite.proof, suite.proof, 10, signer},
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", invalidClient, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, 10, 10, signer),
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, emptyPrefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, 10, 10, signer),
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{}, suite.proof, suite.proof, suite.proof, 10, 10, signer),
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, emptyProof, suite.proof, suite.proof, 10, 10, signer),
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, emptyProof, suite.proof, 10, 10, signer),
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, emptyProof, 10, 10, signer),
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, 0, 10, signer),
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, 10, 0, signer),
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, 10, 10, nil),
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{ibctesting.ConnectionVersion}, suite.proof, suite.proof, suite.proof, 10, 10, signer),
types.NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []string{"(invalid version)"}, suite.proof, suite.proof, suite.proof, 10, 10, signer),
}
var testCases = []struct {
@ -128,15 +151,19 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() {
{testMsgs[1], false, "invalid client ID"},
{testMsgs[2], false, "invalid counterparty connection ID"},
{testMsgs[3], false, "invalid counterparty client ID"},
{testMsgs[4], false, "empty counterparty prefix"},
{testMsgs[5], false, "empty counterpartyVersions"},
{testMsgs[6], false, "empty proofInit"},
{testMsgs[7], false, "empty proofConsensus"},
{testMsgs[8], false, "invalid proofHeight"},
{testMsgs[9], false, "invalid consensusHeight"},
{testMsgs[10], false, "empty singer"},
{testMsgs[11], true, "success"},
{testMsgs[12], false, "invalid version"},
{testMsgs[4], false, "invalid nil counterparty client"},
{testMsgs[5], false, "invalid client unpacking"},
{testMsgs[6], false, "counterparty failed Validate"},
{testMsgs[7], false, "empty counterparty prefix"},
{testMsgs[8], false, "empty counterpartyVersions"},
{testMsgs[9], false, "empty proofInit"},
{testMsgs[10], false, "empty proofClient"},
{testMsgs[11], false, "empty proofConsensus"},
{testMsgs[12], false, "invalid proofHeight"},
{testMsgs[13], false, "invalid consensusHeight"},
{testMsgs[14], false, "empty singer"},
{testMsgs[15], true, "success"},
{testMsgs[16], false, "invalid version"},
}
for i, tc := range testCases {
@ -151,16 +178,34 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() {
func (suite *MsgTestSuite) TestNewMsgConnectionOpenAck() {
signer, _ := sdk.AccAddressFromBech32("cosmos1ckgw5d7jfj7wwxjzs9fdrdev9vc8dzcw3n2lht")
clientState := ibctmtypes.NewClientState(
chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(),
)
// Pack consensus state into any to test unpacking error
consState := ibctmtypes.NewConsensusState(
time.Now(), commitmenttypes.NewMerkleRoot([]byte("root")), clientHeight, []byte("nextValsHash"),
)
invalidAny := clienttypes.MustPackConsensusState(consState)
// invalidClientState fails validateBasic
invalidClient := ibctmtypes.NewClientState(
chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, 0, commitmenttypes.GetSDKSpecs(),
)
testMsgs := []*types.MsgConnectionOpenAck{
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, ibctesting.ConnectionVersion, nil),
types.NewMsgConnectionOpenAck("ibcconntest", suite.proof, suite.proof, 10, 10, ibctesting.ConnectionVersion, signer),
types.NewMsgConnectionOpenAck("test/conn1", clientState, suite.proof, suite.proof, suite.proof, 10, 10, ibctesting.ConnectionVersion, signer),
types.NewMsgConnectionOpenAck("ibcconntest", nil, suite.proof, suite.proof, suite.proof, 10, 10, ibctesting.ConnectionVersion, signer),
&types.MsgConnectionOpenAck{"ibcconntest", ibctesting.ConnectionVersion, invalidAny, 10, suite.proof, suite.proof, suite.proof, 10, signer},
types.NewMsgConnectionOpenAck("ibcconntest", invalidClient, suite.proof, suite.proof, suite.proof, 10, 10, ibctesting.ConnectionVersion, signer),
types.NewMsgConnectionOpenAck("ibcconntest", clientState, emptyProof, suite.proof, suite.proof, 10, 10, ibctesting.ConnectionVersion, signer),
types.NewMsgConnectionOpenAck("ibcconntest", clientState, suite.proof, emptyProof, suite.proof, 10, 10, ibctesting.ConnectionVersion, signer),
types.NewMsgConnectionOpenAck("ibcconntest", clientState, suite.proof, suite.proof, emptyProof, 10, 10, ibctesting.ConnectionVersion, signer),
types.NewMsgConnectionOpenAck("ibcconntest", clientState, suite.proof, suite.proof, suite.proof, 0, 10, ibctesting.ConnectionVersion, signer),
types.NewMsgConnectionOpenAck("ibcconntest", clientState, suite.proof, suite.proof, suite.proof, 10, 0, ibctesting.ConnectionVersion, signer),
types.NewMsgConnectionOpenAck("ibcconntest", clientState, suite.proof, suite.proof, suite.proof, 10, 10, "", signer),
types.NewMsgConnectionOpenAck("ibcconntest", clientState, suite.proof, suite.proof, suite.proof, 10, 10, ibctesting.ConnectionVersion, nil),
types.NewMsgConnectionOpenAck("ibcconntest", clientState, suite.proof, suite.proof, suite.proof, 10, 10, ibctesting.ConnectionVersion, signer),
}
var testCases = []struct {
msg *types.MsgConnectionOpenAck
@ -168,13 +213,17 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenAck() {
errMsg string
}{
{testMsgs[0], false, "invalid connection ID"},
{testMsgs[1], false, "empty proofTry"},
{testMsgs[2], false, "empty proofConsensus"},
{testMsgs[3], false, "invalid proofHeight"},
{testMsgs[4], false, "invalid consensusHeight"},
{testMsgs[5], false, "invalid version"},
{testMsgs[6], false, "empty signer"},
{testMsgs[7], true, "success"},
{testMsgs[1], false, "invalid nil counterparty client"},
{testMsgs[2], false, "invalid unpacking counterparty client"},
{testMsgs[3], false, "counterparty client failed Validate"},
{testMsgs[4], false, "empty proofTry"},
{testMsgs[5], false, "empty proofClient"},
{testMsgs[6], false, "empty proofConsensus"},
{testMsgs[7], false, "invalid proofHeight"},
{testMsgs[8], false, "invalid consensusHeight"},
{testMsgs[9], false, "invalid version"},
{testMsgs[10], false, "empty signer"},
{testMsgs[11], true, "success"},
}
for i, tc := range testCases {

View File

@ -304,7 +304,6 @@ func local_request_Query_ConnectionConsensusState_0(ctx context.Context, marshal
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Connection_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -878,7 +878,6 @@ func local_request_Query_NextSequenceReceive_0(ctx context.Context, marshaler ru
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Channel_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -112,6 +112,46 @@ func (cs ClientState) GetProofSpecs() []*ics23.ProofSpec {
return cs.ProofSpecs
}
// VerifyClientState verifies a proof of the client state of the running chain
// stored on the target machine
func (cs ClientState) VerifyClientState(
store sdk.KVStore,
cdc codec.BinaryMarshaler,
provingRoot commitmentexported.Root,
height uint64,
prefix commitmentexported.Prefix,
counterpartyClientIdentifier string,
proof []byte,
clientState clientexported.ClientState,
) error {
merkleProof, _, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
if err != nil {
return err
}
clientPrefixedPath := "clients/" + counterpartyClientIdentifier + "/" + host.ClientStatePath()
path, err := commitmenttypes.ApplyPrefix(prefix, clientPrefixedPath)
if err != nil {
return err
}
if clientState == nil {
return sdkerrors.Wrap(clienttypes.ErrInvalidClient, "client state cannot be empty")
}
_, ok := clientState.(*ClientState)
if !ok {
return sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "invalid client type %T, expected %T", clientState, &ClientState{})
}
bz, err := codec.MarshalAny(cdc, clientState)
if err != nil {
return err
}
return merkleProof.VerifyMembership(cs.ProofSpecs, provingRoot, path, bz)
}
// VerifyClientConsensusState verifies a proof of the consensus state of the
// Tendermint client stored on the target machine.
func (cs ClientState) VerifyClientConsensusState(

View File

@ -6,7 +6,6 @@ import (
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
"github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/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"
@ -32,52 +31,52 @@ func (suite *TendermintTestSuite) TestValidate() {
}{
{
name: "valid client",
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
expPass: true,
},
{
name: "invalid chainID",
clientState: ibctmtypes.NewClientState(" ", types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(" ", types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
expPass: false,
},
{
name: "invalid trust level",
clientState: ibctmtypes.NewClientState(chainID, types.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
expPass: false,
},
{
name: "invalid trusting period",
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, 0, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, 0, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
expPass: false,
},
{
name: "invalid unbonding period",
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, 0, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, 0, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
expPass: false,
},
{
name: "invalid max clock drift",
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, 0, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, 0, height, commitmenttypes.GetSDKSpecs()),
expPass: false,
},
{
name: "invalid height",
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, 0, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, 0, commitmenttypes.GetSDKSpecs()),
expPass: false,
},
{
name: "trusting period not less than unbonding period",
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
expPass: false,
},
{
name: "proof specs is nil",
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, nil),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, nil),
expPass: false,
},
{
name: "proof specs contains nil",
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, []*ics23.ProofSpec{ics23.TendermintSpec, nil}),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, []*ics23.ProofSpec{ics23.TendermintSpec, nil}),
expPass: false,
},
}
@ -95,8 +94,8 @@ func (suite *TendermintTestSuite) TestValidate() {
func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
testCases := []struct {
name string
clientState *ibctmtypes.ClientState
consensusState ibctmtypes.ConsensusState
clientState *types.ClientState
consensusState types.ConsensusState
prefix commitmenttypes.MerklePrefix
proof []byte
expPass bool
@ -104,8 +103,8 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
// FIXME: uncomment
// {
// name: "successful verification",
// clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
// consensusState: ibctmtypes.ConsensusState{
// clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
// consensusState: types.ConsensusState{
// Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
// },
// prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
@ -113,8 +112,8 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
// },
{
name: "ApplyPrefix failed",
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
consensusState: ibctmtypes.ConsensusState{
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
consensusState: types.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
},
prefix: commitmenttypes.MerklePrefix{},
@ -122,8 +121,8 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
},
{
name: "latest client height < height",
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
consensusState: ibctmtypes.ConsensusState{
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
consensusState: types.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
},
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
@ -131,8 +130,8 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
},
{
name: "client is frozen",
clientState: &ibctmtypes.ClientState{LatestHeight: height, FrozenHeight: height - 1},
consensusState: ibctmtypes.ConsensusState{
clientState: &types.ClientState{LatestHeight: height, FrozenHeight: height - 1},
consensusState: types.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
},
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
@ -140,8 +139,8 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
},
{
name: "proof verification failed",
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
consensusState: ibctmtypes.ConsensusState{
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
consensusState: types.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
NextValidatorsHash: suite.valsHash,
},

View File

@ -3,6 +3,7 @@ package types
import (
"bytes"
"encoding/binary"
"reflect"
"strings"
ics23 "github.com/confio/ics23/go"
@ -17,7 +18,6 @@ import (
channelexported "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported"
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
commitmentexported "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/exported"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
)
@ -91,13 +91,36 @@ func (cs ClientState) CheckMisbehaviourAndUpdateState(
return nil, sdkerrors.Wrap(clienttypes.ErrInvalidEvidence, "cannot submit misbehaviour to localhost client")
}
// VerifyClientConsensusState returns an error since a local host client does not store consensus
// VerifyClientState verifies that the localhost client state is stored locally
func (cs ClientState) VerifyClientState(
store sdk.KVStore, cdc codec.BinaryMarshaler, _ commitmentexported.Root,
_ uint64, _ commitmentexported.Prefix, _ string, _ []byte, clientState clientexported.ClientState,
) error {
path := host.KeyClientState()
bz := store.Get(path)
if bz == nil {
return sdkerrors.Wrapf(clienttypes.ErrFailedClientStateVerification,
"not found for path: %s", path)
}
selfClient := clienttypes.MustUnmarshalClientState(cdc, bz)
if !reflect.DeepEqual(selfClient, clientState) {
return sdkerrors.Wrapf(clienttypes.ErrFailedClientStateVerification,
"stored clientState != provided clientState: \n%v\n≠\n%v",
selfClient, clientState,
)
}
return nil
}
// VerifyClientConsensusState returns nil since a local host client does not store consensus
// states.
func (cs ClientState) VerifyClientConsensusState(
sdk.KVStore, codec.BinaryMarshaler, commitmentexported.Root,
uint64, string, uint64, commitmentexported.Prefix, []byte, clientexported.ConsensusState,
) error {
return ErrConsensusStatesNotStored
return nil
}
// VerifyConnectionState verifies a proof of the connection state of the
@ -106,28 +129,24 @@ func (cs ClientState) VerifyConnectionState(
store sdk.KVStore,
cdc codec.BinaryMarshaler,
_ uint64,
prefix commitmentexported.Prefix,
_ commitmentexported.Prefix,
_ []byte,
connectionID string,
connectionEnd connectionexported.ConnectionI,
) error {
path, err := commitmenttypes.ApplyPrefix(prefix, host.ConnectionPath(connectionID))
if err != nil {
return err
}
bz := store.Get([]byte(path.String()))
path := host.KeyConnection(connectionID)
bz := store.Get(path)
if bz == nil {
return sdkerrors.Wrapf(clienttypes.ErrFailedConnectionStateVerification, "not found for path %s", path)
}
var prevConnection connectiontypes.ConnectionEnd
err = cdc.UnmarshalBinaryBare(bz, &prevConnection)
err := cdc.UnmarshalBinaryBare(bz, &prevConnection)
if err != nil {
return err
}
if connectionEnd != &prevConnection {
if !reflect.DeepEqual(&prevConnection, connectionEnd) {
return sdkerrors.Wrapf(
clienttypes.ErrFailedConnectionStateVerification,
"connection end ≠ previous stored connection: \n%v\n≠\n%v", connectionEnd, prevConnection,
@ -149,23 +168,19 @@ func (cs ClientState) VerifyChannelState(
channelID string,
channel channelexported.ChannelI,
) error {
path, err := commitmenttypes.ApplyPrefix(prefix, host.ChannelPath(portID, channelID))
if err != nil {
return err
}
bz := store.Get([]byte(path.String()))
path := host.KeyChannel(portID, channelID)
bz := store.Get(path)
if bz == nil {
return sdkerrors.Wrapf(clienttypes.ErrFailedChannelStateVerification, "not found for path %s", path)
}
var prevChannel channeltypes.Channel
err = cdc.UnmarshalBinaryBare(bz, &prevChannel)
err := cdc.UnmarshalBinaryBare(bz, &prevChannel)
if err != nil {
return err
}
if channel != &prevChannel {
if !reflect.DeepEqual(&prevChannel, channel) {
return sdkerrors.Wrapf(
clienttypes.ErrFailedChannelStateVerification,
"channel end ≠ previous stored channel: \n%v\n≠\n%v", channel, prevChannel,
@ -181,19 +196,16 @@ func (cs ClientState) VerifyPacketCommitment(
store sdk.KVStore,
_ codec.BinaryMarshaler,
_ uint64,
prefix commitmentexported.Prefix,
_ commitmentexported.Prefix,
_ []byte,
portID,
channelID string,
sequence uint64,
commitmentBytes []byte,
) error {
path, err := commitmenttypes.ApplyPrefix(prefix, host.PacketCommitmentPath(portID, channelID, sequence))
if err != nil {
return err
}
path := host.KeyPacketCommitment(portID, channelID, sequence)
data := store.Get([]byte(path.String()))
data := store.Get(path)
if len(data) == 0 {
return sdkerrors.Wrapf(clienttypes.ErrFailedPacketCommitmentVerification, "not found for path %s", path)
}
@ -214,19 +226,16 @@ func (cs ClientState) VerifyPacketAcknowledgement(
store sdk.KVStore,
_ codec.BinaryMarshaler,
_ uint64,
prefix commitmentexported.Prefix,
_ commitmentexported.Prefix,
_ []byte,
portID,
channelID string,
sequence uint64,
acknowledgement []byte,
) error {
path, err := commitmenttypes.ApplyPrefix(prefix, host.PacketAcknowledgementPath(portID, channelID, sequence))
if err != nil {
return err
}
path := host.KeyPacketAcknowledgement(portID, channelID, sequence)
data := store.Get([]byte(path.String()))
data := store.Get(path)
if len(data) == 0 {
return sdkerrors.Wrapf(clienttypes.ErrFailedPacketAckVerification, "not found for path %s", path)
}
@ -248,18 +257,15 @@ func (cs ClientState) VerifyPacketAcknowledgementAbsence(
store sdk.KVStore,
_ codec.BinaryMarshaler,
_ uint64,
prefix commitmentexported.Prefix,
_ commitmentexported.Prefix,
_ []byte,
portID,
channelID string,
sequence uint64,
) error {
path, err := commitmenttypes.ApplyPrefix(prefix, host.PacketAcknowledgementPath(portID, channelID, sequence))
if err != nil {
return err
}
path := host.KeyPacketAcknowledgement(portID, channelID, sequence)
data := store.Get([]byte(path.String()))
data := store.Get(path)
if data != nil {
return sdkerrors.Wrap(clienttypes.ErrFailedPacketAckAbsenceVerification, "expected no ack absence")
}
@ -273,18 +279,15 @@ func (cs ClientState) VerifyNextSequenceRecv(
store sdk.KVStore,
_ codec.BinaryMarshaler,
_ uint64,
prefix commitmentexported.Prefix,
_ commitmentexported.Prefix,
_ []byte,
portID,
channelID string,
nextSequenceRecv uint64,
) error {
path, err := commitmenttypes.ApplyPrefix(prefix, host.NextSequenceRecvPath(portID, channelID))
if err != nil {
return err
}
path := host.KeyNextSequenceRecv(portID, channelID)
data := store.Get([]byte(path.String()))
data := store.Get(path)
if len(data) == 0 {
return sdkerrors.Wrapf(clienttypes.ErrFailedNextSeqRecvVerification, "not found for path %s", path)
}

View File

@ -1,10 +1,13 @@
package types_test
import (
sdk "github.com/cosmos/cosmos-sdk/types"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
"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"
)
const (
@ -47,106 +50,218 @@ func (suite *LocalhostTestSuite) TestValidate() {
}
}
func (suite *LocalhostTestSuite) TestVerifyClientState() {
clientState := types.NewClientState("chainID", 10)
invalidClient := types.NewClientState("chainID", 12)
testCases := []struct {
name string
clientState *types.ClientState
malleate func()
counterparty *types.ClientState
expPass bool
}{
{
name: "proof verification success",
clientState: clientState,
malleate: func() {
bz := clienttypes.MustMarshalClientState(suite.cdc, clientState)
suite.store.Set(host.KeyClientState(), bz)
},
counterparty: clientState,
expPass: true,
},
{
name: "proof verification failed: invalid client",
clientState: clientState,
malleate: func() {
bz := clienttypes.MustMarshalClientState(suite.cdc, clientState)
suite.store.Set(host.KeyClientState(), bz)
},
counterparty: invalidClient,
expPass: false,
},
{
name: "proof verification failed: client not stored",
clientState: clientState,
malleate: func() {},
counterparty: clientState,
expPass: false,
},
}
for _, tc := range testCases {
tc := tc
suite.Run(tc.name, func() {
suite.SetupTest()
tc.malleate()
err := tc.clientState.VerifyClientState(
suite.store, suite.cdc, nil, 10, nil, "", []byte{}, tc.counterparty,
)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *LocalhostTestSuite) TestVerifyClientConsensusState() {
clientState := types.NewClientState("chainID", 10)
err := clientState.VerifyClientConsensusState(
nil, nil, nil, 0, "", 0, nil, nil, nil,
)
suite.Require().Error(err)
suite.Require().NoError(err)
}
func (suite *LocalhostTestSuite) TestVerifyConnectionState() {
counterparty := connectiontypes.NewCounterparty("clientB", testConnectionID, commitmenttypes.NewMerklePrefix([]byte("ibc")))
conn := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "clientA", counterparty, []string{"1.0.0"})
conn1 := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "clientA", counterparty, []string{"1.0.0"})
conn2 := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "clientA", counterparty, []string{"2.0.0"})
testCases := []struct {
name string
clientState *types.ClientState
malleate func()
connection connectiontypes.ConnectionEnd
prefix commitmenttypes.MerklePrefix
proof []byte
expPass bool
}{
{
name: "ApplyPrefix failed",
name: "proof verification success",
clientState: types.NewClientState("chainID", 10),
connection: conn,
prefix: commitmenttypes.MerklePrefix{},
malleate: func() {
bz, err := suite.cdc.MarshalBinaryBare(&conn1)
suite.Require().NoError(err)
suite.store.Set(host.KeyConnection(testConnectionID), bz)
},
connection: conn1,
expPass: true,
},
{
name: "proof verification failed: connection not stored",
clientState: types.NewClientState("chainID", 10),
malleate: func() {},
connection: conn1,
expPass: false,
},
{
name: "proof verification failed",
name: "proof verification failed: unmarshal error",
clientState: types.NewClientState("chainID", 10),
connection: conn,
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
proof: []byte{},
expPass: false,
malleate: func() {
suite.store.Set(host.KeyConnection(testConnectionID), []byte("connection"))
},
connection: conn1,
expPass: false,
},
{
name: "proof verification failed: different connection stored",
clientState: types.NewClientState("chainID", 10),
malleate: func() {
bz, err := suite.cdc.MarshalBinaryBare(&conn2)
suite.Require().NoError(err)
suite.store.Set(host.KeyConnection(testConnectionID), bz)
},
connection: conn1,
expPass: false,
},
}
for i, tc := range testCases {
for _, tc := range testCases {
tc := tc
err := tc.clientState.VerifyConnectionState(
suite.store, suite.cdc, height, tc.prefix, tc.proof, testConnectionID, &tc.connection,
)
suite.Run(tc.name, func() {
suite.SetupTest()
tc.malleate()
if tc.expPass {
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
} else {
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
}
err := tc.clientState.VerifyConnectionState(
suite.store, suite.cdc, height, nil, []byte{}, testConnectionID, &tc.connection,
)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *LocalhostTestSuite) TestVerifyChannelState() {
counterparty := channeltypes.NewCounterparty(testPortID, testChannelID)
ch := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, counterparty, []string{testConnectionID}, "1.0.0")
ch1 := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, counterparty, []string{testConnectionID}, "1.0.0")
ch2 := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, counterparty, []string{testConnectionID}, "2.0.0")
testCases := []struct {
name string
clientState *types.ClientState
malleate func()
channel channeltypes.Channel
prefix commitmenttypes.MerklePrefix
proof []byte
expPass bool
}{
{
name: "ApplyPrefix failed",
name: "proof verification success",
clientState: types.NewClientState("chainID", 10),
channel: ch,
prefix: commitmenttypes.MerklePrefix{},
malleate: func() {
bz, err := suite.cdc.MarshalBinaryBare(&ch1)
suite.Require().NoError(err)
suite.store.Set(host.KeyChannel(testPortID, testChannelID), bz)
},
channel: ch1,
expPass: true,
},
{
name: "proof verification failed: channel not stored",
clientState: types.NewClientState("chainID", 10),
malleate: func() {},
channel: ch1,
expPass: false,
},
{
name: "latest client height < height",
name: "proof verification failed: unmarshal failed",
clientState: types.NewClientState("chainID", 10),
channel: ch,
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
expPass: false,
malleate: func() {
suite.store.Set(host.KeyChannel(testPortID, testChannelID), []byte("channel"))
},
channel: ch1,
expPass: false,
},
{
name: "proof verification failed",
name: "proof verification failed: different channel stored",
clientState: types.NewClientState("chainID", 10),
channel: ch,
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
proof: []byte{},
expPass: false,
malleate: func() {
bz, err := suite.cdc.MarshalBinaryBare(&ch2)
suite.Require().NoError(err)
suite.store.Set(host.KeyChannel(testPortID, testChannelID), bz)
},
channel: ch1,
expPass: false,
},
}
for i, tc := range testCases {
for _, tc := range testCases {
tc := tc
err := tc.clientState.VerifyChannelState(
suite.store, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, &tc.channel,
)
suite.Run(tc.name, func() {
suite.SetupTest()
tc.malleate()
if tc.expPass {
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
} else {
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
}
err := tc.clientState.VerifyChannelState(
suite.store, suite.cdc, height, nil, []byte{}, testPortID, testChannelID, &tc.channel,
)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
@ -154,54 +269,58 @@ func (suite *LocalhostTestSuite) TestVerifyPacketCommitment() {
testCases := []struct {
name string
clientState *types.ClientState
malleate func()
commitment []byte
prefix commitmenttypes.MerklePrefix
proof []byte
expPass bool
}{
{
name: "ApplyPrefix failed",
name: "proof verification success",
clientState: types.NewClientState("chainID", 10),
commitment: []byte{},
prefix: commitmenttypes.MerklePrefix{},
expPass: false,
malleate: func() {
suite.store.Set(
host.KeyPacketCommitment(testPortID, testChannelID, testSequence), []byte("commitment"),
)
},
commitment: []byte("commitment"),
expPass: true,
},
{
name: "latest client height < height",
name: "proof verification failed: different commitment stored",
clientState: types.NewClientState("chainID", 10),
commitment: []byte{},
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
expPass: false,
malleate: func() {
suite.store.Set(
host.KeyPacketCommitment(testPortID, testChannelID, testSequence), []byte("different"),
)
},
commitment: []byte("commitment"),
expPass: false,
},
{
name: "client is frozen",
name: "proof verification failed: no commitment stored",
clientState: types.NewClientState("chainID", 10),
malleate: func() {},
commitment: []byte{},
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
expPass: false,
},
{
name: "proof verification failed",
clientState: types.NewClientState("chainID", 10),
commitment: []byte{},
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
proof: []byte{},
expPass: false,
},
}
for i, tc := range testCases {
for _, tc := range testCases {
tc := tc
err := tc.clientState.VerifyPacketCommitment(
suite.store, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence, tc.commitment,
)
suite.Run(tc.name, func() {
suite.SetupTest()
tc.malleate()
if tc.expPass {
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
} else {
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
}
err := tc.clientState.VerifyPacketCommitment(
suite.store, suite.cdc, height, nil, []byte{}, testPortID, testChannelID, testSequence, tc.commitment,
)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
@ -209,134 +328,137 @@ func (suite *LocalhostTestSuite) TestVerifyPacketAcknowledgement() {
testCases := []struct {
name string
clientState *types.ClientState
malleate func()
ack []byte
prefix commitmenttypes.MerklePrefix
proof []byte
expPass bool
}{
{
name: "ApplyPrefix failed",
name: "proof verification success",
clientState: types.NewClientState("chainID", 10),
ack: []byte{},
prefix: commitmenttypes.MerklePrefix{},
expPass: false,
malleate: func() {
suite.store.Set(
host.KeyPacketAcknowledgement(testPortID, testChannelID, testSequence), []byte("acknowledgement"),
)
},
ack: []byte("acknowledgement"),
expPass: true,
},
{
name: "latest client height < height",
name: "proof verification failed: different ack stored",
clientState: types.NewClientState("chainID", 10),
ack: []byte{},
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
expPass: false,
malleate: func() {
suite.store.Set(
host.KeyPacketAcknowledgement(testPortID, testChannelID, testSequence), []byte("different"),
)
},
ack: []byte("acknowledgment"),
expPass: false,
},
{
name: "client is frozen",
name: "proof verification failed: no commitment stored",
clientState: types.NewClientState("chainID", 10),
malleate: func() {},
ack: []byte{},
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
expPass: false,
},
{
name: "proof verification failed",
clientState: types.NewClientState("chainID", 10),
ack: []byte{},
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
proof: []byte{},
expPass: false,
},
}
for i, tc := range testCases {
for _, tc := range testCases {
tc := tc
err := tc.clientState.VerifyPacketAcknowledgement(
suite.store, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence, tc.ack,
)
suite.Run(tc.name, func() {
suite.SetupTest()
tc.malleate()
if tc.expPass {
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
} else {
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
}
err := tc.clientState.VerifyPacketAcknowledgement(
suite.store, suite.cdc, height, nil, []byte{}, testPortID, testChannelID, testSequence, tc.ack,
)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *LocalhostTestSuite) TestVerifyPacketAcknowledgementAbsence() {
testCases := []struct {
name string
clientState *types.ClientState
prefix commitmenttypes.MerklePrefix
proof []byte
expPass bool
}{
{
name: "ApplyPrefix failed",
clientState: types.NewClientState("chainID", 10),
prefix: commitmenttypes.MerklePrefix{},
expPass: false,
},
}
clientState := types.NewClientState("chainID", 10)
for i, tc := range testCases {
tc := tc
err := clientState.VerifyPacketAcknowledgementAbsence(
suite.store, suite.cdc, height, nil, nil, testPortID, testChannelID, testSequence,
)
err := tc.clientState.VerifyPacketAcknowledgementAbsence(
suite.store, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence,
)
suite.Require().NoError(err, "ack absence failed")
if tc.expPass {
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
} else {
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
}
}
suite.store.Set(host.KeyPacketAcknowledgement(testPortID, testChannelID, testSequence), []byte("ack"))
err = clientState.VerifyPacketAcknowledgementAbsence(
suite.store, suite.cdc, height, nil, nil, testPortID, testChannelID, testSequence,
)
suite.Require().Error(err, "ack exists in store")
}
func (suite *LocalhostTestSuite) TestVerifyNextSeqRecv() {
nextSeqRecv := uint64(5)
testCases := []struct {
name string
clientState *types.ClientState
prefix commitmenttypes.MerklePrefix
proof []byte
malleate func()
nextSeqRecv uint64
expPass bool
}{
{
name: "ApplyPrefix failed",
name: "proof verification success",
clientState: types.NewClientState("chainID", 10),
prefix: commitmenttypes.MerklePrefix{},
malleate: func() {
suite.store.Set(
host.KeyNextSequenceRecv(testPortID, testChannelID),
sdk.Uint64ToBigEndian(nextSeqRecv),
)
},
nextSeqRecv: nextSeqRecv,
expPass: true,
},
{
name: "proof verification failed: different nextSeqRecv stored",
clientState: types.NewClientState("chainID", 10),
malleate: func() {
suite.store.Set(
host.KeyNextSequenceRecv(testPortID, testChannelID),
sdk.Uint64ToBigEndian(3),
)
},
nextSeqRecv: nextSeqRecv,
expPass: false,
},
{
name: "latest client height < height",
name: "proof verification failed: no nextSeqRecv stored",
clientState: types.NewClientState("chainID", 10),
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
expPass: false,
},
{
name: "client is frozen",
clientState: types.NewClientState("chainID", 10),
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
expPass: false,
},
{
name: "proof verification failed",
clientState: types.NewClientState("chainID", 10),
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
proof: []byte{},
malleate: func() {},
nextSeqRecv: nextSeqRecv,
expPass: false,
},
}
for i, tc := range testCases {
for _, tc := range testCases {
tc := tc
err := tc.clientState.VerifyNextSequenceRecv(
suite.store, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence,
)
suite.Run(tc.name, func() {
suite.SetupTest()
tc.malleate()
if tc.expPass {
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
} else {
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
}
err := tc.clientState.VerifyNextSequenceRecv(
suite.store, suite.cdc, height, nil, []byte{}, testPortID, testChannelID, nextSeqRecv,
)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}

View File

@ -91,10 +91,12 @@ using the `MsgConnectionOpenTry`.
type MsgConnectionOpenTry struct {
ClientId string
ConnectionId string
ClientState *types.Any // proto-packed counterparty client
Counterparty Counterparty
CounterpartyVersions []string
ProofInit []byte
ProofHeight uint64
ProofInit []byte
ProofClient []byte
ProofConsensus []byte
ConsensusHeight uint64
Signer sdk.AccAddress
@ -104,16 +106,19 @@ type MsgConnectionOpenTry struct {
This message is expected to fail if:
- `ClientId` is invalid (see naming requirements)
- `ConnectionId` is invalid (see naming requirements)
- `ClientState` is not a valid client of the executing chain
- `Counterparty` is empty
- `CounterpartyVersions` is empty
- `ProofInit` is empty
- `ProofHeight` is zero
- `ProofInit` is empty
- `ProofClient` is empty
- `ProofConsensus` is empty
- `ConsensusHeight` is zero
- `Signer` is empty
- A Client hasn't been created for the given ID
- A Connection for the given ID already exists
- `ProofInit` does not prove that the counterparty connection is in state INIT
- `ProofClient` does not prove that the counterparty has stored the `ClientState` provided in message
- `ProofConsensus` does not prove that the counterparty has the correct consensus state for this chain
The message creates a connection for the given ID with an TRYOPEN State.
@ -127,8 +132,10 @@ using the `MsgConnectionOpenAck`.
type MsgConnectionOpenAck struct {
ConnectionId string
Version string
ProofTry []byte
ClientState *types.Any // proto-packed counterparty client
ProofHeight uint64
ProofTry []byte
ProofClient []byte
ProofConsensus []byte
ConsensusHeight uint64
Signer sdk.AccAddress
@ -138,12 +145,15 @@ type MsgConnectionOpenAck struct {
This message is expected to fail if:
- `ConnectionId` is invalid (see naming requirements)
- `Version` is empty
- `ProofTry` is empty
- `ClientState` is not a valid client of the executing chain
- `ProofHeight` is zero
- `ProofTry` is empty
- `ProofClient` is empty
- `ProofConsensus` is empty
- `ConsensusHeight` is zero
- `Signer` is empty
- `ProofTry` does not prove that the counterparty connection is in state TRYOPEN
- `ProofClient` does not prove that the counterparty has stored the `ClientState` provided by message
- `ProofConsensus` does not prove that the counterparty has the correct consensus state for this chain
The message sets the connection state for the given ID to OPEN.

View File

@ -170,6 +170,19 @@ func (chain *TestChain) QueryProof(key []byte) ([]byte, uint64) {
return proof, uint64(res.Height) + 1
}
// QueryClientStateProof performs and abci query for a client state
// stored with a given clientID and returns the ClientState along with the proof
func (chain *TestChain) QueryClientStateProof(clientID string) (clientexported.ClientState, []byte) {
// retrieve client state to provide proof for
clientState, found := chain.App.IBCKeeper.ClientKeeper.GetClientState(chain.GetContext(), clientID)
require.True(chain.t, found)
clientKey := host.FullKeyClientPath(clientID, host.KeyClientState())
proofClient, _ := chain.QueryProof(clientKey)
return clientState, proofClient
}
// QueryConsensusStateProof performs an abci query for a consensus state
// stored on the given clientID. The proof and consensusHeight are returned.
func (chain *TestChain) QueryConsensusStateProof(clientID string) ([]byte, uint64) {
@ -194,6 +207,7 @@ func (chain *TestChain) NextBlock() {
// increment the current header
chain.CurrentHeader = tmproto.Header{
ChainID: chain.ChainID,
Height: chain.App.LastBlockHeight() + 1,
AppHash: chain.App.LastCommitID().Hash,
// NOTE: the time is increased by the coordinator to maintain time synchrony amongst
@ -216,6 +230,7 @@ func (chain *TestChain) SendMsgs(msgs ...sdk.Msg) error {
chain.App.BaseApp,
chain.GetContext().BlockHeader(),
msgs,
chain.ChainID,
[]uint64{chain.SenderAccount.GetAccountNumber()},
[]uint64{chain.SenderAccount.GetSequence()},
true, true, chain.senderPrivKey,
@ -467,6 +482,8 @@ func (chain *TestChain) ConnectionOpenTry(
counterparty *TestChain,
connection, counterpartyConnection *TestConnection,
) error {
counterpartyClient, proofClient := counterparty.QueryClientStateProof(counterpartyConnection.ClientID)
connectionKey := host.KeyConnection(counterpartyConnection.ID)
proofInit, proofHeight := counterparty.QueryProof(connectionKey)
@ -475,8 +492,8 @@ func (chain *TestChain) ConnectionOpenTry(
msg := connectiontypes.NewMsgConnectionOpenTry(
connection.ID, connection.ClientID,
counterpartyConnection.ID, counterpartyConnection.ClientID,
counterparty.GetPrefix(), []string{ConnectionVersion},
proofInit, proofConsensus,
counterpartyClient, counterparty.GetPrefix(), []string{ConnectionVersion},
proofInit, proofClient, proofConsensus,
proofHeight, consensusHeight,
chain.SenderAccount.GetAddress(),
)
@ -488,14 +505,16 @@ func (chain *TestChain) ConnectionOpenAck(
counterparty *TestChain,
connection, counterpartyConnection *TestConnection,
) error {
counterpartyClient, proofClient := counterparty.QueryClientStateProof(counterpartyConnection.ClientID)
connectionKey := host.KeyConnection(counterpartyConnection.ID)
proofTry, proofHeight := counterparty.QueryProof(connectionKey)
proofConsensus, consensusHeight := counterparty.QueryConsensusStateProof(counterpartyConnection.ClientID)
msg := connectiontypes.NewMsgConnectionOpenAck(
connection.ID,
proofTry, proofConsensus,
connection.ID, counterpartyClient,
proofTry, proofClient, proofConsensus,
proofHeight, consensusHeight,
ConnectionVersion,
chain.SenderAccount.GetAddress(),

View File

@ -88,7 +88,6 @@ func local_request_Query_AnnualProvisions_0(ctx context.Context, marshaler runti
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -70,7 +70,6 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -69,7 +69,7 @@ func TestSlashingMsgs(t *testing.T) {
header := tmproto.Header{Height: app.LastBlockHeight() + 1}
txGen := simapp.MakeEncodingConfig().TxConfig
_, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{createValidatorMsg}, []uint64{0}, []uint64{0}, true, true, priv1)
_, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{createValidatorMsg}, "", []uint64{0}, []uint64{0}, true, true, priv1)
require.NoError(t, err)
simapp.CheckBalance(t, app, addr1, sdk.Coins{genCoin.Sub(bondCoin)})
@ -86,7 +86,7 @@ func TestSlashingMsgs(t *testing.T) {
// unjail should fail with unknown validator
header = tmproto.Header{Height: app.LastBlockHeight() + 1}
_, res, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{unjailMsg}, []uint64{0}, []uint64{1}, false, false, priv1)
_, res, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{unjailMsg}, "", []uint64{0}, []uint64{1}, false, false, priv1)
require.Error(t, err)
require.Nil(t, res)
require.True(t, errors.Is(types.ErrValidatorNotJailed, err))

View File

@ -142,7 +142,6 @@ func local_request_Query_SigningInfos_0(ctx context.Context, marshaler runtime.M
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -71,7 +71,7 @@ func TestStakingMsgs(t *testing.T) {
header := tmproto.Header{Height: app.LastBlockHeight() + 1}
txGen := simapp.MakeEncodingConfig().TxConfig
_, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{createValidatorMsg}, []uint64{0}, []uint64{0}, true, true, priv1)
_, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{createValidatorMsg}, "", []uint64{0}, []uint64{0}, true, true, priv1)
require.NoError(t, err)
simapp.CheckBalance(t, app, addr1, sdk.Coins{genCoin.Sub(bondCoin)})
@ -91,7 +91,7 @@ func TestStakingMsgs(t *testing.T) {
editValidatorMsg := types.NewMsgEditValidator(sdk.ValAddress(addr1), description, nil, nil)
header = tmproto.Header{Height: app.LastBlockHeight() + 1}
_, _, err = simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{editValidatorMsg}, []uint64{0}, []uint64{1}, true, true, priv1)
_, _, err = simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{editValidatorMsg}, "", []uint64{0}, []uint64{1}, true, true, priv1)
require.NoError(t, err)
validator = checkValidator(t, app, sdk.ValAddress(addr1), true)
@ -102,7 +102,7 @@ func TestStakingMsgs(t *testing.T) {
delegateMsg := types.NewMsgDelegate(addr2, sdk.ValAddress(addr1), bondCoin)
header = tmproto.Header{Height: app.LastBlockHeight() + 1}
_, _, err = simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{delegateMsg}, []uint64{1}, []uint64{0}, true, true, priv2)
_, _, err = simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{delegateMsg}, "", []uint64{1}, []uint64{0}, true, true, priv2)
require.NoError(t, err)
simapp.CheckBalance(t, app, addr2, sdk.Coins{genCoin.Sub(bondCoin)})
@ -111,7 +111,7 @@ func TestStakingMsgs(t *testing.T) {
// begin unbonding
beginUnbondingMsg := types.NewMsgUndelegate(addr2, sdk.ValAddress(addr1), bondCoin)
header = tmproto.Header{Height: app.LastBlockHeight() + 1}
_, _, err = simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{beginUnbondingMsg}, []uint64{1}, []uint64{1}, true, true, priv2)
_, _, err = simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{beginUnbondingMsg}, "", []uint64{1}, []uint64{1}, true, true, priv2)
require.NoError(t, err)
// delegation should exist anymore

View File

@ -874,7 +874,6 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Validators_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -106,7 +106,6 @@ func local_request_Query_AppliedPlan_0(ctx context.Context, marshaler runtime.Ma
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_CurrentPlan_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {