diff --git a/CHANGELOG.md b/CHANGELOG.md
index c536f16ed8d..458dc36a1f6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -44,6 +44,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
 
 ### API Breaking
 
+* (modules) [\#140](https://github.com/cosmos/ibc-go/pull/140) IsFrozen() client state interface changed to Status(). gRPC `ClientStatus` route added.
 * (modules/core) [\#109](https://github.com/cosmos/ibc-go/pull/109) Remove connection and channel handshake CLI commands.
 * (modules) [\#107](https://github.com/cosmos/ibc-go/pull/107) Modify OnRecvPacket callback to return an acknowledgement which indicates if it is successful or not. Callback state changes are discarded for unsuccessful acknowledgements only. 
 * (modules) [\#108](https://github.com/cosmos/ibc-go/pull/108) All message constructors take the signer as a string to prevent upstream bugs. The `String()` function for an SDK Acc Address relies on external context.
diff --git a/docs/ibc/proto-docs.md b/docs/ibc/proto-docs.md
index 5cf16d3fe09..14fc96fa8b1 100644
--- a/docs/ibc/proto-docs.md
+++ b/docs/ibc/proto-docs.md
@@ -640,6 +640,14 @@
                   <a href="#ibc.core.client.v1.QueryClientStatesResponse"><span class="badge">M</span>QueryClientStatesResponse</a>
                 </li>
               
+                <li>
+                  <a href="#ibc.core.client.v1.QueryClientStatusRequest"><span class="badge">M</span>QueryClientStatusRequest</a>
+                </li>
+              
+                <li>
+                  <a href="#ibc.core.client.v1.QueryClientStatusResponse"><span class="badge">M</span>QueryClientStatusResponse</a>
+                </li>
+              
                 <li>
                   <a href="#ibc.core.client.v1.QueryConsensusStateRequest"><span class="badge">M</span>QueryConsensusStateRequest</a>
                 </li>
@@ -4547,6 +4555,54 @@ MsgChannelCloseConfirm.</p></td>
 
         
       
+        <h3 id="ibc.core.client.v1.QueryClientStatusRequest">QueryClientStatusRequest</h3>
+        <p>QueryClientStatusRequest is the request type for the Query/ClientStatus RPC</p><p>method</p>
+
+        
+          <table class="field-table">
+            <thead>
+              <tr><td>Field</td><td>Type</td><td>Label</td><td>Description</td></tr>
+            </thead>
+            <tbody>
+              
+                <tr>
+                  <td>client_id</td>
+                  <td><a href="#string">string</a></td>
+                  <td></td>
+                  <td><p>client unique identifier </p></td>
+                </tr>
+              
+            </tbody>
+          </table>
+
+          
+
+        
+      
+        <h3 id="ibc.core.client.v1.QueryClientStatusResponse">QueryClientStatusResponse</h3>
+        <p>QueryClientStatusResponse is the response type for the Query/ClientStatus RPC</p><p>method. It returns the current status of the IBC client.</p>
+
+        
+          <table class="field-table">
+            <thead>
+              <tr><td>Field</td><td>Type</td><td>Label</td><td>Description</td></tr>
+            </thead>
+            <tbody>
+              
+                <tr>
+                  <td>status</td>
+                  <td><a href="#string">string</a></td>
+                  <td></td>
+                  <td><p> </p></td>
+                </tr>
+              
+            </tbody>
+          </table>
+
+          
+
+        
+      
         <h3 id="ibc.core.client.v1.QueryConsensusStateRequest">QueryConsensusStateRequest</h3>
         <p>QueryConsensusStateRequest is the request type for the Query/ConsensusState</p><p>RPC method. Besides the consensus state, it includes a proof and the height</p><p>from which the proof was retrieved.</p>
 
@@ -4799,6 +4855,13 @@ a given height.</p></td>
 client.</p></td>
               </tr>
             
+              <tr>
+                <td>ClientStatus</td>
+                <td><a href="#ibc.core.client.v1.QueryClientStatusRequest">QueryClientStatusRequest</a></td>
+                <td><a href="#ibc.core.client.v1.QueryClientStatusResponse">QueryClientStatusResponse</a></td>
+                <td><p>Status queries the status of an IBC client.</p></td>
+              </tr>
+            
               <tr>
                 <td>ClientParams</td>
                 <td><a href="#ibc.core.client.v1.QueryClientParamsRequest">QueryClientParamsRequest</a></td>
@@ -4880,6 +4943,16 @@ client.</p></td>
             
               
               
+              <tr>
+                <td>ClientStatus</td>
+                <td>GET</td>
+                <td>/ibc/core/client/v1/client_status/{client_id}</td>
+                <td></td>
+              </tr>
+              
+            
+              
+              
               <tr>
                 <td>ClientParams</td>
                 <td>GET</td>
diff --git a/modules/core/02-client/keeper/client.go b/modules/core/02-client/keeper/client.go
index e8288da5f61..c5416b9e803 100644
--- a/modules/core/02-client/keeper/client.go
+++ b/modules/core/02-client/keeper/client.go
@@ -61,12 +61,13 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H
 		return sdkerrors.Wrapf(types.ErrClientNotFound, "cannot update client with ID %s", clientID)
 	}
 
-	// prevent update if the client is frozen before or at header height
-	if clientState.IsFrozen() && clientState.GetFrozenHeight().LTE(header.GetHeight()) {
-		return sdkerrors.Wrapf(types.ErrClientFrozen, "cannot update client with ID %s", clientID)
+	clientStore := k.ClientStore(ctx, clientID)
+
+	if status := clientState.Status(ctx, clientStore, k.cdc); status != exported.Active {
+		return sdkerrors.Wrapf(types.ErrClientNotActive, "cannot update client (%s) with status %s", clientID, status)
 	}
 
-	clientState, consensusState, err := clientState.CheckHeaderAndUpdateState(ctx, k.cdc, k.ClientStore(ctx, clientID), header)
+	clientState, consensusState, err := clientState.CheckHeaderAndUpdateState(ctx, k.cdc, clientStore, header)
 	if err != nil {
 		return sdkerrors.Wrapf(err, "cannot update client with ID %s", clientID)
 	}
@@ -130,12 +131,13 @@ func (k Keeper) UpgradeClient(ctx sdk.Context, clientID string, upgradedClient e
 		return sdkerrors.Wrapf(types.ErrClientNotFound, "cannot update client with ID %s", clientID)
 	}
 
-	// prevent upgrade if current client is frozen
-	if clientState.IsFrozen() {
-		return sdkerrors.Wrapf(types.ErrClientFrozen, "cannot update client with ID %s", clientID)
+	clientStore := k.ClientStore(ctx, clientID)
+
+	if status := clientState.Status(ctx, clientStore, k.cdc); status != exported.Active {
+		return sdkerrors.Wrapf(types.ErrClientNotActive, "cannot upgrade client (%s) with status %s", clientID, status)
 	}
 
-	updatedClientState, updatedConsState, err := clientState.VerifyUpgradeAndUpdateState(ctx, k.cdc, k.ClientStore(ctx, clientID),
+	updatedClientState, updatedConsState, err := clientState.VerifyUpgradeAndUpdateState(ctx, k.cdc, clientStore,
 		upgradedClient, upgradedConsState, proofUpgradeClient, proofUpgradeConsState)
 	if err != nil {
 		return sdkerrors.Wrapf(err, "cannot upgrade client with ID %s", clientID)
@@ -178,11 +180,13 @@ func (k Keeper) CheckMisbehaviourAndUpdateState(ctx sdk.Context, misbehaviour ex
 		return sdkerrors.Wrapf(types.ErrClientNotFound, "cannot check misbehaviour for client with ID %s", misbehaviour.GetClientID())
 	}
 
-	if clientState.IsFrozen() && clientState.GetFrozenHeight().LTE(misbehaviour.GetHeight()) {
-		return sdkerrors.Wrapf(types.ErrInvalidMisbehaviour, "client is already frozen at height ≤ misbehaviour height (%s ≤ %s)", clientState.GetFrozenHeight(), misbehaviour.GetHeight())
+	clientStore := k.ClientStore(ctx, misbehaviour.GetClientID())
+
+	if status := clientState.Status(ctx, clientStore, k.cdc); status != exported.Active {
+		return sdkerrors.Wrapf(types.ErrClientNotActive, "cannot process misbehaviour for client (%s) with status %s", misbehaviour.GetClientID(), status)
 	}
 
-	clientState, err := clientState.CheckMisbehaviourAndUpdateState(ctx, k.cdc, k.ClientStore(ctx, misbehaviour.GetClientID()), misbehaviour)
+	clientState, err := clientState.CheckMisbehaviourAndUpdateState(ctx, k.cdc, clientStore, misbehaviour)
 	if err != nil {
 		return err
 	}
diff --git a/modules/core/02-client/keeper/client_test.go b/modules/core/02-client/keeper/client_test.go
index b42322d992d..1e1f393df9a 100644
--- a/modules/core/02-client/keeper/client_test.go
+++ b/modules/core/02-client/keeper/client_test.go
@@ -42,141 +42,101 @@ func (suite *KeeperTestSuite) TestCreateClient() {
 }
 
 func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
-	// Must create header creation functions since suite.header gets recreated on each test case
-	createFutureUpdateFn := func(s *KeeperTestSuite) *ibctmtypes.Header {
-		heightPlus3 := clienttypes.NewHeight(suite.header.GetHeight().GetRevisionNumber(), suite.header.GetHeight().GetRevisionHeight()+3)
-		height := suite.header.GetHeight().(clienttypes.Height)
-
-		return suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus3.RevisionHeight), height, suite.header.Header.Time.Add(time.Hour),
-			suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
-	}
-	createPastUpdateFn := func(s *KeeperTestSuite) *ibctmtypes.Header {
-		heightMinus2 := clienttypes.NewHeight(suite.header.GetHeight().GetRevisionNumber(), suite.header.GetHeight().GetRevisionHeight()-2)
-		heightMinus4 := clienttypes.NewHeight(suite.header.GetHeight().GetRevisionNumber(), suite.header.GetHeight().GetRevisionHeight()-4)
-
-		return suite.chainA.CreateTMClientHeader(testChainID, int64(heightMinus2.RevisionHeight), heightMinus4, suite.header.Header.Time,
-			suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
-	}
 	var (
+		path         *ibctesting.Path
 		updateHeader *ibctmtypes.Header
-		clientState  *ibctmtypes.ClientState
-		clientID     string
-		err          error
 	)
 
+	// Must create header creation functions since suite.header gets recreated on each test case
+	createFutureUpdateFn := func(trustedHeight clienttypes.Height) *ibctmtypes.Header {
+		header, err := suite.chainA.ConstructUpdateTMClientHeaderWithTrustedHeight(path.EndpointB.Chain, path.EndpointA.ClientID, trustedHeight)
+		suite.Require().NoError(err)
+		return header
+	}
+
+	createPastUpdateFn := func(fillHeight, trustedHeight clienttypes.Height) *ibctmtypes.Header {
+		consState, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientConsensusState(suite.chainA.GetContext(), path.EndpointA.ClientID, trustedHeight)
+		suite.Require().True(found)
+
+		return suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(fillHeight.RevisionHeight), trustedHeight, consState.(*ibctmtypes.ConsensusState).Timestamp.Add(time.Second*5),
+			suite.chainB.Vals, suite.chainB.Vals, suite.chainB.Signers)
+	}
 	cases := []struct {
 		name     string
-		malleate func() error
+		malleate func()
 		expPass  bool
 	}{
-		{"valid update", func() error {
-			clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
-			clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState)
+		{"valid update", func() {
+			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+			trustHeight := clientState.GetLatestHeight().(types.Height)
 
 			// store intermediate consensus state to check that trustedHeight does not need to be highest consensus state before header height
-			incrementedClientHeight := testClientHeight.Increment().(types.Height)
-			intermediateConsState := &ibctmtypes.ConsensusState{
-				Timestamp:          suite.now.Add(time.Minute),
-				NextValidatorsHash: suite.valSetHash,
-			}
-			suite.keeper.SetClientConsensusState(suite.ctx, clientID, incrementedClientHeight, intermediateConsState)
-
-			clientState.LatestHeight = incrementedClientHeight
-			suite.keeper.SetClientState(suite.ctx, clientID, clientState)
+			path.EndpointA.UpdateClient()
 
-			updateHeader = createFutureUpdateFn(suite)
-			return err
+			updateHeader = createFutureUpdateFn(trustHeight)
 		}, true},
-		{"valid past update", func() error {
-			clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
-			clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState)
-			suite.Require().NoError(err)
+		{"valid past update", func() {
+			clientState := path.EndpointA.GetClientState()
+			trustedHeight := clientState.GetLatestHeight().(types.Height)
 
-			height1 := types.NewHeight(0, 1)
+			currHeight := suite.chainB.CurrentHeader.Height
+			fillHeight := types.NewHeight(clientState.GetLatestHeight().GetRevisionNumber(), uint64(currHeight))
 
-			// store previous consensus state
-			prevConsState := &ibctmtypes.ConsensusState{
-				Timestamp:          suite.past,
-				NextValidatorsHash: suite.valSetHash,
-			}
-			suite.keeper.SetClientConsensusState(suite.ctx, clientID, height1, prevConsState)
+			// commit a couple blocks to allow client to fill in gaps
+			suite.coordinator.CommitBlock(suite.chainB) // this height is not filled in yet
+			suite.coordinator.CommitBlock(suite.chainB) // this height is filled in by the update below
 
-			height2 := types.NewHeight(0, 2)
+			path.EndpointA.UpdateClient()
 
-			// store intermediate consensus state to check that trustedHeight does not need to be hightest consensus state before header height
-			intermediateConsState := &ibctmtypes.ConsensusState{
-				Timestamp:          suite.past.Add(time.Minute),
-				NextValidatorsHash: suite.valSetHash,
-			}
-			suite.keeper.SetClientConsensusState(suite.ctx, clientID, height2, intermediateConsState)
+			// ensure fill height not set
+			_, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientConsensusState(suite.chainA.GetContext(), path.EndpointA.ClientID, fillHeight)
+			suite.Require().False(found)
 
 			// updateHeader will fill in consensus state between prevConsState and suite.consState
 			// clientState should not be updated
-			updateHeader = createPastUpdateFn(suite)
-			return nil
+			updateHeader = createPastUpdateFn(fillHeight, trustedHeight)
 		}, true},
-		{"client state not found", func() error {
-			updateHeader = createFutureUpdateFn(suite)
+		{"client state not found", func() {
+			updateHeader = createFutureUpdateFn(path.EndpointA.GetClientState().GetLatestHeight().(types.Height))
 
-			return nil
+			path.EndpointA.ClientID = ibctesting.InvalidID
 		}, false},
-		{"consensus state not found", func() error {
-			clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
-			suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
-			updateHeader = createFutureUpdateFn(suite)
-
-			return nil
+		{"consensus state not found", func() {
+			clientState := path.EndpointA.GetClientState()
+			tmClient, ok := clientState.(*ibctmtypes.ClientState)
+			suite.Require().True(ok)
+			tmClient.LatestHeight = tmClient.LatestHeight.Increment().(types.Height)
+
+			suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID, clientState)
+			updateHeader = createFutureUpdateFn(clientState.GetLatestHeight().(types.Height))
 		}, false},
-		{"frozen client before update", func() error {
-			clientState = &ibctmtypes.ClientState{FrozenHeight: types.NewHeight(0, 1), LatestHeight: testClientHeight}
-			suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
-			updateHeader = createFutureUpdateFn(suite)
-
-			return nil
+		{"client is not active", func() {
+			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+			clientState.FrozenHeight = types.NewHeight(0, 1)
+			suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID, clientState)
+			updateHeader = createFutureUpdateFn(clientState.GetLatestHeight().(types.Height))
 		}, false},
-		{"valid past update before client was frozen", func() error {
-			clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
-			clientState.FrozenHeight = types.NewHeight(0, testClientHeight.RevisionHeight-1)
-			clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState)
-			suite.Require().NoError(err)
-
-			height1 := types.NewHeight(0, 1)
-
-			// store previous consensus state
-			prevConsState := &ibctmtypes.ConsensusState{
-				Timestamp:          suite.past,
-				NextValidatorsHash: suite.valSetHash,
-			}
-			suite.keeper.SetClientConsensusState(suite.ctx, clientID, height1, prevConsState)
-
-			// updateHeader will fill in consensus state between prevConsState and suite.consState
-			// clientState should not be updated
-			updateHeader = createPastUpdateFn(suite)
-			return nil
-		}, true},
-		{"invalid header", func() error {
-			clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
-			_, err := suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState)
-			suite.Require().NoError(err)
-			updateHeader = createPastUpdateFn(suite)
-
-			return nil
+		{"invalid header", func() {
+			updateHeader = createFutureUpdateFn(path.EndpointA.GetClientState().GetLatestHeight().(types.Height))
+			updateHeader.TrustedHeight = updateHeader.TrustedHeight.Increment().(types.Height)
 		}, false},
 	}
 
-	for i, tc := range cases {
+	for _, tc := range cases {
 		tc := tc
-		i := i
 		suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
 			suite.SetupTest()
-			clientID = testClientID // must be explicitly changed
+			path = ibctesting.NewPath(suite.chainA, suite.chainB)
+			suite.coordinator.SetupClients(path)
 
-			err := tc.malleate()
-			suite.Require().NoError(err)
+			tc.malleate()
 
-			suite.ctx = suite.ctx.WithBlockTime(updateHeader.Header.Time.Add(time.Minute))
+			var clientState exported.ClientState
+			if tc.expPass {
+				clientState = path.EndpointA.GetClientState()
+			}
 
-			err = suite.keeper.UpdateClient(suite.ctx, clientID, updateHeader)
+			err := suite.chainA.App.GetIBCKeeper().ClientKeeper.UpdateClient(suite.chainA.GetContext(), path.EndpointA.ClientID, updateHeader)
 
 			if tc.expPass {
 				suite.Require().NoError(err, err)
@@ -187,11 +147,10 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
 					NextValidatorsHash: updateHeader.Header.NextValidatorsHash,
 				}
 
-				newClientState, found := suite.keeper.GetClientState(suite.ctx, clientID)
-				suite.Require().True(found, "valid test case %d failed: %s", i, tc.name)
+				newClientState := path.EndpointA.GetClientState()
 
-				consensusState, found := suite.keeper.GetClientConsensusState(suite.ctx, clientID, updateHeader.GetHeight())
-				suite.Require().True(found, "valid test case %d failed: %s", i, tc.name)
+				consensusState, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientConsensusState(suite.chainA.GetContext(), path.EndpointA.ClientID, updateHeader.GetHeight())
+				suite.Require().True(found)
 
 				// Determine if clientState should be updated or not
 				if updateHeader.GetHeight().GT(clientState.GetLatestHeight()) {
@@ -202,10 +161,10 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
 					suite.Require().Equal(clientState.GetLatestHeight(), newClientState.GetLatestHeight(), "client state height updated for past header")
 				}
 
-				suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
+				suite.Require().NoError(err)
 				suite.Require().Equal(expConsensusState, consensusState, "consensus state should have been updated on case %s", tc.name)
 			} else {
-				suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
+				suite.Require().Error(err)
 			}
 		})
 	}
@@ -291,8 +250,10 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
 			expPass: false,
 		},
 		{
-			name: "client state frozen",
+			name: "client state is not active",
 			setup: func() {
+				// client is frozen
+
 				// last Height is at next block
 				lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
 
@@ -524,7 +485,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
 			false,
 		},
 		{
-			"client already frozen at earlier height",
+			"client already is not active - client is frozen",
 			&ibctmtypes.Misbehaviour{
 				Header1:  suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight), testClientHeight, altTime, bothValSet, bothValSet, bothSigners),
 				Header2:  suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight), testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners),
@@ -582,7 +543,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
 
 				clientState, found := suite.keeper.GetClientState(suite.ctx, clientID)
 				suite.Require().True(found, "valid test case %d failed: %s", i, tc.name)
-				suite.Require().True(clientState.IsFrozen(), "valid test case %d failed: %s", i, tc.name)
+				suite.Require().True(!clientState.(*ibctmtypes.ClientState).FrozenHeight.IsZero(), "valid test case %d failed: %s", i, tc.name)
 				suite.Require().Equal(tc.misbehaviour.GetHeight(), clientState.GetFrozenHeight(),
 					"valid test case %d failed: %s. Expected FrozenHeight %s got %s", tc.misbehaviour.GetHeight(), clientState.GetFrozenHeight())
 			} else {
diff --git a/modules/core/02-client/keeper/grpc_query.go b/modules/core/02-client/keeper/grpc_query.go
index 556ccad2fb7..4ebfadb5369 100644
--- a/modules/core/02-client/keeper/grpc_query.go
+++ b/modules/core/02-client/keeper/grpc_query.go
@@ -188,6 +188,33 @@ func (q Keeper) ConsensusStates(c context.Context, req *types.QueryConsensusStat
 	}, nil
 }
 
+// ClientStatus implements the Query/ClientStatus gRPC method
+func (q Keeper) ClientStatus(c context.Context, req *types.QueryClientStatusRequest) (*types.QueryClientStatusResponse, error) {
+	if req == nil {
+		return nil, status.Error(codes.InvalidArgument, "empty request")
+	}
+
+	if err := host.ClientIdentifierValidator(req.ClientId); err != nil {
+		return nil, status.Error(codes.InvalidArgument, err.Error())
+	}
+
+	ctx := sdk.UnwrapSDKContext(c)
+	clientState, found := q.GetClientState(ctx, req.ClientId)
+	if !found {
+		return nil, status.Error(
+			codes.NotFound,
+			sdkerrors.Wrap(types.ErrClientNotFound, req.ClientId).Error(),
+		)
+	}
+
+	clientStore := q.ClientStore(ctx, req.ClientId)
+	status := clientState.Status(ctx, clientStore, q.cdc)
+
+	return &types.QueryClientStatusResponse{
+		Status: status.String(),
+	}, nil
+}
+
 // ClientParams implements the Query/ClientParams gRPC method
 func (q Keeper) ClientParams(c context.Context, _ *types.QueryClientParamsRequest) (*types.QueryClientParamsResponse, error) {
 	ctx := sdk.UnwrapSDKContext(c)
diff --git a/modules/core/02-client/keeper/grpc_query_test.go b/modules/core/02-client/keeper/grpc_query_test.go
index b80fd57ff87..a2531c4dd62 100644
--- a/modules/core/02-client/keeper/grpc_query_test.go
+++ b/modules/core/02-client/keeper/grpc_query_test.go
@@ -28,6 +28,12 @@ func (suite *KeeperTestSuite) TestQueryClientState() {
 		malleate func()
 		expPass  bool
 	}{
+		{"req is nil",
+			func() {
+				req = nil
+			},
+			false,
+		},
 		{"invalid clientID",
 			func() {
 				req = &types.QueryClientStateRequest{}
@@ -45,15 +51,15 @@ func (suite *KeeperTestSuite) TestQueryClientState() {
 		{
 			"success",
 			func() {
-				clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
-				suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
+				path := ibctesting.NewPath(suite.chainA, suite.chainB)
+				suite.coordinator.SetupClients(path)
 
 				var err error
-				expClientState, err = types.PackClientState(clientState)
+				expClientState, err = types.PackClientState(path.EndpointA.GetClientState())
 				suite.Require().NoError(err)
 
 				req = &types.QueryClientStateRequest{
-					ClientId: testClientID,
+					ClientId: path.EndpointA.ClientID,
 				}
 			},
 			true,
@@ -65,8 +71,8 @@ func (suite *KeeperTestSuite) TestQueryClientState() {
 			suite.SetupTest() // reset
 
 			tc.malleate()
-			ctx := sdk.WrapSDKContext(suite.ctx)
-			res, err := suite.queryClient.ClientState(ctx, req)
+			ctx := sdk.WrapSDKContext(suite.chainA.GetContext())
+			res, err := suite.chainA.QueryServer.ClientState(ctx, req)
 
 			if tc.expPass {
 				suite.Require().NoError(err)
@@ -94,6 +100,12 @@ func (suite *KeeperTestSuite) TestQueryClientStates() {
 		malleate func()
 		expPass  bool
 	}{
+		{"req is nil",
+			func() {
+				req = nil
+			},
+			false,
+		},
 		{
 			"empty pagination",
 			func() {
@@ -179,6 +191,12 @@ func (suite *KeeperTestSuite) TestQueryConsensusState() {
 		malleate func()
 		expPass  bool
 	}{
+		{"req is nil",
+			func() {
+				req = nil
+			},
+			false,
+		},
 		{
 			"invalid clientID",
 			func() {
@@ -202,7 +220,7 @@ func (suite *KeeperTestSuite) TestQueryConsensusState() {
 			"consensus state not found",
 			func() {
 				req = &types.QueryConsensusStateRequest{
-					ClientId:     testClientID,
+					ClientId:     ibctesting.FirstClientID,
 					LatestHeight: true,
 				}
 			},
@@ -211,19 +229,16 @@ func (suite *KeeperTestSuite) TestQueryConsensusState() {
 		{
 			"success latest height",
 			func() {
-				clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
-				cs := ibctmtypes.NewConsensusState(
-					suite.consensusState.Timestamp, commitmenttypes.NewMerkleRoot([]byte("hash1")), nil,
-				)
-				suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
-				suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight, cs)
+				path := ibctesting.NewPath(suite.chainA, suite.chainB)
+				suite.coordinator.SetupClients(path)
+				cs := path.EndpointA.GetConsensusState(path.EndpointA.GetClientState().GetLatestHeight())
 
 				var err error
 				expConsensusState, err = types.PackConsensusState(cs)
 				suite.Require().NoError(err)
 
 				req = &types.QueryConsensusStateRequest{
-					ClientId:     testClientID,
+					ClientId:     path.EndpointA.ClientID,
 					LatestHeight: true,
 				}
 			},
@@ -232,19 +247,22 @@ func (suite *KeeperTestSuite) TestQueryConsensusState() {
 		{
 			"success with height",
 			func() {
-				cs := ibctmtypes.NewConsensusState(
-					suite.consensusState.Timestamp, commitmenttypes.NewMerkleRoot([]byte("hash1")), nil,
-				)
-				suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight, cs)
+				path := ibctesting.NewPath(suite.chainA, suite.chainB)
+				suite.coordinator.SetupClients(path)
+				height := path.EndpointA.GetClientState().GetLatestHeight()
+				cs := path.EndpointA.GetConsensusState(height)
 
 				var err error
 				expConsensusState, err = types.PackConsensusState(cs)
 				suite.Require().NoError(err)
 
+				// update client to new height
+				path.EndpointA.UpdateClient()
+
 				req = &types.QueryConsensusStateRequest{
-					ClientId:       testClientID,
-					RevisionNumber: 0,
-					RevisionHeight: height,
+					ClientId:       path.EndpointA.ClientID,
+					RevisionNumber: height.GetRevisionNumber(),
+					RevisionHeight: height.GetRevisionHeight(),
 				}
 			},
 			true,
@@ -256,8 +274,8 @@ func (suite *KeeperTestSuite) TestQueryConsensusState() {
 			suite.SetupTest() // reset
 
 			tc.malleate()
-			ctx := sdk.WrapSDKContext(suite.ctx)
-			res, err := suite.queryClient.ConsensusState(ctx, req)
+			ctx := sdk.WrapSDKContext(suite.chainA.GetContext())
+			res, err := suite.chainA.QueryServer.ConsensusState(ctx, req)
 
 			if tc.expPass {
 				suite.Require().NoError(err)
@@ -378,6 +396,102 @@ func (suite *KeeperTestSuite) TestQueryConsensusStates() {
 	}
 }
 
+func (suite *KeeperTestSuite) TestQueryClientStatus() {
+	var (
+		req *types.QueryClientStatusRequest
+	)
+
+	testCases := []struct {
+		msg       string
+		malleate  func()
+		expPass   bool
+		expStatus string
+	}{
+		{"req is nil",
+			func() {
+				req = nil
+			},
+			false, "",
+		},
+		{"invalid clientID",
+			func() {
+				req = &types.QueryClientStatusRequest{}
+			},
+			false, "",
+		},
+		{"client not found",
+			func() {
+				req = &types.QueryClientStatusRequest{
+					ClientId: ibctesting.InvalidID,
+				}
+			},
+			false, "",
+		},
+		{
+			"Active client status",
+			func() {
+				path := ibctesting.NewPath(suite.chainA, suite.chainB)
+				suite.coordinator.SetupClients(path)
+				req = &types.QueryClientStatusRequest{
+					ClientId: path.EndpointA.ClientID,
+				}
+			},
+			true, exported.Active.String(),
+		},
+		{
+			"Unknown client status",
+			func() {
+				path := ibctesting.NewPath(suite.chainA, suite.chainB)
+				suite.coordinator.SetupClients(path)
+				clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+
+				// increment latest height so no consensus state is stored
+				clientState.LatestHeight = clientState.LatestHeight.Increment().(types.Height)
+				path.EndpointA.SetClientState(clientState)
+
+				req = &types.QueryClientStatusRequest{
+					ClientId: path.EndpointA.ClientID,
+				}
+			},
+			true, exported.Unknown.String(),
+		},
+		{
+			"Frozen client status",
+			func() {
+				path := ibctesting.NewPath(suite.chainA, suite.chainB)
+				suite.coordinator.SetupClients(path)
+				clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+
+				clientState.FrozenHeight = types.NewHeight(0, 1)
+				path.EndpointA.SetClientState(clientState)
+
+				req = &types.QueryClientStatusRequest{
+					ClientId: path.EndpointA.ClientID,
+				}
+			},
+			true, exported.Frozen.String(),
+		},
+	}
+
+	for _, tc := range testCases {
+		suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
+			suite.SetupTest() // reset
+
+			tc.malleate()
+			ctx := sdk.WrapSDKContext(suite.chainA.GetContext())
+			res, err := suite.chainA.QueryServer.ClientStatus(ctx, req)
+
+			if tc.expPass {
+				suite.Require().NoError(err)
+				suite.Require().NotNil(res)
+				suite.Require().Equal(tc.expStatus, res.Status)
+			} else {
+				suite.Require().Error(err)
+			}
+		})
+	}
+}
+
 func (suite *KeeperTestSuite) TestQueryUpgradedConsensusStates() {
 	var (
 		req               *types.QueryUpgradedConsensusStateRequest
@@ -390,6 +504,12 @@ func (suite *KeeperTestSuite) TestQueryUpgradedConsensusStates() {
 		malleate func()
 		expPass  bool
 	}{
+		{"req is nil",
+			func() {
+				req = nil
+			},
+			false,
+		},
 		{
 			"no plan",
 			func() {
@@ -437,6 +557,6 @@ func (suite *KeeperTestSuite) TestQueryUpgradedConsensusStates() {
 func (suite *KeeperTestSuite) TestQueryParams() {
 	ctx := sdk.WrapSDKContext(suite.chainA.GetContext())
 	expParams := types.DefaultParams()
-	res, _ := suite.queryClient.ClientParams(ctx, &types.QueryClientParamsRequest{})
+	res, _ := suite.chainA.QueryServer.ClientParams(ctx, &types.QueryClientParamsRequest{})
 	suite.Require().Equal(&expParams, res.Params)
 }
diff --git a/modules/core/02-client/keeper/keeper.go b/modules/core/02-client/keeper/keeper.go
index aa3369bc7ac..d19360dc6ee 100644
--- a/modules/core/02-client/keeper/keeper.go
+++ b/modules/core/02-client/keeper/keeper.go
@@ -274,7 +274,7 @@ func (k Keeper) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientS
 			&ibctmtypes.ClientState{}, tmClient)
 	}
 
-	if clientState.IsFrozen() {
+	if !tmClient.FrozenHeight.IsZero() {
 		return types.ErrClientFrozen
 	}
 
diff --git a/modules/core/02-client/keeper/keeper_test.go b/modules/core/02-client/keeper/keeper_test.go
index d3e1cef5bcc..676967cbacf 100644
--- a/modules/core/02-client/keeper/keeper_test.go
+++ b/modules/core/02-client/keeper/keeper_test.go
@@ -66,6 +66,7 @@ type KeeperTestSuite struct {
 	now            time.Time
 	past           time.Time
 
+	// TODO: deprecate
 	queryClient types.QueryClient
 }
 
@@ -122,6 +123,7 @@ func (suite *KeeperTestSuite) SetupTest() {
 	)
 	suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), exported.Localhost, localHostClient)
 
+	// TODO: deprecate
 	queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, app.InterfaceRegistry())
 	types.RegisterQueryServer(queryHelper, app.IBCKeeper.ClientKeeper)
 	suite.queryClient = types.NewQueryClient(queryHelper)
diff --git a/modules/core/02-client/types/errors.go b/modules/core/02-client/types/errors.go
index 8a956f86873..c40bae878cc 100644
--- a/modules/core/02-client/types/errors.go
+++ b/modules/core/02-client/types/errors.go
@@ -33,4 +33,5 @@ var (
 	ErrInvalidHeight                          = sdkerrors.Register(SubModuleName, 26, "invalid height")
 	ErrInvalidSubstitute                      = sdkerrors.Register(SubModuleName, 27, "invalid client state substitute")
 	ErrInvalidUpgradeProposal                 = sdkerrors.Register(SubModuleName, 28, "invalid upgrade proposal")
+	ErrClientNotActive                        = sdkerrors.Register(SubModuleName, 29, "client is not active")
 )
diff --git a/modules/core/02-client/types/query.pb.go b/modules/core/02-client/types/query.pb.go
index 57908e13d13..0e62431265a 100644
--- a/modules/core/02-client/types/query.pb.go
+++ b/modules/core/02-client/types/query.pb.go
@@ -500,6 +500,99 @@ func (m *QueryConsensusStatesResponse) GetPagination() *query.PageResponse {
 	return nil
 }
 
+// QueryClientStatusRequest is the request type for the Query/ClientStatus RPC
+// method
+type QueryClientStatusRequest struct {
+	// client unique identifier
+	ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
+}
+
+func (m *QueryClientStatusRequest) Reset()         { *m = QueryClientStatusRequest{} }
+func (m *QueryClientStatusRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryClientStatusRequest) ProtoMessage()    {}
+func (*QueryClientStatusRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dc42cdfd1d52d76e, []int{8}
+}
+func (m *QueryClientStatusRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *QueryClientStatusRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_QueryClientStatusRequest.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *QueryClientStatusRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_QueryClientStatusRequest.Merge(m, src)
+}
+func (m *QueryClientStatusRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *QueryClientStatusRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_QueryClientStatusRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryClientStatusRequest proto.InternalMessageInfo
+
+func (m *QueryClientStatusRequest) GetClientId() string {
+	if m != nil {
+		return m.ClientId
+	}
+	return ""
+}
+
+// QueryClientStatusResponse is the response type for the Query/ClientStatus RPC
+// method. It returns the current status of the IBC client.
+type QueryClientStatusResponse struct {
+	Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
+}
+
+func (m *QueryClientStatusResponse) Reset()         { *m = QueryClientStatusResponse{} }
+func (m *QueryClientStatusResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryClientStatusResponse) ProtoMessage()    {}
+func (*QueryClientStatusResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dc42cdfd1d52d76e, []int{9}
+}
+func (m *QueryClientStatusResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *QueryClientStatusResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_QueryClientStatusResponse.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *QueryClientStatusResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_QueryClientStatusResponse.Merge(m, src)
+}
+func (m *QueryClientStatusResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *QueryClientStatusResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_QueryClientStatusResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryClientStatusResponse proto.InternalMessageInfo
+
+func (m *QueryClientStatusResponse) GetStatus() string {
+	if m != nil {
+		return m.Status
+	}
+	return ""
+}
+
 // QueryClientParamsRequest is the request type for the Query/ClientParams RPC
 // method.
 type QueryClientParamsRequest struct {
@@ -509,7 +602,7 @@ func (m *QueryClientParamsRequest) Reset()         { *m = QueryClientParamsReque
 func (m *QueryClientParamsRequest) String() string { return proto.CompactTextString(m) }
 func (*QueryClientParamsRequest) ProtoMessage()    {}
 func (*QueryClientParamsRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_dc42cdfd1d52d76e, []int{8}
+	return fileDescriptor_dc42cdfd1d52d76e, []int{10}
 }
 func (m *QueryClientParamsRequest) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -549,7 +642,7 @@ func (m *QueryClientParamsResponse) Reset()         { *m = QueryClientParamsResp
 func (m *QueryClientParamsResponse) String() string { return proto.CompactTextString(m) }
 func (*QueryClientParamsResponse) ProtoMessage()    {}
 func (*QueryClientParamsResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_dc42cdfd1d52d76e, []int{9}
+	return fileDescriptor_dc42cdfd1d52d76e, []int{11}
 }
 func (m *QueryClientParamsResponse) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -594,7 +687,7 @@ func (m *QueryUpgradedClientStateRequest) Reset()         { *m = QueryUpgradedCl
 func (m *QueryUpgradedClientStateRequest) String() string { return proto.CompactTextString(m) }
 func (*QueryUpgradedClientStateRequest) ProtoMessage()    {}
 func (*QueryUpgradedClientStateRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_dc42cdfd1d52d76e, []int{10}
+	return fileDescriptor_dc42cdfd1d52d76e, []int{12}
 }
 func (m *QueryUpgradedClientStateRequest) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -634,7 +727,7 @@ func (m *QueryUpgradedClientStateResponse) Reset()         { *m = QueryUpgradedC
 func (m *QueryUpgradedClientStateResponse) String() string { return proto.CompactTextString(m) }
 func (*QueryUpgradedClientStateResponse) ProtoMessage()    {}
 func (*QueryUpgradedClientStateResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_dc42cdfd1d52d76e, []int{11}
+	return fileDescriptor_dc42cdfd1d52d76e, []int{13}
 }
 func (m *QueryUpgradedClientStateResponse) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -679,7 +772,7 @@ func (m *QueryUpgradedConsensusStateRequest) Reset()         { *m = QueryUpgrade
 func (m *QueryUpgradedConsensusStateRequest) String() string { return proto.CompactTextString(m) }
 func (*QueryUpgradedConsensusStateRequest) ProtoMessage()    {}
 func (*QueryUpgradedConsensusStateRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_dc42cdfd1d52d76e, []int{12}
+	return fileDescriptor_dc42cdfd1d52d76e, []int{14}
 }
 func (m *QueryUpgradedConsensusStateRequest) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -719,7 +812,7 @@ func (m *QueryUpgradedConsensusStateResponse) Reset()         { *m = QueryUpgrad
 func (m *QueryUpgradedConsensusStateResponse) String() string { return proto.CompactTextString(m) }
 func (*QueryUpgradedConsensusStateResponse) ProtoMessage()    {}
 func (*QueryUpgradedConsensusStateResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_dc42cdfd1d52d76e, []int{13}
+	return fileDescriptor_dc42cdfd1d52d76e, []int{15}
 }
 func (m *QueryUpgradedConsensusStateResponse) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -764,6 +857,8 @@ func init() {
 	proto.RegisterType((*QueryConsensusStateResponse)(nil), "ibc.core.client.v1.QueryConsensusStateResponse")
 	proto.RegisterType((*QueryConsensusStatesRequest)(nil), "ibc.core.client.v1.QueryConsensusStatesRequest")
 	proto.RegisterType((*QueryConsensusStatesResponse)(nil), "ibc.core.client.v1.QueryConsensusStatesResponse")
+	proto.RegisterType((*QueryClientStatusRequest)(nil), "ibc.core.client.v1.QueryClientStatusRequest")
+	proto.RegisterType((*QueryClientStatusResponse)(nil), "ibc.core.client.v1.QueryClientStatusResponse")
 	proto.RegisterType((*QueryClientParamsRequest)(nil), "ibc.core.client.v1.QueryClientParamsRequest")
 	proto.RegisterType((*QueryClientParamsResponse)(nil), "ibc.core.client.v1.QueryClientParamsResponse")
 	proto.RegisterType((*QueryUpgradedClientStateRequest)(nil), "ibc.core.client.v1.QueryUpgradedClientStateRequest")
@@ -775,66 +870,69 @@ func init() {
 func init() { proto.RegisterFile("ibc/core/client/v1/query.proto", fileDescriptor_dc42cdfd1d52d76e) }
 
 var fileDescriptor_dc42cdfd1d52d76e = []byte{
-	// 942 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x57, 0xcf, 0x6f, 0xdc, 0x44,
-	0x14, 0xce, 0xa4, 0x69, 0xd5, 0xbc, 0xdd, 0x26, 0x68, 0x9a, 0xa6, 0x5b, 0xb7, 0x38, 0x5b, 0x07,
-	0xd1, 0xb4, 0x24, 0x9e, 0x64, 0x4b, 0x5b, 0x2e, 0x1c, 0x48, 0xa5, 0xd2, 0x5e, 0xda, 0x62, 0x84,
-	0x90, 0x90, 0x50, 0x64, 0x7b, 0x27, 0x8e, 0xa5, 0x5d, 0x8f, 0xeb, 0xb1, 0x23, 0x45, 0x55, 0x2e,
-	0x3d, 0x72, 0x42, 0x42, 0xe2, 0xca, 0x9d, 0x43, 0xc5, 0x01, 0x89, 0x2b, 0x27, 0xd4, 0x63, 0x25,
-	0x38, 0x70, 0x40, 0x04, 0x25, 0xfc, 0x21, 0xc8, 0x33, 0xe3, 0x8d, 0xbd, 0x3b, 0xcb, 0x7a, 0x11,
-	0xbd, 0x6d, 0xde, 0xcf, 0xef, 0x7d, 0xef, 0xcd, 0x67, 0x05, 0xcc, 0xd0, 0xf3, 0x89, 0xcf, 0x12,
-	0x4a, 0xfc, 0x5e, 0x48, 0xa3, 0x94, 0xec, 0x6f, 0x91, 0x67, 0x19, 0x4d, 0x0e, 0xec, 0x38, 0x61,
-	0x29, 0xc3, 0x38, 0xf4, 0x7c, 0x3b, 0xf7, 0xdb, 0xd2, 0x6f, 0xef, 0x6f, 0x19, 0xb7, 0x7c, 0xc6,
-	0xfb, 0x8c, 0x13, 0xcf, 0xe5, 0x54, 0x06, 0x93, 0xfd, 0x2d, 0x8f, 0xa6, 0xee, 0x16, 0x89, 0xdd,
-	0x20, 0x8c, 0xdc, 0x34, 0x64, 0x91, 0xcc, 0x37, 0x56, 0x34, 0xf5, 0x55, 0x25, 0x19, 0x70, 0x25,
-	0x60, 0x2c, 0xe8, 0x51, 0x22, 0xfe, 0xf2, 0xb2, 0x5d, 0xe2, 0x46, 0xaa, 0xb7, 0x71, 0x4d, 0xb9,
-	0xdc, 0x38, 0x24, 0x6e, 0x14, 0xb1, 0x54, 0x14, 0xe6, 0xca, 0xbb, 0x14, 0xb0, 0x80, 0x89, 0x9f,
-	0x24, 0xff, 0x25, 0xad, 0xd6, 0x5d, 0xb8, 0xfc, 0x49, 0x8e, 0xe8, 0xbe, 0xe8, 0xf1, 0x69, 0xea,
-	0xa6, 0xd4, 0xa1, 0xcf, 0x32, 0xca, 0x53, 0x7c, 0x15, 0xe6, 0x65, 0xe7, 0x9d, 0xb0, 0xdb, 0x42,
-	0x6d, 0xb4, 0x36, 0xef, 0x9c, 0x97, 0x86, 0x47, 0x5d, 0xeb, 0x25, 0x82, 0xd6, 0x68, 0x22, 0x8f,
-	0x59, 0xc4, 0x29, 0xbe, 0x07, 0x4d, 0x95, 0xc9, 0x73, 0xbb, 0x48, 0x6e, 0x74, 0x96, 0x6c, 0x89,
-	0xcf, 0x2e, 0xa0, 0xdb, 0x1f, 0x45, 0x07, 0x4e, 0xc3, 0x3f, 0x2d, 0x80, 0x97, 0xe0, 0x6c, 0x9c,
-	0x30, 0xb6, 0xdb, 0x9a, 0x6d, 0xa3, 0xb5, 0xa6, 0x23, 0xff, 0xc0, 0xf7, 0xa1, 0x29, 0x7e, 0xec,
-	0xec, 0xd1, 0x30, 0xd8, 0x4b, 0x5b, 0x67, 0x44, 0x39, 0xc3, 0x1e, 0xa5, 0xda, 0x7e, 0x28, 0x22,
-	0xb6, 0xe7, 0x5e, 0xfd, 0xb9, 0x32, 0xe3, 0x34, 0x44, 0x96, 0x34, 0x59, 0xde, 0x28, 0x5e, 0x5e,
-	0x4c, 0xfa, 0x00, 0xe0, 0x74, 0x11, 0x0a, 0xed, 0xbb, 0xb6, 0xdc, 0x9a, 0x9d, 0x6f, 0xcd, 0x96,
-	0x2b, 0x56, 0x5b, 0xb3, 0x9f, 0xba, 0x41, 0xc1, 0x92, 0x53, 0xca, 0xb4, 0x7e, 0x43, 0x70, 0x45,
-	0xd3, 0x44, 0xb1, 0x12, 0xc1, 0x85, 0x32, 0x2b, 0xbc, 0x85, 0xda, 0x67, 0xd6, 0x1a, 0x9d, 0x9b,
-	0xba, 0x39, 0x1e, 0x75, 0x69, 0x94, 0x86, 0xbb, 0x21, 0xed, 0x96, 0x4a, 0x6d, 0x9b, 0xf9, 0x58,
-	0xdf, 0x1f, 0xad, 0x2c, 0x6b, 0xdd, 0xdc, 0x69, 0x96, 0xb8, 0xe4, 0xf8, 0xe3, 0xca, 0x54, 0xb3,
-	0x62, 0xaa, 0x1b, 0x13, 0xa7, 0x92, 0x60, 0x2b, 0x63, 0xfd, 0x80, 0xc0, 0x90, 0x63, 0xe5, 0xae,
-	0x88, 0x67, 0xbc, 0xf6, 0x9d, 0xe0, 0x1b, 0xb0, 0x98, 0xd0, 0xfd, 0x90, 0x87, 0x2c, 0xda, 0x89,
-	0xb2, 0xbe, 0x47, 0x13, 0x81, 0x64, 0xce, 0x59, 0x28, 0xcc, 0x8f, 0x85, 0xb5, 0x12, 0x58, 0xda,
-	0x73, 0x29, 0x50, 0x2e, 0x12, 0xaf, 0xc2, 0x85, 0x5e, 0x3e, 0x5f, 0x5a, 0x84, 0xcd, 0xb5, 0xd1,
-	0xda, 0x79, 0xa7, 0x29, 0x8d, 0x6a, 0xdb, 0x3f, 0x21, 0xb8, 0xaa, 0x85, 0xac, 0x76, 0xf1, 0x21,
-	0x2c, 0xfa, 0x85, 0xa7, 0xc6, 0x91, 0x2e, 0xf8, 0x95, 0x32, 0x6f, 0xf2, 0x4e, 0x5f, 0xe8, 0x91,
-	0xf3, 0x5a, 0x6c, 0x3f, 0xd0, 0xac, 0xfc, 0xbf, 0x1c, 0xf2, 0x2f, 0x08, 0xae, 0xe9, 0x41, 0x28,
-	0xfe, 0xbe, 0x84, 0xb7, 0x86, 0xf8, 0x2b, 0xce, 0x79, 0x5d, 0x37, 0x6e, 0xb5, 0xcc, 0xe7, 0x61,
-	0xba, 0x57, 0x21, 0x60, 0xb1, 0x4a, 0xef, 0xff, 0x78, 0xba, 0x46, 0xe5, 0xd5, 0x3f, 0x75, 0x13,
-	0xb7, 0x5f, 0x30, 0x69, 0x3d, 0xa9, 0x3c, 0xd6, 0xc2, 0xa7, 0x06, 0xec, 0xc0, 0xb9, 0x58, 0x58,
-	0xd4, 0x5d, 0x68, 0xb7, 0xa8, 0x72, 0x54, 0xa4, 0x75, 0x1d, 0x56, 0x44, 0xc1, 0xcf, 0xe2, 0x20,
-	0x71, 0xbb, 0x95, 0xb7, 0x59, 0xf4, 0xec, 0x41, 0x7b, 0x7c, 0x88, 0x6a, 0xfd, 0x10, 0x2e, 0x65,
-	0xca, 0xbd, 0x53, 0x5b, 0x46, 0x2f, 0x66, 0xa3, 0x15, 0xad, 0x77, 0xc0, 0xaa, 0x76, 0xd3, 0xbd,
-	0x5f, 0x2b, 0x83, 0xd5, 0x7f, 0x8d, 0x52, 0xb0, 0x1e, 0x43, 0xeb, 0x14, 0xd6, 0x14, 0x6f, 0x67,
-	0x39, 0xd3, 0xd6, 0xed, 0xfc, 0x31, 0x0f, 0x67, 0x45, 0x5f, 0xfc, 0x1d, 0x82, 0x46, 0x09, 0x36,
-	0x7e, 0x4f, 0xc7, 0xf5, 0x98, 0xaf, 0x94, 0xb1, 0x5e, 0x2f, 0x58, 0x0e, 0x61, 0xdd, 0x79, 0xf1,
-	0xeb, 0xdf, 0xdf, 0xcc, 0x12, 0xbc, 0x41, 0xc6, 0x7e, 0x67, 0xd5, 0x39, 0x93, 0xe7, 0x83, 0x67,
-	0x76, 0x88, 0xbf, 0x45, 0xd0, 0x2c, 0x2b, 0x2d, 0xae, 0xd5, 0xb5, 0xb8, 0x34, 0x63, 0xa3, 0x66,
-	0xb4, 0x02, 0x79, 0x53, 0x80, 0x5c, 0xc5, 0xd7, 0x27, 0x82, 0xc4, 0x47, 0x08, 0x16, 0xaa, 0xbc,
-	0x62, 0x7b, 0x7c, 0x33, 0xdd, 0xfa, 0x0d, 0x52, 0x3b, 0x5e, 0xc1, 0xeb, 0x09, 0x78, 0xbb, 0xb8,
-	0xab, 0x85, 0x37, 0xa4, 0x0a, 0x65, 0x1a, 0x49, 0xa1, 0xe4, 0xe4, 0xf9, 0xd0, 0x37, 0xe1, 0x90,
-	0x48, 0xc9, 0x2c, 0x39, 0xa4, 0xe1, 0x10, 0xbf, 0x44, 0xb0, 0x38, 0xa4, 0x42, 0xb8, 0x2e, 0xe4,
-	0xc1, 0x02, 0x36, 0xeb, 0x27, 0xa8, 0x21, 0x3f, 0x10, 0x43, 0x76, 0xf0, 0xe6, 0xb4, 0x43, 0xe2,
-	0xaf, 0x06, 0xb7, 0x22, 0xe5, 0x61, 0xe2, 0xad, 0x54, 0x54, 0x69, 0xe2, 0xad, 0x54, 0x75, 0xca,
-	0x7a, 0x5b, 0xe0, 0xbc, 0x8c, 0x2f, 0x49, 0x9c, 0x03, 0x88, 0x52, 0x92, 0xf0, 0x8f, 0x08, 0x2e,
-	0x6a, 0xb4, 0x06, 0xdf, 0x1e, 0xdb, 0x65, 0xbc, 0x78, 0x19, 0xef, 0x4f, 0x97, 0xa4, 0x10, 0x76,
-	0x04, 0xc2, 0x75, 0x7c, 0x4b, 0xc7, 0xa4, 0x56, 0xe8, 0x38, 0xfe, 0x19, 0xc1, 0xb2, 0x5e, 0x8e,
-	0xf0, 0xdd, 0xc9, 0x20, 0xb4, 0x67, 0x7e, 0x6f, 0xea, 0xbc, 0x3a, 0x92, 0x31, 0x4e, 0x11, 0xf9,
-	0xf6, 0x93, 0x57, 0xc7, 0x26, 0x7a, 0x7d, 0x6c, 0xa2, 0xbf, 0x8e, 0x4d, 0xf4, 0xf5, 0x89, 0x39,
-	0xf3, 0xfa, 0xc4, 0x9c, 0xf9, 0xfd, 0xc4, 0x9c, 0xf9, 0xe2, 0x4e, 0x10, 0xa6, 0x7b, 0x99, 0x67,
-	0xfb, 0xac, 0x4f, 0xd4, 0x7f, 0x06, 0xa1, 0xe7, 0x6f, 0x04, 0x8c, 0xf4, 0x59, 0x37, 0xeb, 0x51,
-	0x2e, 0x9b, 0x6c, 0x76, 0x36, 0x54, 0x9f, 0xf4, 0x20, 0xa6, 0xdc, 0x3b, 0x27, 0x54, 0xf5, 0xf6,
-	0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xf6, 0x5d, 0xec, 0x67, 0x82, 0x0c, 0x00, 0x00,
+	// 981 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x57, 0xcd, 0x6f, 0x1b, 0x45,
+	0x14, 0xcf, 0xa4, 0x69, 0xd4, 0x3e, 0xbb, 0x09, 0x9a, 0xa6, 0xa9, 0xbb, 0x2d, 0x8e, 0xbb, 0x41,
+	0x34, 0x2d, 0xc9, 0x4e, 0xe2, 0xd0, 0x86, 0x0b, 0x07, 0x52, 0xa9, 0xb4, 0x97, 0xb6, 0x2c, 0x42,
+	0x48, 0x48, 0x28, 0xda, 0x5d, 0x4f, 0x36, 0x2b, 0xd9, 0x3b, 0xae, 0x67, 0x27, 0x52, 0x54, 0xe5,
+	0x40, 0x8f, 0x9c, 0x90, 0x90, 0xb8, 0x22, 0x71, 0xe4, 0x50, 0x71, 0x40, 0xe2, 0xca, 0x09, 0xf5,
+	0x58, 0x09, 0x0e, 0x9c, 0x08, 0x4a, 0xf8, 0x43, 0x90, 0x67, 0x66, 0xe3, 0x9d, 0x78, 0x8c, 0xd7,
+	0x08, 0x6e, 0x3b, 0xef, 0xf3, 0xf7, 0x3e, 0xe6, 0x37, 0x5a, 0xa8, 0x27, 0x61, 0x44, 0x22, 0xd6,
+	0xa3, 0x24, 0x6a, 0x27, 0x34, 0xcd, 0xc8, 0xfe, 0x06, 0x79, 0x26, 0x68, 0xef, 0xc0, 0xeb, 0xf6,
+	0x58, 0xc6, 0x30, 0x4e, 0xc2, 0xc8, 0xeb, 0xeb, 0x3d, 0xa5, 0xf7, 0xf6, 0x37, 0x9c, 0x3b, 0x11,
+	0xe3, 0x1d, 0xc6, 0x49, 0x18, 0x70, 0xaa, 0x8c, 0xc9, 0xfe, 0x46, 0x48, 0xb3, 0x60, 0x83, 0x74,
+	0x83, 0x38, 0x49, 0x83, 0x2c, 0x61, 0xa9, 0xf2, 0x77, 0x96, 0x2c, 0xf1, 0x75, 0x24, 0x65, 0x70,
+	0x2d, 0x66, 0x2c, 0x6e, 0x53, 0x22, 0x4f, 0xa1, 0xd8, 0x25, 0x41, 0xaa, 0x73, 0x3b, 0x37, 0xb4,
+	0x2a, 0xe8, 0x26, 0x24, 0x48, 0x53, 0x96, 0xc9, 0xc0, 0x5c, 0x6b, 0x17, 0x62, 0x16, 0x33, 0xf9,
+	0x49, 0xfa, 0x5f, 0x4a, 0xea, 0xde, 0x83, 0xab, 0x1f, 0xf5, 0x11, 0xdd, 0x97, 0x39, 0x3e, 0xce,
+	0x82, 0x8c, 0xfa, 0xf4, 0x99, 0xa0, 0x3c, 0xc3, 0xd7, 0xe1, 0xa2, 0xca, 0xbc, 0x93, 0xb4, 0x6a,
+	0xa8, 0x81, 0x56, 0x2e, 0xfa, 0x17, 0x94, 0xe0, 0x51, 0xcb, 0x7d, 0x89, 0xa0, 0x36, 0xec, 0xc8,
+	0xbb, 0x2c, 0xe5, 0x14, 0x6f, 0x41, 0x55, 0x7b, 0xf2, 0xbe, 0x5c, 0x3a, 0x57, 0x9a, 0x0b, 0x9e,
+	0xc2, 0xe7, 0xe5, 0xd0, 0xbd, 0x0f, 0xd2, 0x03, 0xbf, 0x12, 0x0d, 0x02, 0xe0, 0x05, 0x38, 0xdf,
+	0xed, 0x31, 0xb6, 0x5b, 0x9b, 0x6e, 0xa0, 0x95, 0xaa, 0xaf, 0x0e, 0xf8, 0x3e, 0x54, 0xe5, 0xc7,
+	0xce, 0x1e, 0x4d, 0xe2, 0xbd, 0xac, 0x76, 0x4e, 0x86, 0x73, 0xbc, 0xe1, 0x56, 0x7b, 0x0f, 0xa5,
+	0xc5, 0xf6, 0xcc, 0xab, 0x3f, 0x96, 0xa6, 0xfc, 0x8a, 0xf4, 0x52, 0x22, 0x37, 0x1c, 0xc6, 0xcb,
+	0xf3, 0x4a, 0x1f, 0x00, 0x0c, 0x06, 0xa1, 0xd1, 0xbe, 0xed, 0xa9, 0xa9, 0x79, 0xfd, 0xa9, 0x79,
+	0x6a, 0xc4, 0x7a, 0x6a, 0xde, 0xd3, 0x20, 0xce, 0xbb, 0xe4, 0x17, 0x3c, 0xdd, 0xdf, 0x10, 0x5c,
+	0xb3, 0x24, 0xd1, 0x5d, 0x49, 0xe1, 0x52, 0xb1, 0x2b, 0xbc, 0x86, 0x1a, 0xe7, 0x56, 0x2a, 0xcd,
+	0xdb, 0xb6, 0x3a, 0x1e, 0xb5, 0x68, 0x9a, 0x25, 0xbb, 0x09, 0x6d, 0x15, 0x42, 0x6d, 0xd7, 0xfb,
+	0x65, 0x7d, 0x7f, 0xb4, 0xb4, 0x68, 0x55, 0x73, 0xbf, 0x5a, 0xe8, 0x25, 0xc7, 0x1f, 0x1a, 0x55,
+	0x4d, 0xcb, 0xaa, 0x6e, 0x8d, 0xad, 0x4a, 0x81, 0x35, 0xca, 0xfa, 0x01, 0x81, 0xa3, 0xca, 0xea,
+	0xab, 0x52, 0x2e, 0x78, 0xe9, 0x3d, 0xc1, 0xb7, 0x60, 0xbe, 0x47, 0xf7, 0x13, 0x9e, 0xb0, 0x74,
+	0x27, 0x15, 0x9d, 0x90, 0xf6, 0x24, 0x92, 0x19, 0x7f, 0x2e, 0x17, 0x3f, 0x96, 0x52, 0xc3, 0xb0,
+	0x30, 0xe7, 0x82, 0xa1, 0x1a, 0x24, 0x5e, 0x86, 0x4b, 0xed, 0x7e, 0x7d, 0x59, 0x6e, 0x36, 0xd3,
+	0x40, 0x2b, 0x17, 0xfc, 0xaa, 0x12, 0xea, 0x69, 0xff, 0x84, 0xe0, 0xba, 0x15, 0xb2, 0x9e, 0xc5,
+	0xfb, 0x30, 0x1f, 0xe5, 0x9a, 0x12, 0x4b, 0x3a, 0x17, 0x19, 0x61, 0xfe, 0xcf, 0x3d, 0x7d, 0x61,
+	0x47, 0xce, 0x4b, 0x75, 0xfb, 0x81, 0x65, 0xe4, 0xff, 0x66, 0x91, 0x7f, 0x41, 0x70, 0xc3, 0x0e,
+	0x42, 0xf7, 0xef, 0x73, 0x78, 0xe3, 0x4c, 0xff, 0xf2, 0x75, 0x5e, 0xb5, 0x95, 0x6b, 0x86, 0xf9,
+	0x34, 0xc9, 0xf6, 0x8c, 0x06, 0xcc, 0x9b, 0xed, 0xfd, 0x0f, 0x57, 0x77, 0x6b, 0xe8, 0xd6, 0x8b,
+	0x52, 0x9d, 0x74, 0x37, 0x87, 0x6e, 0xb2, 0x18, 0x54, 0xbf, 0x08, 0xb3, 0x5c, 0x4a, 0xb4, 0x9b,
+	0x3e, 0xb9, 0x8e, 0x91, 0xed, 0x69, 0xd0, 0x0b, 0x3a, 0x79, 0x36, 0xf7, 0x89, 0x11, 0x30, 0xd7,
+	0xe9, 0x80, 0x4d, 0x98, 0xed, 0x4a, 0x89, 0xde, 0x42, 0xeb, 0xce, 0x68, 0x1f, 0x6d, 0xe9, 0xde,
+	0x84, 0x25, 0x19, 0xf0, 0x93, 0x6e, 0xdc, 0x0b, 0x5a, 0x06, 0x13, 0xe4, 0x39, 0xdb, 0xd0, 0x18,
+	0x6d, 0xa2, 0x53, 0x3f, 0x84, 0x2b, 0x42, 0xab, 0x77, 0x4a, 0x93, 0xf6, 0x65, 0x31, 0x1c, 0xd1,
+	0x7d, 0x0b, 0x5c, 0x33, 0x9b, 0x8d, 0x2d, 0x5c, 0x01, 0xcb, 0xff, 0x68, 0xa5, 0x61, 0x3d, 0x86,
+	0xda, 0x00, 0xd6, 0x04, 0x37, 0x75, 0x51, 0x58, 0xe3, 0x36, 0xbf, 0xa8, 0xc0, 0x79, 0x99, 0x17,
+	0x7f, 0x8b, 0xa0, 0x52, 0x80, 0x8d, 0xdf, 0xb1, 0xf5, 0x7a, 0xc4, 0x9b, 0xe8, 0xac, 0x96, 0x33,
+	0x56, 0x45, 0xb8, 0x77, 0x5f, 0xfc, 0xfa, 0xd7, 0xd7, 0xd3, 0x04, 0xaf, 0x91, 0x91, 0xaf, 0xba,
+	0xbe, 0x3c, 0xe4, 0xf9, 0xe9, 0x2a, 0x1e, 0xe2, 0x6f, 0x10, 0x54, 0x8b, 0xbc, 0x8e, 0x4b, 0x65,
+	0xcd, 0x37, 0xcd, 0x59, 0x2b, 0x69, 0xad, 0x41, 0xde, 0x96, 0x20, 0x97, 0xf1, 0xcd, 0xb1, 0x20,
+	0xf1, 0x11, 0x82, 0x39, 0xb3, 0xaf, 0xd8, 0x1b, 0x9d, 0xcc, 0x36, 0x7e, 0x87, 0x94, 0xb6, 0xd7,
+	0xf0, 0xda, 0x12, 0xde, 0x2e, 0x6e, 0x59, 0xe1, 0x9d, 0xe1, 0xa0, 0x62, 0x1b, 0x49, 0xfe, 0x6e,
+	0x90, 0xe7, 0x67, 0x5e, 0xa0, 0x43, 0xa2, 0x08, 0xba, 0xa0, 0x50, 0x82, 0x43, 0xfc, 0x12, 0xc1,
+	0xfc, 0x19, 0xce, 0xc3, 0x65, 0x21, 0x9f, 0x0e, 0x60, 0xbd, 0xbc, 0x83, 0x2e, 0xf2, 0x3d, 0x59,
+	0x64, 0x13, 0xaf, 0x4f, 0x5a, 0x24, 0xfe, 0xce, 0xd8, 0x15, 0x51, 0x6e, 0x57, 0xc4, 0x44, 0xbb,
+	0x32, 0x20, 0xbe, 0xd2, 0x0b, 0x2d, 0x4c, 0x90, 0x5f, 0x9e, 0x82, 0x54, 0x1c, 0x36, 0x16, 0xa4,
+	0x41, 0x9d, 0x63, 0x41, 0x9a, 0x64, 0xea, 0xbe, 0x29, 0x41, 0x5e, 0xc5, 0x57, 0x14, 0xc8, 0x53,
+	0x7c, 0x8a, 0x37, 0xf1, 0x8f, 0x08, 0x2e, 0x5b, 0x08, 0x11, 0x6f, 0x8e, 0xcc, 0x32, 0x9a, 0x61,
+	0x9d, 0x77, 0x27, 0x73, 0xd2, 0x08, 0x9b, 0x12, 0xe1, 0x2a, 0xbe, 0x63, 0x6b, 0xa3, 0x95, 0x8d,
+	0x39, 0xfe, 0x19, 0xc1, 0xa2, 0x9d, 0x33, 0xf1, 0xbd, 0xf1, 0x20, 0xac, 0x77, 0x71, 0x6b, 0x62,
+	0xbf, 0x32, 0x6b, 0x30, 0x8a, 0xb6, 0xf9, 0xf6, 0x93, 0x57, 0xc7, 0x75, 0xf4, 0xfa, 0xb8, 0x8e,
+	0xfe, 0x3c, 0xae, 0xa3, 0xaf, 0x4e, 0xea, 0x53, 0xaf, 0x4f, 0xea, 0x53, 0xbf, 0x9f, 0xd4, 0xa7,
+	0x3e, 0xbb, 0x1b, 0x27, 0xd9, 0x9e, 0x08, 0xbd, 0x88, 0x75, 0x88, 0xfe, 0x59, 0x4a, 0xc2, 0x68,
+	0x2d, 0x66, 0xa4, 0xc3, 0x5a, 0xa2, 0x4d, 0xb9, 0x4a, 0xb2, 0xde, 0x5c, 0xd3, 0x79, 0xb2, 0x83,
+	0x2e, 0xe5, 0xe1, 0xac, 0xa4, 0xfe, 0xcd, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x50, 0xa9, 0x40,
+	0x56, 0x95, 0x0d, 0x00, 0x00,
 }
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -859,6 +957,8 @@ type QueryClient interface {
 	// ConsensusStates queries all the consensus state associated with a given
 	// client.
 	ConsensusStates(ctx context.Context, in *QueryConsensusStatesRequest, opts ...grpc.CallOption) (*QueryConsensusStatesResponse, error)
+	// Status queries the status of an IBC client.
+	ClientStatus(ctx context.Context, in *QueryClientStatusRequest, opts ...grpc.CallOption) (*QueryClientStatusResponse, error)
 	// ClientParams queries all parameters of the ibc client.
 	ClientParams(ctx context.Context, in *QueryClientParamsRequest, opts ...grpc.CallOption) (*QueryClientParamsResponse, error)
 	// UpgradedClientState queries an Upgraded IBC light client.
@@ -911,6 +1011,15 @@ func (c *queryClient) ConsensusStates(ctx context.Context, in *QueryConsensusSta
 	return out, nil
 }
 
+func (c *queryClient) ClientStatus(ctx context.Context, in *QueryClientStatusRequest, opts ...grpc.CallOption) (*QueryClientStatusResponse, error) {
+	out := new(QueryClientStatusResponse)
+	err := c.cc.Invoke(ctx, "/ibc.core.client.v1.Query/ClientStatus", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 func (c *queryClient) ClientParams(ctx context.Context, in *QueryClientParamsRequest, opts ...grpc.CallOption) (*QueryClientParamsResponse, error) {
 	out := new(QueryClientParamsResponse)
 	err := c.cc.Invoke(ctx, "/ibc.core.client.v1.Query/ClientParams", in, out, opts...)
@@ -950,6 +1059,8 @@ type QueryServer interface {
 	// ConsensusStates queries all the consensus state associated with a given
 	// client.
 	ConsensusStates(context.Context, *QueryConsensusStatesRequest) (*QueryConsensusStatesResponse, error)
+	// Status queries the status of an IBC client.
+	ClientStatus(context.Context, *QueryClientStatusRequest) (*QueryClientStatusResponse, error)
 	// ClientParams queries all parameters of the ibc client.
 	ClientParams(context.Context, *QueryClientParamsRequest) (*QueryClientParamsResponse, error)
 	// UpgradedClientState queries an Upgraded IBC light client.
@@ -974,6 +1085,9 @@ func (*UnimplementedQueryServer) ConsensusState(ctx context.Context, req *QueryC
 func (*UnimplementedQueryServer) ConsensusStates(ctx context.Context, req *QueryConsensusStatesRequest) (*QueryConsensusStatesResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method ConsensusStates not implemented")
 }
+func (*UnimplementedQueryServer) ClientStatus(ctx context.Context, req *QueryClientStatusRequest) (*QueryClientStatusResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method ClientStatus not implemented")
+}
 func (*UnimplementedQueryServer) ClientParams(ctx context.Context, req *QueryClientParamsRequest) (*QueryClientParamsResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method ClientParams not implemented")
 }
@@ -1060,6 +1174,24 @@ func _Query_ConsensusStates_Handler(srv interface{}, ctx context.Context, dec fu
 	return interceptor(ctx, in, info, handler)
 }
 
+func _Query_ClientStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(QueryClientStatusRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(QueryServer).ClientStatus(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/ibc.core.client.v1.Query/ClientStatus",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(QueryServer).ClientStatus(ctx, req.(*QueryClientStatusRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 func _Query_ClientParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
 	in := new(QueryClientParamsRequest)
 	if err := dec(in); err != nil {
@@ -1134,6 +1266,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{
 			MethodName: "ConsensusStates",
 			Handler:    _Query_ConsensusStates_Handler,
 		},
+		{
+			MethodName: "ClientStatus",
+			Handler:    _Query_ClientStatus_Handler,
+		},
 		{
 			MethodName: "ClientParams",
 			Handler:    _Query_ClientParams_Handler,
@@ -1510,6 +1646,66 @@ func (m *QueryConsensusStatesResponse) MarshalToSizedBuffer(dAtA []byte) (int, e
 	return len(dAtA) - i, nil
 }
 
+func (m *QueryClientStatusRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *QueryClientStatusRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryClientStatusRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.ClientId) > 0 {
+		i -= len(m.ClientId)
+		copy(dAtA[i:], m.ClientId)
+		i = encodeVarintQuery(dAtA, i, uint64(len(m.ClientId)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *QueryClientStatusResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *QueryClientStatusResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryClientStatusResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.Status) > 0 {
+		i -= len(m.Status)
+		copy(dAtA[i:], m.Status)
+		i = encodeVarintQuery(dAtA, i, uint64(len(m.Status)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
 func (m *QueryClientParamsRequest) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
@@ -1836,6 +2032,32 @@ func (m *QueryConsensusStatesResponse) Size() (n int) {
 	return n
 }
 
+func (m *QueryClientStatusRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.ClientId)
+	if l > 0 {
+		n += 1 + l + sovQuery(uint64(l))
+	}
+	return n
+}
+
+func (m *QueryClientStatusResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Status)
+	if l > 0 {
+		n += 1 + l + sovQuery(uint64(l))
+	}
+	return n
+}
+
 func (m *QueryClientParamsRequest) Size() (n int) {
 	if m == nil {
 		return 0
@@ -2880,6 +3102,170 @@ func (m *QueryConsensusStatesResponse) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
+func (m *QueryClientStatusRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowQuery
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: QueryClientStatusRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: QueryClientStatusRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ClientId", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowQuery
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthQuery
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthQuery
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.ClientId = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipQuery(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthQuery
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *QueryClientStatusResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowQuery
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: QueryClientStatusResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: QueryClientStatusResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowQuery
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthQuery
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthQuery
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Status = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipQuery(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthQuery
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func (m *QueryClientParamsRequest) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
diff --git a/modules/core/02-client/types/query.pb.gw.go b/modules/core/02-client/types/query.pb.gw.go
index ed3df357a0c..3704fb07895 100644
--- a/modules/core/02-client/types/query.pb.gw.go
+++ b/modules/core/02-client/types/query.pb.gw.go
@@ -309,6 +309,60 @@ func local_request_Query_ConsensusStates_0(ctx context.Context, marshaler runtim
 
 }
 
+func request_Query_ClientStatus_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var protoReq QueryClientStatusRequest
+	var metadata runtime.ServerMetadata
+
+	var (
+		val string
+		ok  bool
+		err error
+		_   = err
+	)
+
+	val, ok = pathParams["client_id"]
+	if !ok {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "client_id")
+	}
+
+	protoReq.ClientId, err = runtime.String(val)
+
+	if err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "client_id", err)
+	}
+
+	msg, err := client.ClientStatus(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+	return msg, metadata, err
+
+}
+
+func local_request_Query_ClientStatus_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var protoReq QueryClientStatusRequest
+	var metadata runtime.ServerMetadata
+
+	var (
+		val string
+		ok  bool
+		err error
+		_   = err
+	)
+
+	val, ok = pathParams["client_id"]
+	if !ok {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "client_id")
+	}
+
+	protoReq.ClientId, err = runtime.String(val)
+
+	if err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "client_id", err)
+	}
+
+	msg, err := server.ClientStatus(ctx, &protoReq)
+	return msg, metadata, err
+
+}
+
 func request_Query_ClientParams_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
 	var protoReq QueryClientParamsRequest
 	var metadata runtime.ServerMetadata
@@ -449,6 +503,26 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
 
 	})
 
+	mux.Handle("GET", pattern_Query_ClientStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+		ctx, cancel := context.WithCancel(req.Context())
+		defer cancel()
+		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+		rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		resp, md, err := local_request_Query_ClientStatus_0(rctx, inboundMarshaler, server, req, pathParams)
+		ctx = runtime.NewServerMetadataContext(ctx, md)
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+
+		forward_Query_ClientStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+	})
+
 	mux.Handle("GET", pattern_Query_ClientParams_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
@@ -630,6 +704,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
 
 	})
 
+	mux.Handle("GET", pattern_Query_ClientStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+		ctx, cancel := context.WithCancel(req.Context())
+		defer cancel()
+		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+		rctx, err := runtime.AnnotateContext(ctx, mux, req)
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		resp, md, err := request_Query_ClientStatus_0(rctx, inboundMarshaler, client, req, pathParams)
+		ctx = runtime.NewServerMetadataContext(ctx, md)
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+
+		forward_Query_ClientStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+	})
+
 	mux.Handle("GET", pattern_Query_ClientParams_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
@@ -702,6 +796,8 @@ var (
 
 	pattern_Query_ConsensusStates_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "client", "v1", "consensus_states", "client_id"}, "", runtime.AssumeColonVerbOpt(true)))
 
+	pattern_Query_ClientStatus_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "client", "v1", "client_status", "client_id"}, "", runtime.AssumeColonVerbOpt(true)))
+
 	pattern_Query_ClientParams_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"ibc", "client", "v1", "params"}, "", runtime.AssumeColonVerbOpt(true)))
 
 	pattern_Query_UpgradedClientState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "core", "client", "v1", "upgraded_client_states"}, "", runtime.AssumeColonVerbOpt(true)))
@@ -718,6 +814,8 @@ var (
 
 	forward_Query_ConsensusStates_0 = runtime.ForwardResponseMessage
 
+	forward_Query_ClientStatus_0 = runtime.ForwardResponseMessage
+
 	forward_Query_ClientParams_0 = runtime.ForwardResponseMessage
 
 	forward_Query_UpgradedClientState_0 = runtime.ForwardResponseMessage
diff --git a/modules/core/03-connection/keeper/verify.go b/modules/core/03-connection/keeper/verify.go
index 9355d4eff6b..38722f98958 100644
--- a/modules/core/03-connection/keeper/verify.go
+++ b/modules/core/03-connection/keeper/verify.go
@@ -17,15 +17,21 @@ func (k Keeper) VerifyClientState(
 	clientState exported.ClientState,
 ) error {
 	clientID := connection.GetClientID()
+	clientStore := k.clientKeeper.ClientStore(ctx, clientID)
+
 	targetClient, found := k.clientKeeper.GetClientState(ctx, clientID)
 	if !found {
 		return sdkerrors.Wrap(clienttypes.ErrClientNotFound, clientID)
 	}
 
+	if status := targetClient.Status(ctx, clientStore, k.cdc); status != exported.Active {
+		return sdkerrors.Wrapf(clienttypes.ErrClientNotActive, "client (%s) status is %s", clientID, status)
+	}
+
 	if err := targetClient.VerifyClientState(
-		k.clientKeeper.ClientStore(ctx, clientID), k.cdc, height,
+		clientStore, k.cdc, 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 sdkerrors.Wrapf(err, "failed client state verification for target client: %s", clientID)
 	}
 
 	return nil
@@ -42,16 +48,22 @@ func (k Keeper) VerifyClientConsensusState(
 	consensusState exported.ConsensusState,
 ) error {
 	clientID := connection.GetClientID()
+	clientStore := k.clientKeeper.ClientStore(ctx, clientID)
+
 	clientState, found := k.clientKeeper.GetClientState(ctx, clientID)
 	if !found {
 		return sdkerrors.Wrap(clienttypes.ErrClientNotFound, clientID)
 	}
 
+	if status := clientState.Status(ctx, clientStore, k.cdc); status != exported.Active {
+		return sdkerrors.Wrapf(clienttypes.ErrClientNotActive, "client (%s) status is %s", clientID, status)
+	}
+
 	if err := clientState.VerifyClientConsensusState(
-		k.clientKeeper.ClientStore(ctx, clientID), k.cdc, height,
+		clientStore, k.cdc, height,
 		connection.GetCounterparty().GetClientID(), consensusHeight, connection.GetCounterparty().GetPrefix(), proof, consensusState,
 	); err != nil {
-		return sdkerrors.Wrapf(err, "failed consensus state verification for client (%s)", connection.GetClientID())
+		return sdkerrors.Wrapf(err, "failed consensus state verification for client (%s)", clientID)
 	}
 
 	return nil
@@ -67,16 +79,23 @@ func (k Keeper) VerifyConnectionState(
 	connectionID string,
 	connectionEnd exported.ConnectionI, // opposite connection
 ) error {
-	clientState, found := k.clientKeeper.GetClientState(ctx, connection.GetClientID())
+	clientID := connection.GetClientID()
+	clientStore := k.clientKeeper.ClientStore(ctx, clientID)
+
+	clientState, found := k.clientKeeper.GetClientState(ctx, clientID)
 	if !found {
-		return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
+		return sdkerrors.Wrap(clienttypes.ErrClientNotFound, clientID)
+	}
+
+	if status := clientState.Status(ctx, clientStore, k.cdc); status != exported.Active {
+		return sdkerrors.Wrapf(clienttypes.ErrClientNotActive, "client (%s) status is %s", clientID, status)
 	}
 
 	if err := clientState.VerifyConnectionState(
-		k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
+		clientStore, k.cdc, height,
 		connection.GetCounterparty().GetPrefix(), proof, connectionID, connectionEnd,
 	); err != nil {
-		return sdkerrors.Wrapf(err, "failed connection state verification for client (%s)", connection.GetClientID())
+		return sdkerrors.Wrapf(err, "failed connection state verification for client (%s)", clientID)
 	}
 
 	return nil
@@ -93,17 +112,24 @@ func (k Keeper) VerifyChannelState(
 	channelID string,
 	channel exported.ChannelI,
 ) error {
-	clientState, found := k.clientKeeper.GetClientState(ctx, connection.GetClientID())
+	clientID := connection.GetClientID()
+	clientStore := k.clientKeeper.ClientStore(ctx, clientID)
+
+	clientState, found := k.clientKeeper.GetClientState(ctx, clientID)
 	if !found {
-		return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
+		return sdkerrors.Wrap(clienttypes.ErrClientNotFound, clientID)
+	}
+
+	if status := clientState.Status(ctx, clientStore, k.cdc); status != exported.Active {
+		return sdkerrors.Wrapf(clienttypes.ErrClientNotActive, "client (%s) status is %s", clientID, status)
 	}
 
 	if err := clientState.VerifyChannelState(
-		k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
+		clientStore, k.cdc, height,
 		connection.GetCounterparty().GetPrefix(), proof,
 		portID, channelID, channel,
 	); err != nil {
-		return sdkerrors.Wrapf(err, "failed channel state verification for client (%s)", connection.GetClientID())
+		return sdkerrors.Wrapf(err, "failed channel state verification for client (%s)", clientID)
 	}
 
 	return nil
@@ -121,18 +147,25 @@ func (k Keeper) VerifyPacketCommitment(
 	sequence uint64,
 	commitmentBytes []byte,
 ) error {
-	clientState, found := k.clientKeeper.GetClientState(ctx, connection.GetClientID())
+	clientID := connection.GetClientID()
+	clientStore := k.clientKeeper.ClientStore(ctx, clientID)
+
+	clientState, found := k.clientKeeper.GetClientState(ctx, clientID)
 	if !found {
-		return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
+		return sdkerrors.Wrap(clienttypes.ErrClientNotFound, clientID)
+	}
+
+	if status := clientState.Status(ctx, clientStore, k.cdc); status != exported.Active {
+		return sdkerrors.Wrapf(clienttypes.ErrClientNotActive, "client (%s) status is %s", clientID, status)
 	}
 
 	if err := clientState.VerifyPacketCommitment(
-		k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
+		clientStore, k.cdc, height,
 		uint64(ctx.BlockTime().UnixNano()), connection.GetDelayPeriod(),
 		connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
 		sequence, commitmentBytes,
 	); err != nil {
-		return sdkerrors.Wrapf(err, "failed packet commitment verification for client (%s)", connection.GetClientID())
+		return sdkerrors.Wrapf(err, "failed packet commitment verification for client (%s)", clientID)
 	}
 
 	return nil
@@ -150,18 +183,25 @@ func (k Keeper) VerifyPacketAcknowledgement(
 	sequence uint64,
 	acknowledgement []byte,
 ) error {
-	clientState, found := k.clientKeeper.GetClientState(ctx, connection.GetClientID())
+	clientID := connection.GetClientID()
+	clientStore := k.clientKeeper.ClientStore(ctx, clientID)
+
+	clientState, found := k.clientKeeper.GetClientState(ctx, clientID)
 	if !found {
-		return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
+		return sdkerrors.Wrap(clienttypes.ErrClientNotFound, clientID)
+	}
+
+	if status := clientState.Status(ctx, clientStore, k.cdc); status != exported.Active {
+		return sdkerrors.Wrapf(clienttypes.ErrClientNotActive, "client (%s) status is %s", clientID, status)
 	}
 
 	if err := clientState.VerifyPacketAcknowledgement(
-		k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
+		clientStore, k.cdc, height,
 		uint64(ctx.BlockTime().UnixNano()), connection.GetDelayPeriod(),
 		connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
 		sequence, acknowledgement,
 	); err != nil {
-		return sdkerrors.Wrapf(err, "failed packet acknowledgement verification for client (%s)", connection.GetClientID())
+		return sdkerrors.Wrapf(err, "failed packet acknowledgement verification for client (%s)", clientID)
 	}
 
 	return nil
@@ -179,18 +219,25 @@ func (k Keeper) VerifyPacketReceiptAbsence(
 	channelID string,
 	sequence uint64,
 ) error {
-	clientState, found := k.clientKeeper.GetClientState(ctx, connection.GetClientID())
+	clientID := connection.GetClientID()
+	clientStore := k.clientKeeper.ClientStore(ctx, clientID)
+
+	clientState, found := k.clientKeeper.GetClientState(ctx, clientID)
 	if !found {
-		return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
+		return sdkerrors.Wrap(clienttypes.ErrClientNotFound, clientID)
+	}
+
+	if status := clientState.Status(ctx, clientStore, k.cdc); status != exported.Active {
+		return sdkerrors.Wrapf(clienttypes.ErrClientNotActive, "client (%s) status is %s", clientID, status)
 	}
 
 	if err := clientState.VerifyPacketReceiptAbsence(
-		k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
+		clientStore, k.cdc, height,
 		uint64(ctx.BlockTime().UnixNano()), connection.GetDelayPeriod(),
 		connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
 		sequence,
 	); err != nil {
-		return sdkerrors.Wrapf(err, "failed packet receipt absence verification for client (%s)", connection.GetClientID())
+		return sdkerrors.Wrapf(err, "failed packet receipt absence verification for client (%s)", clientID)
 	}
 
 	return nil
@@ -207,18 +254,25 @@ func (k Keeper) VerifyNextSequenceRecv(
 	channelID string,
 	nextSequenceRecv uint64,
 ) error {
-	clientState, found := k.clientKeeper.GetClientState(ctx, connection.GetClientID())
+	clientID := connection.GetClientID()
+	clientStore := k.clientKeeper.ClientStore(ctx, clientID)
+
+	clientState, found := k.clientKeeper.GetClientState(ctx, clientID)
 	if !found {
-		return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
+		return sdkerrors.Wrap(clienttypes.ErrClientNotFound, clientID)
+	}
+
+	if status := clientState.Status(ctx, clientStore, k.cdc); status != exported.Active {
+		return sdkerrors.Wrapf(clienttypes.ErrClientNotActive, "client (%s) status is %s", clientID, status)
 	}
 
 	if err := clientState.VerifyNextSequenceRecv(
-		k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
+		clientStore, k.cdc, height,
 		uint64(ctx.BlockTime().UnixNano()), connection.GetDelayPeriod(),
 		connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
 		nextSequenceRecv,
 	); err != nil {
-		return sdkerrors.Wrapf(err, "failed next sequence receive verification for client (%s)", connection.GetClientID())
+		return sdkerrors.Wrapf(err, "failed next sequence receive verification for client (%s)", clientID)
 	}
 
 	return nil
diff --git a/modules/core/03-connection/keeper/verify_test.go b/modules/core/03-connection/keeper/verify_test.go
index 2c63ea97a03..f57953feff6 100644
--- a/modules/core/03-connection/keeper/verify_test.go
+++ b/modules/core/03-connection/keeper/verify_test.go
@@ -19,44 +19,56 @@ var defaultTimeoutHeight = clienttypes.NewHeight(0, 100000)
 // TestVerifyClientState verifies a client state of chainA
 // stored on path.EndpointB (which is on chainB)
 func (suite *KeeperTestSuite) TestVerifyClientState() {
+	var (
+		path       *ibctesting.Path
+		heightDiff uint64
+	)
 	cases := []struct {
-		msg                  string
-		changeClientID       bool
-		heightDiff           uint64
-		malleateCounterparty bool
-		expPass              bool
+		name     string
+		malleate func()
+		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},
+		{"verification success", func() {}, true},
+		{"client state not found", func() {
+			connection := path.EndpointA.GetConnection()
+			connection.ClientId = ibctesting.InvalidID
+			path.EndpointA.SetConnection(connection)
+		}, false},
+		{"consensus state for proof height not found", func() {
+			heightDiff = 5
+		}, false},
+		{"verification failed", func() {
+			counterpartyClient := path.EndpointB.GetClientState().(*ibctmtypes.ClientState)
+			counterpartyClient.ChainId = "wrongChainID"
+			path.EndpointB.SetClientState(counterpartyClient)
+		}, false},
+		{"client status is not active - client is expired", func() {
+			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
+			path.EndpointA.SetClientState(clientState)
+		}, false},
 	}
 
 	for _, tc := range cases {
 		tc := tc
 
-		suite.Run(tc.msg, func() {
+		suite.Run(tc.name, func() {
 			suite.SetupTest() // reset
+			heightDiff = 0    // must be explicitly changed
 
-			path := ibctesting.NewPath(suite.chainA, suite.chainB)
+			path = ibctesting.NewPath(suite.chainA, suite.chainB)
 			suite.coordinator.SetupConnections(path)
 
+			tc.malleate()
+
 			counterpartyClient, clientProof := path.EndpointB.QueryClientStateProof()
 			proofHeight := clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()-1))
 
-			if tc.malleateCounterparty {
-				tmClient, _ := counterpartyClient.(*ibctmtypes.ClientState)
-				tmClient.ChainId = "wrongChainID"
-			}
-
 			connection := path.EndpointA.GetConnection()
-			if tc.changeClientID {
-				connection.ClientId = ibctesting.InvalidID
-			}
 
 			err := suite.chainA.App.GetIBCKeeper().ConnectionKeeper.VerifyClientState(
 				suite.chainA.GetContext(), connection,
-				malleateHeight(proofHeight, tc.heightDiff), clientProof, counterpartyClient,
+				malleateHeight(proofHeight, heightDiff), clientProof, counterpartyClient,
 			)
 
 			if tc.expPass {
@@ -73,19 +85,19 @@ func (suite *KeeperTestSuite) TestVerifyClientState() {
 // state for chainA at that height.
 func (suite *KeeperTestSuite) TestVerifyClientConsensusState() {
 	var (
-		path           *ibctesting.Path
-		changeClientID bool
-		heightDiff     uint64
+		path       *ibctesting.Path
+		heightDiff uint64
 	)
 	cases := []struct {
-		msg      string
+		name     string
 		malleate func()
 		expPass  bool
 	}{
-		{"verification success", func() {
-		}, true},
+		{"verification success", func() {}, true},
 		{"client state not found", func() {
-			changeClientID = true
+			connection := path.EndpointA.GetConnection()
+			connection.ClientId = ibctesting.InvalidID
+			path.EndpointA.SetConnection(connection)
 		}, false},
 		{"consensus state not found", func() {
 			heightDiff = 5
@@ -105,24 +117,25 @@ func (suite *KeeperTestSuite) TestVerifyClientConsensusState() {
 
 			suite.coordinator.CommitBlock(suite.chainB)
 		}, false},
+		{"client status is not active - client is expired", func() {
+			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
+			path.EndpointA.SetClientState(clientState)
+		}, false},
 	}
 
 	for _, tc := range cases {
 		tc := tc
 
-		suite.Run(tc.msg, func() {
-			suite.SetupTest()      // reset
-			heightDiff = 0         // must be explicitly changed in malleate
-			changeClientID = false // must be explicitly changed in malleate
+		suite.Run(tc.name, func() {
+			suite.SetupTest() // reset
+			heightDiff = 0    // must be explicitly changed in malleate
 			path = ibctesting.NewPath(suite.chainA, suite.chainB)
 			suite.coordinator.SetupConnections(path)
 
 			tc.malleate()
 
 			connection := path.EndpointA.GetConnection()
-			if changeClientID {
-				connection.ClientId = ibctesting.InvalidID
-			}
 
 			proof, consensusHeight := suite.chainB.QueryConsensusStateProof(path.EndpointB.ClientID)
 			proofHeight := clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()-1))
@@ -146,44 +159,57 @@ func (suite *KeeperTestSuite) TestVerifyClientConsensusState() {
 // TestVerifyConnectionState verifies the connection state of the connection
 // on chainB. The connections on chainA and chainB are fully opened.
 func (suite *KeeperTestSuite) TestVerifyConnectionState() {
+	var (
+		path       *ibctesting.Path
+		heightDiff uint64
+	)
 	cases := []struct {
-		msg                   string
-		changeClientID        bool
-		changeConnectionState bool
-		heightDiff            uint64
-		expPass               bool
+		name     string
+		malleate func()
+		expPass  bool
 	}{
-		{"verification success", false, false, 0, true},
-		{"client state not found - changed client ID", true, false, 0, false},
-		{"consensus state not found - increased proof height", false, false, 5, false},
-		{"verification failed - connection state is different than proof", false, true, 0, false},
+		{"verification success", func() {}, true},
+		{"client state not found - changed client ID", func() {
+			connection := path.EndpointA.GetConnection()
+			connection.ClientId = ibctesting.InvalidID
+			path.EndpointA.SetConnection(connection)
+		}, false},
+		{"consensus state not found - increased proof height", func() {
+			heightDiff = 5
+		}, false},
+		{"verification failed - connection state is different than proof", func() {
+			connection := path.EndpointA.GetConnection()
+			connection.State = types.TRYOPEN
+			path.EndpointA.SetConnection(connection)
+		}, false},
+		{"client status is not active - client is expired", func() {
+			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
+			path.EndpointA.SetClientState(clientState)
+		}, false},
 	}
 
 	for _, tc := range cases {
 		tc := tc
 
-		suite.Run(tc.msg, func() {
+		suite.Run(tc.name, func() {
 			suite.SetupTest() // reset
 
-			path := ibctesting.NewPath(suite.chainA, suite.chainB)
+			path = ibctesting.NewPath(suite.chainA, suite.chainB)
 			suite.coordinator.SetupConnections(path)
 
-			connection := path.EndpointA.GetConnection()
-			if tc.changeClientID {
-				connection.ClientId = ibctesting.InvalidID
-			}
-			expectedConnection := path.EndpointB.GetConnection()
-
 			connectionKey := host.ConnectionKey(path.EndpointB.ConnectionID)
 			proof, proofHeight := suite.chainB.QueryProof(connectionKey)
 
-			if tc.changeConnectionState {
-				expectedConnection.State = types.TRYOPEN
-			}
+			tc.malleate()
+
+			connection := path.EndpointA.GetConnection()
+
+			expectedConnection := path.EndpointB.GetConnection()
 
 			err := suite.chainA.App.GetIBCKeeper().ConnectionKeeper.VerifyConnectionState(
 				suite.chainA.GetContext(), connection,
-				malleateHeight(proofHeight, tc.heightDiff), proof, path.EndpointB.ConnectionID, expectedConnection,
+				malleateHeight(proofHeight, heightDiff), proof, path.EndpointB.ConnectionID, expectedConnection,
 			)
 
 			if tc.expPass {
@@ -198,42 +224,55 @@ func (suite *KeeperTestSuite) TestVerifyConnectionState() {
 // TestVerifyChannelState verifies the channel state of the channel on
 // chainB. The channels on chainA and chainB are fully opened.
 func (suite *KeeperTestSuite) TestVerifyChannelState() {
+	var (
+		path       *ibctesting.Path
+		heightDiff uint64
+	)
 	cases := []struct {
-		msg                string
-		changeClientID     bool
-		changeChannelState bool
-		heightDiff         uint64
-		expPass            bool
+		name     string
+		malleate func()
+		expPass  bool
 	}{
-		{"verification success", false, false, 0, true},
-		{"client state not found- changed client ID", true, false, 0, false},
-		{"consensus state not found - increased proof height", false, false, 5, false},
-		{"verification failed - changed channel state", false, true, 0, false},
+		{"verification success", func() {}, true},
+		{"client state not found- changed client ID", func() {
+			connection := path.EndpointA.GetConnection()
+			connection.ClientId = ibctesting.InvalidID
+			path.EndpointA.SetConnection(connection)
+		}, false},
+		{"consensus state not found - increased proof height", func() {
+			heightDiff = 5
+		}, false},
+		{"verification failed - changed channel state", func() {
+			channel := path.EndpointA.GetChannel()
+			channel.State = channeltypes.TRYOPEN
+			path.EndpointA.SetChannel(channel)
+		}, false},
+		{"client status is not active - client is expired", func() {
+			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
+			path.EndpointA.SetClientState(clientState)
+		}, false},
 	}
 
 	for _, tc := range cases {
 		tc := tc
 
-		suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
+		suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
 			suite.SetupTest() // reset
 
-			path := ibctesting.NewPath(suite.chainA, suite.chainB)
+			path = ibctesting.NewPath(suite.chainA, suite.chainB)
 			suite.coordinator.Setup(path)
-			connection := path.EndpointA.GetConnection()
-			if tc.changeClientID {
-				connection.ClientId = ibctesting.InvalidID
-			}
 
 			channelKey := host.ChannelKey(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
 			proof, proofHeight := suite.chainB.QueryProof(channelKey)
 
+			tc.malleate()
+			connection := path.EndpointA.GetConnection()
+
 			channel := path.EndpointB.GetChannel()
-			if tc.changeChannelState {
-				channel.State = channeltypes.TRYOPEN
-			}
 
 			err := suite.chainA.App.GetIBCKeeper().ConnectionKeeper.VerifyChannelState(
-				suite.chainA.GetContext(), connection, malleateHeight(proofHeight, tc.heightDiff), proof,
+				suite.chainA.GetContext(), connection, malleateHeight(proofHeight, heightDiff), proof,
 				path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, channel,
 			)
 
@@ -250,51 +289,65 @@ func (suite *KeeperTestSuite) TestVerifyChannelState() {
 // on channelA. The channels on chainA and chainB are fully opened and a
 // packet is sent from chainA to chainB, but has not been received.
 func (suite *KeeperTestSuite) TestVerifyPacketCommitment() {
+	var (
+		path        *ibctesting.Path
+		packet      channeltypes.Packet
+		heightDiff  uint64
+		delayPeriod uint64
+	)
 	cases := []struct {
-		msg                         string
-		changeClientID              bool
-		changePacketCommitmentState bool
-		heightDiff                  uint64
-		delayPeriod                 uint64
-		expPass                     bool
+		name     string
+		malleate func()
+		expPass  bool
 	}{
-		{"verification success", false, false, 0, 0, true},
-		{"verification success: delay period passed", false, false, 0, uint64(1 * time.Second.Nanoseconds()), true},
-		{"delay period has not passed", false, false, 0, uint64(1 * time.Hour.Nanoseconds()), false},
-		{"client state not found- changed client ID", true, false, 0, 0, false},
-		{"consensus state not found - increased proof height", false, false, 5, 0, false},
-		{"verification failed - changed packet commitment state", false, true, 0, 0, false},
+		{"verification success", func() {}, true},
+		{"verification success: delay period passed", func() {
+			delayPeriod = uint64(1 * time.Second.Nanoseconds())
+		}, true},
+		{"delay period has not passed", func() {
+			delayPeriod = uint64(1 * time.Hour.Nanoseconds())
+		}, false},
+		{"client state not found- changed client ID", func() {
+			connection := path.EndpointB.GetConnection()
+			connection.ClientId = ibctesting.InvalidID
+			path.EndpointB.SetConnection(connection)
+		}, false},
+		{"consensus state not found - increased proof height", func() {
+			heightDiff = 5
+		}, false},
+		{"verification failed - changed packet commitment state", func() {
+			packet.Data = []byte(ibctesting.InvalidID)
+		}, false},
+		{"client status is not active - client is expired", func() {
+			clientState := path.EndpointB.GetClientState().(*ibctmtypes.ClientState)
+			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
+			path.EndpointB.SetClientState(clientState)
+		}, false},
 	}
 
 	for _, tc := range cases {
 		tc := tc
 
-		suite.Run(tc.msg, func() {
+		suite.Run(tc.name, func() {
 			suite.SetupTest() // reset
 
-			path := ibctesting.NewPath(suite.chainA, suite.chainB)
+			path = ibctesting.NewPath(suite.chainA, suite.chainB)
 			suite.coordinator.Setup(path)
 
-			connection := path.EndpointB.GetConnection()
-			connection.DelayPeriod = tc.delayPeriod
-			if tc.changeClientID {
-				connection.ClientId = ibctesting.InvalidID
-			}
-
-			packet := channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, 0)
+			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, 0)
 			err := path.EndpointA.SendPacket(packet)
 			suite.Require().NoError(err)
 
+			tc.malleate()
+
+			connection := path.EndpointB.GetConnection()
+			connection.DelayPeriod = delayPeriod
 			commitmentKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
 			proof, proofHeight := suite.chainA.QueryProof(commitmentKey)
 
-			if tc.changePacketCommitmentState {
-				packet.Data = []byte(ibctesting.InvalidID)
-			}
-
 			commitment := channeltypes.CommitPacket(suite.chainB.App.GetIBCKeeper().Codec(), packet)
 			err = suite.chainB.App.GetIBCKeeper().ConnectionKeeper.VerifyPacketCommitment(
-				suite.chainB.GetContext(), connection, malleateHeight(proofHeight, tc.heightDiff), proof,
+				suite.chainB.GetContext(), connection, malleateHeight(proofHeight, heightDiff), proof,
 				packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence(), commitment,
 			)
 
@@ -311,37 +364,53 @@ func (suite *KeeperTestSuite) TestVerifyPacketCommitment() {
 // channelB. The channels on chainA and chainB are fully opened and a packet
 // is sent from chainA to chainB and received.
 func (suite *KeeperTestSuite) TestVerifyPacketAcknowledgement() {
+	var (
+		path        *ibctesting.Path
+		ack         exported.Acknowledgement
+		heightDiff  uint64
+		delayPeriod uint64
+	)
+
 	cases := []struct {
-		msg                   string
-		changeClientID        bool
-		changeAcknowledgement bool
-		heightDiff            uint64
-		delayPeriod           uint64
-		expPass               bool
+		name     string
+		malleate func()
+		expPass  bool
 	}{
-		{"verification success", false, false, 0, 0, true},
-		{"verification success: delay period passed", false, false, 0, uint64(1 * time.Second.Nanoseconds()), true},
-		{"delay period has not passed", false, false, 0, uint64(1 * time.Hour.Nanoseconds()), false},
-		{"client state not found- changed client ID", true, false, 0, 0, false},
-		{"consensus state not found - increased proof height", false, false, 5, 0, false},
-		{"verification failed - changed acknowledgement", false, true, 0, 0, false},
+		{"verification success", func() {}, true},
+		{"verification success: delay period passed", func() {
+			delayPeriod = uint64(1 * time.Second.Nanoseconds())
+		}, true},
+		{"delay period has not passed", func() {
+			delayPeriod = uint64(1 * time.Hour.Nanoseconds())
+		}, false},
+		{"client state not found- changed client ID", func() {
+			connection := path.EndpointA.GetConnection()
+			connection.ClientId = ibctesting.InvalidID
+			path.EndpointA.SetConnection(connection)
+		}, false},
+		{"consensus state not found - increased proof height", func() {
+			heightDiff = 5
+		}, false},
+		{"verification failed - changed acknowledgement", func() {
+			ack = ibcmock.MockFailAcknowledgement
+		}, false},
+		{"client status is not active - client is expired", func() {
+			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
+			path.EndpointA.SetClientState(clientState)
+		}, false},
 	}
 
 	for _, tc := range cases {
 		tc := tc
 
-		suite.Run(tc.msg, func() {
-			suite.SetupTest() // reset
+		suite.Run(tc.name, func() {
+			suite.SetupTest()                 // reset
+			ack = ibcmock.MockAcknowledgement // must be explicitly changed
 
-			path := ibctesting.NewPath(suite.chainA, suite.chainB)
+			path = ibctesting.NewPath(suite.chainA, suite.chainB)
 			suite.coordinator.Setup(path)
 
-			connection := path.EndpointA.GetConnection()
-			connection.DelayPeriod = tc.delayPeriod
-			if tc.changeClientID {
-				connection.ClientId = ibctesting.InvalidID
-			}
-
 			// send and receive packet
 			packet := channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, 0)
 			err := path.EndpointA.SendPacket(packet)
@@ -357,13 +426,13 @@ func (suite *KeeperTestSuite) TestVerifyPacketAcknowledgement() {
 			packetAckKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
 			proof, proofHeight := suite.chainB.QueryProof(packetAckKey)
 
-			ack := ibcmock.MockAcknowledgement
-			if tc.changeAcknowledgement {
-				ack = ibcmock.MockFailAcknowledgement
-			}
+			tc.malleate()
+
+			connection := path.EndpointA.GetConnection()
+			connection.DelayPeriod = delayPeriod
 
 			err = suite.chainA.App.GetIBCKeeper().ConnectionKeeper.VerifyPacketAcknowledgement(
-				suite.chainA.GetContext(), connection, malleateHeight(proofHeight, tc.heightDiff), proof,
+				suite.chainA.GetContext(), connection, malleateHeight(proofHeight, heightDiff), proof,
 				packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), ack.Acknowledgement(),
 			)
 
@@ -380,51 +449,70 @@ func (suite *KeeperTestSuite) TestVerifyPacketAcknowledgement() {
 // absence on channelB. The channels on chainA and chainB are fully opened and
 // a packet is sent from chainA to chainB and not received.
 func (suite *KeeperTestSuite) TestVerifyPacketReceiptAbsence() {
+	var (
+		path        *ibctesting.Path
+		packet      channeltypes.Packet
+		heightDiff  uint64
+		delayPeriod uint64
+	)
+
 	cases := []struct {
-		msg            string
-		changeClientID bool
-		recvAck        bool
-		heightDiff     uint64
-		delayPeriod    uint64
-		expPass        bool
+		name     string
+		malleate func()
+		expPass  bool
 	}{
-		{"verification success", false, false, 0, 0, true},
-		{"verification success: delay period passed", false, false, 0, uint64(1 * time.Second.Nanoseconds()), true},
-		{"delay period has not passed", false, false, 0, uint64(1 * time.Hour.Nanoseconds()), false},
-		{"client state not found - changed client ID", true, false, 0, 0, false},
-		{"consensus state not found - increased proof height", false, false, 5, 0, false},
-		{"verification failed - acknowledgement was received", false, true, 0, 0, false},
+		{"verification success", func() {}, true},
+		{"verification success: delay period passed", func() {
+			delayPeriod = uint64(1 * time.Second.Nanoseconds())
+		}, true},
+		{"delay period has not passed", func() {
+			delayPeriod = uint64(1 * time.Hour.Nanoseconds())
+		}, false},
+		{"client state not found - changed client ID", func() {
+			connection := path.EndpointA.GetConnection()
+			connection.ClientId = ibctesting.InvalidID
+			path.EndpointA.SetConnection(connection)
+		}, false},
+		{"consensus state not found - increased proof height", func() {
+			heightDiff = 5
+		}, false},
+		{"verification failed - acknowledgement was received", func() {
+			// increment receiving chain's (chainB) time by 2 hour to always pass receive
+			suite.coordinator.IncrementTimeBy(time.Hour * 2)
+			suite.coordinator.CommitBlock(suite.chainB)
+
+			err := path.EndpointB.RecvPacket(packet)
+			suite.Require().NoError(err)
+		}, false},
+		{"client status is not active - client is expired", func() {
+			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
+			path.EndpointA.SetClientState(clientState)
+		}, false},
 	}
 
 	for _, tc := range cases {
 		tc := tc
 
-		suite.Run(tc.msg, func() {
+		suite.Run(tc.name, func() {
 			suite.SetupTest() // reset
 
-			path := ibctesting.NewPath(suite.chainA, suite.chainB)
+			path = ibctesting.NewPath(suite.chainA, suite.chainB)
 			suite.coordinator.Setup(path)
 
-			connection := path.EndpointA.GetConnection()
-			connection.DelayPeriod = tc.delayPeriod
-			if tc.changeClientID {
-				connection.ClientId = ibctesting.InvalidID
-			}
-
-			// send, only receive if specified
-			packet := channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, 0)
+			// send, only receive in malleate if applicable
+			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, 0)
 			err := path.EndpointA.SendPacket(packet)
 			suite.Require().NoError(err)
 
-			if tc.recvAck {
-				// increment receiving chain's (chainB) time by 2 hour to always pass receive
-				suite.coordinator.IncrementTimeBy(time.Hour * 2)
-				suite.coordinator.CommitBlock(suite.chainB)
+			tc.malleate()
 
-				err = path.EndpointB.RecvPacket(packet)
-				suite.Require().NoError(err)
-			} else {
-				// need to update height to prove absence
+			connection := path.EndpointA.GetConnection()
+			connection.DelayPeriod = delayPeriod
+
+			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+			if clientState.FrozenHeight.IsZero() {
+				// need to update height to prove absence or receipt
 				suite.coordinator.CommitBlock(suite.chainA, suite.chainB)
 				path.EndpointA.UpdateClient()
 			}
@@ -433,7 +521,7 @@ func (suite *KeeperTestSuite) TestVerifyPacketReceiptAbsence() {
 			proof, proofHeight := suite.chainB.QueryProof(packetReceiptKey)
 
 			err = suite.chainA.App.GetIBCKeeper().ConnectionKeeper.VerifyPacketReceiptAbsence(
-				suite.chainA.GetContext(), connection, malleateHeight(proofHeight, tc.heightDiff), proof,
+				suite.chainA.GetContext(), connection, malleateHeight(proofHeight, heightDiff), proof,
 				packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(),
 			)
 
@@ -450,37 +538,52 @@ func (suite *KeeperTestSuite) TestVerifyPacketReceiptAbsence() {
 // channelB. The channels on chainA and chainB are fully opened and a packet
 // is sent from chainA to chainB and received.
 func (suite *KeeperTestSuite) TestVerifyNextSequenceRecv() {
+	var (
+		path        *ibctesting.Path
+		heightDiff  uint64
+		delayPeriod uint64
+		offsetSeq   uint64
+	)
+
 	cases := []struct {
-		msg            string
-		changeClientID bool
-		offsetSeq      uint64
-		heightDiff     uint64
-		delayPeriod    uint64
-		expPass        bool
+		name     string
+		malleate func()
+		expPass  bool
 	}{
-		{"verification success", false, 0, 0, 0, true},
-		{"verification success: delay period passed", false, 0, 0, uint64(1 * time.Second.Nanoseconds()), true},
-		{"delay period has not passed", false, 0, 0, uint64(1 * time.Hour.Nanoseconds()), false},
-		{"client state not found- changed client ID", true, 0, 0, 0, false},
-		{"consensus state not found - increased proof height", false, 0, 5, 0, false},
-		{"verification failed - wrong expected next seq recv", false, 1, 0, 0, false},
+		{"verification success", func() {}, true},
+		{"verification success: delay period passed", func() {
+			delayPeriod = uint64(1 * time.Second.Nanoseconds())
+		}, true},
+		{"delay period has not passed", func() {
+			delayPeriod = uint64(1 * time.Hour.Nanoseconds())
+		}, false},
+		{"client state not found- changed client ID", func() {
+			connection := path.EndpointA.GetConnection()
+			connection.ClientId = ibctesting.InvalidID
+			path.EndpointA.SetConnection(connection)
+		}, false},
+		{"consensus state not found - increased proof height", func() {
+			heightDiff = 5
+		}, false},
+		{"verification failed - wrong expected next seq recv", func() {
+			offsetSeq = 1
+		}, false},
+		{"client status is not active - client is expired", func() {
+			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
+			path.EndpointA.SetClientState(clientState)
+		}, false},
 	}
 
 	for _, tc := range cases {
 		tc := tc
 
-		suite.Run(tc.msg, func() {
+		suite.Run(tc.name, func() {
 			suite.SetupTest() // reset
 
-			path := ibctesting.NewPath(suite.chainA, suite.chainB)
+			path = ibctesting.NewPath(suite.chainA, suite.chainB)
 			suite.coordinator.Setup(path)
 
-			connection := path.EndpointA.GetConnection()
-			connection.DelayPeriod = tc.delayPeriod
-			if tc.changeClientID {
-				connection.ClientId = ibctesting.InvalidID
-			}
-
 			// send and receive packet
 			packet := channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, 0)
 			err := path.EndpointA.SendPacket(packet)
@@ -496,9 +599,13 @@ func (suite *KeeperTestSuite) TestVerifyNextSequenceRecv() {
 			nextSeqRecvKey := host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel())
 			proof, proofHeight := suite.chainB.QueryProof(nextSeqRecvKey)
 
+			tc.malleate()
+
+			connection := path.EndpointA.GetConnection()
+			connection.DelayPeriod = delayPeriod
 			err = suite.chainA.App.GetIBCKeeper().ConnectionKeeper.VerifyNextSequenceRecv(
-				suite.chainA.GetContext(), connection, malleateHeight(proofHeight, tc.heightDiff), proof,
-				packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()+tc.offsetSeq,
+				suite.chainA.GetContext(), connection, malleateHeight(proofHeight, heightDiff), proof,
+				packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()+offsetSeq,
 			)
 
 			if tc.expPass {
diff --git a/modules/core/04-channel/keeper/packet.go b/modules/core/04-channel/keeper/packet.go
index 7634ebf491a..72a1ff5b50c 100644
--- a/modules/core/04-channel/keeper/packet.go
+++ b/modules/core/04-channel/keeper/packet.go
@@ -69,8 +69,9 @@ func (k Keeper) SendPacket(
 	}
 
 	// prevent accidental sends with clients that cannot be updated
-	if clientState.IsFrozen() {
-		return sdkerrors.Wrapf(clienttypes.ErrClientFrozen, "cannot send packet on a frozen client with ID %s", connectionEnd.GetClientID())
+	clientStore := k.clientKeeper.ClientStore(ctx, connectionEnd.GetClientID())
+	if status := clientState.Status(ctx, clientStore, k.cdc); status != exported.Active {
+		return sdkerrors.Wrapf(clienttypes.ErrClientNotActive, "cannot send packet using client (%s) with status %s", connectionEnd.GetClientID(), status)
 	}
 
 	// check if packet timeouted on the receiving chain
diff --git a/modules/core/04-channel/types/expected_keepers.go b/modules/core/04-channel/types/expected_keepers.go
index b109b6c19b2..ec590cd5c39 100644
--- a/modules/core/04-channel/types/expected_keepers.go
+++ b/modules/core/04-channel/types/expected_keepers.go
@@ -11,6 +11,7 @@ import (
 type ClientKeeper interface {
 	GetClientState(ctx sdk.Context, clientID string) (exported.ClientState, bool)
 	GetClientConsensusState(ctx sdk.Context, clientID string, height exported.Height) (exported.ConsensusState, bool)
+	ClientStore(ctx sdk.Context, clientID string) sdk.KVStore
 }
 
 // ConnectionKeeper expected account IBC connection keeper
diff --git a/modules/core/exported/client.go b/modules/core/exported/client.go
index 3d552b07724..890a93d1013 100644
--- a/modules/core/exported/client.go
+++ b/modules/core/exported/client.go
@@ -8,6 +8,9 @@ import (
 	sdk "github.com/cosmos/cosmos-sdk/types"
 )
 
+// Status represents the status of a client
+type Status string
+
 const (
 	// TypeClientMisbehaviour is the shared evidence misbehaviour type
 	TypeClientMisbehaviour string = "client_misbehaviour"
@@ -21,6 +24,18 @@ const (
 	// Localhost is the client type for a localhost client. It is also used as the clientID
 	// for the localhost client.
 	Localhost string = "09-localhost"
+
+	// Active is a status type of a client. An active client is allowed to be used.
+	Active Status = "Active"
+
+	// Frozen is a status type of a client. A frozen client is not allowed to be used.
+	Frozen Status = "Frozen"
+
+	// Expired is a status type of a client. An expired client is not allowed to be used.
+	Expired Status = "Expired"
+
+	// Unknown indicates there was an error in determining the status of a client.
+	Unknown Status = "Unknown"
 )
 
 // ClientState defines the required common functions for light clients.
@@ -29,7 +44,6 @@ type ClientState interface {
 
 	ClientType() string
 	GetLatestHeight() Height
-	IsFrozen() bool
 	GetFrozenHeight() Height
 	Validate() error
 	GetProofSpecs() []*ics23.ProofSpec
@@ -39,6 +53,10 @@ type ClientState interface {
 	// necessary for correct light client operation
 	Initialize(sdk.Context, codec.BinaryMarshaler, sdk.KVStore, ConsensusState) error
 
+	// Status function
+	// Clients must return their status. Only Active clients are allowed to process packets.
+	Status(ctx sdk.Context, clientStore sdk.KVStore, cdc codec.BinaryMarshaler) Status
+
 	// Genesis function
 	ExportMetadata(sdk.KVStore) []GenesisMetadata
 
@@ -221,3 +239,8 @@ type GenesisMetadata interface {
 	// returns metadata value
 	GetValue() []byte
 }
+
+// String returns the string representation of a client status.
+func (s Status) String() string {
+	return string(s)
+}
diff --git a/modules/core/keeper/grpc_query.go b/modules/core/keeper/grpc_query.go
index 365cae03920..f647ab5aceb 100644
--- a/modules/core/keeper/grpc_query.go
+++ b/modules/core/keeper/grpc_query.go
@@ -28,6 +28,11 @@ func (q Keeper) ConsensusStates(c context.Context, req *clienttypes.QueryConsens
 	return q.ClientKeeper.ConsensusStates(c, req)
 }
 
+// ClientStatus implements the IBC QueryServer interface
+func (q Keeper) ClientStatus(c context.Context, req *clienttypes.QueryClientStatusRequest) (*clienttypes.QueryClientStatusResponse, error) {
+	return q.ClientKeeper.ClientStatus(c, req)
+}
+
 // ClientParams implements the IBC QueryServer interface
 func (q Keeper) ClientParams(c context.Context, req *clienttypes.QueryClientParamsRequest) (*clienttypes.QueryClientParamsResponse, error) {
 	return q.ClientKeeper.ClientParams(c, req)
diff --git a/modules/light-clients/06-solomachine/types/client_state.go b/modules/light-clients/06-solomachine/types/client_state.go
index efa740cab6a..a45ccc31b6c 100644
--- a/modules/light-clients/06-solomachine/types/client_state.go
+++ b/modules/light-clients/06-solomachine/types/client_state.go
@@ -40,6 +40,18 @@ func (cs ClientState) GetLatestHeight() exported.Height {
 	return clienttypes.NewHeight(0, cs.Sequence)
 }
 
+// Status returns the status of the solo machine client.
+// The client may be:
+// - Active: if frozen sequence is 0
+// - Frozen: otherwise solo machine is frozen
+func (cs ClientState) Status(_ sdk.Context, _ sdk.KVStore, _ codec.BinaryMarshaler) exported.Status {
+	if cs.FrozenSequence != 0 {
+		return exported.Frozen
+	}
+
+	return exported.Active
+}
+
 // IsFrozen returns true if the client is frozen.
 func (cs ClientState) IsFrozen() bool {
 	return cs.FrozenSequence != 0
diff --git a/modules/light-clients/06-solomachine/types/client_state_test.go b/modules/light-clients/06-solomachine/types/client_state_test.go
index 6bab40ff1bc..bd2587e399e 100644
--- a/modules/light-clients/06-solomachine/types/client_state_test.go
+++ b/modules/light-clients/06-solomachine/types/client_state_test.go
@@ -25,6 +25,18 @@ var (
 	consensusHeight = clienttypes.ZeroHeight()
 )
 
+func (suite *SoloMachineTestSuite) TestStatus() {
+	clientState := suite.solomachine.ClientState()
+	// solo machine discards arguements
+	status := clientState.Status(suite.chainA.GetContext(), nil, nil)
+	suite.Require().Equal(exported.Active, status)
+
+	// freeze solo machine
+	clientState.FrozenSequence = 1
+	status = clientState.Status(suite.chainA.GetContext(), nil, nil)
+	suite.Require().Equal(exported.Frozen, status)
+}
+
 func (suite *SoloMachineTestSuite) TestClientStateValidateBasic() {
 	// test singlesig and multisig public keys
 	for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
diff --git a/modules/light-clients/06-solomachine/types/misbehaviour_handle_test.go b/modules/light-clients/06-solomachine/types/misbehaviour_handle_test.go
index efdd0722f13..9f35f7ed851 100644
--- a/modules/light-clients/06-solomachine/types/misbehaviour_handle_test.go
+++ b/modules/light-clients/06-solomachine/types/misbehaviour_handle_test.go
@@ -264,7 +264,7 @@ func (suite *SoloMachineTestSuite) TestCheckMisbehaviourAndUpdateState() {
 
 				if tc.expPass {
 					suite.Require().NoError(err)
-					suite.Require().True(clientState.IsFrozen(), "client not frozen")
+					suite.Require().True(clientState.(*types.ClientState).FrozenSequence != 0, "client not frozen")
 				} else {
 					suite.Require().Error(err)
 					suite.Require().Nil(clientState)
diff --git a/modules/light-clients/07-tendermint/types/client_state.go b/modules/light-clients/07-tendermint/types/client_state.go
index 060150d91cd..e16a9754111 100644
--- a/modules/light-clients/07-tendermint/types/client_state.go
+++ b/modules/light-clients/07-tendermint/types/client_state.go
@@ -58,9 +58,34 @@ func (cs ClientState) GetLatestHeight() exported.Height {
 	return cs.LatestHeight
 }
 
-// IsFrozen returns true if the frozen height has been set.
-func (cs ClientState) IsFrozen() bool {
-	return !cs.FrozenHeight.IsZero()
+// Status returns the status of the tendermint client.
+// The client may be:
+// - Active: FrozenHeight is zero and client is not expired
+// - Frozen: Frozen Height is not zero
+// - Expired: the latest consensus state timestamp + trusting period <= current time
+//
+// A frozen client will become expired, so the Frozen status
+// has higher precedence.
+func (cs ClientState) Status(
+	ctx sdk.Context,
+	clientStore sdk.KVStore,
+	cdc codec.BinaryMarshaler,
+) exported.Status {
+	if !cs.FrozenHeight.IsZero() {
+		return exported.Frozen
+	}
+
+	// get latest consensus state from clientStore to check for expiry
+	consState, err := GetConsensusState(clientStore, cdc, cs.GetLatestHeight())
+	if err != nil {
+		return exported.Unknown
+	}
+
+	if cs.IsExpired(consState.Timestamp, ctx.BlockTime()) {
+		return exported.Expired
+	}
+
+	return exported.Active
 }
 
 // GetFrozenHeight returns the height at which client is frozen
@@ -507,10 +532,6 @@ func produceVerificationArgs(
 		)
 	}
 
-	if cs.IsFrozen() && !cs.FrozenHeight.GT(height) {
-		return commitmenttypes.MerkleProof{}, nil, clienttypes.ErrClientFrozen
-	}
-
 	if prefix == nil {
 		return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrap(commitmenttypes.ErrInvalidPrefix, "prefix cannot be empty")
 	}
diff --git a/modules/light-clients/07-tendermint/types/client_state_test.go b/modules/light-clients/07-tendermint/types/client_state_test.go
index 94de0199da3..e6b62ddc76a 100644
--- a/modules/light-clients/07-tendermint/types/client_state_test.go
+++ b/modules/light-clients/07-tendermint/types/client_state_test.go
@@ -28,6 +28,46 @@ var (
 	invalidProof = []byte("invalid proof")
 )
 
+func (suite *TendermintTestSuite) TestStatus() {
+	var (
+		path        *ibctesting.Path
+		clientState *types.ClientState
+	)
+
+	testCases := []struct {
+		name      string
+		malleate  func()
+		expStatus exported.Status
+	}{
+		{"client is active", func() {}, exported.Active},
+		{"client is frozen", func() {
+			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
+			path.EndpointA.SetClientState(clientState)
+		}, exported.Frozen},
+		{"client status is unknown", func() {
+			clientState.LatestHeight = clientState.LatestHeight.Increment().(clienttypes.Height)
+			path.EndpointA.SetClientState(clientState)
+		}, exported.Unknown},
+		{"client status is expired", func() {
+			suite.coordinator.IncrementTimeBy(clientState.TrustingPeriod)
+		}, exported.Expired},
+	}
+
+	for _, tc := range testCases {
+		path = ibctesting.NewPath(suite.chainA, suite.chainB)
+		suite.coordinator.SetupClients(path)
+
+		clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
+		clientState = path.EndpointA.GetClientState().(*types.ClientState)
+
+		tc.malleate()
+
+		status := clientState.Status(suite.chainA.GetContext(), clientStore, suite.chainA.App.AppCodec())
+		suite.Require().Equal(tc.expStatus, status)
+
+	}
+}
+
 func (suite *TendermintTestSuite) TestValidate() {
 	testCases := []struct {
 		name        string
@@ -179,15 +219,6 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
 			prefix:  commitmenttypes.NewMerklePrefix([]byte("ibc")),
 			expPass: false,
 		},
-		{
-			name:        "client is frozen",
-			clientState: &types.ClientState{LatestHeight: height, FrozenHeight: clienttypes.NewHeight(height.RevisionNumber, height.RevisionHeight-1)},
-			consensusState: &types.ConsensusState{
-				Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
-			},
-			prefix:  commitmenttypes.NewMerklePrefix([]byte("ibc")),
-			expPass: false,
-		},
 		{
 			name:        "proof verification failed",
 			clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
@@ -244,11 +275,6 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() {
 				proofHeight = clientState.LatestHeight.Increment()
 			}, false,
 		},
-		{
-			"client is frozen", func() {
-				clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
-			}, false,
-		},
 		{
 			"proof verification failed", func() {
 				proof = invalidProof
@@ -323,11 +349,6 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() {
 				proofHeight = clientState.LatestHeight.Increment()
 			}, false,
 		},
-		{
-			"client is frozen", func() {
-				clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
-			}, false,
-		},
 		{
 			"proof verification failed", func() {
 				proof = invalidProof
@@ -418,11 +439,6 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() {
 				proofHeight = clientState.LatestHeight.Increment()
 			}, false,
 		},
-		{
-			"client is frozen", func() {
-				clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
-			}, false,
-		},
 		{
 			"proof verification failed", func() {
 				proof = invalidProof
@@ -518,11 +534,6 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() {
 				proofHeight = clientState.LatestHeight.Increment()
 			}, false,
 		},
-		{
-			"client is frozen", func() {
-				clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
-			}, false,
-		},
 		{
 			"proof verification failed", func() {
 				proof = invalidProof
@@ -623,11 +634,6 @@ func (suite *TendermintTestSuite) TestVerifyPacketReceiptAbsence() {
 				proofHeight = clientState.LatestHeight.Increment()
 			}, false,
 		},
-		{
-			"client is frozen", func() {
-				clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
-			}, false,
-		},
 		{
 			"proof verification failed", func() {
 				proof = invalidProof
@@ -724,11 +730,6 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() {
 				proofHeight = clientState.LatestHeight.Increment()
 			}, false,
 		},
-		{
-			"client is frozen", func() {
-				clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
-			}, false,
-		},
 		{
 			"proof verification failed", func() {
 				proof = invalidProof
diff --git a/modules/light-clients/07-tendermint/types/misbehaviour_handle.go b/modules/light-clients/07-tendermint/types/misbehaviour_handle.go
index 0622372a237..0cda78581ce 100644
--- a/modules/light-clients/07-tendermint/types/misbehaviour_handle.go
+++ b/modules/light-clients/07-tendermint/types/misbehaviour_handle.go
@@ -30,11 +30,7 @@ func (cs ClientState) CheckMisbehaviourAndUpdateState(
 		return nil, sdkerrors.Wrapf(clienttypes.ErrInvalidClientType, "expected type %T, got %T", misbehaviour, &Misbehaviour{})
 	}
 
-	// If client is already frozen at earlier height than misbehaviour, return with error
-	if cs.IsFrozen() && cs.FrozenHeight.LTE(misbehaviour.GetHeight()) {
-		return nil, sdkerrors.Wrapf(clienttypes.ErrInvalidMisbehaviour,
-			"client is already frozen at earlier height %s than misbehaviour height %s", cs.FrozenHeight, misbehaviour.GetHeight())
-	}
+	// The status of the client is checked in 02-client
 
 	// Retrieve trusted consensus states for each Header in misbehaviour
 	// and unmarshal from clientStore
diff --git a/modules/light-clients/07-tendermint/types/misbehaviour_handle_test.go b/modules/light-clients/07-tendermint/types/misbehaviour_handle_test.go
index ee8118472ec..1ce0b154ed5 100644
--- a/modules/light-clients/07-tendermint/types/misbehaviour_handle_test.go
+++ b/modules/light-clients/07-tendermint/types/misbehaviour_handle_test.go
@@ -360,7 +360,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
 			if tc.expPass {
 				suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
 				suite.Require().NotNil(clientState, "valid test case %d failed: %s", i, tc.name)
-				suite.Require().True(clientState.IsFrozen(), "valid test case %d failed: %s", i, tc.name)
+				suite.Require().True(!clientState.(*types.ClientState).FrozenHeight.IsZero(), "valid test case %d failed: %s", i, tc.name)
 				suite.Require().Equal(tc.misbehaviour.GetHeight(), clientState.GetFrozenHeight(),
 					"valid test case %d failed: %s. Expected FrozenHeight %s got %s", tc.misbehaviour.GetHeight(), clientState.GetFrozenHeight())
 			} else {
diff --git a/modules/light-clients/07-tendermint/types/proposal_handle.go b/modules/light-clients/07-tendermint/types/proposal_handle.go
index a4ccaea9dae..f913ce9b375 100644
--- a/modules/light-clients/07-tendermint/types/proposal_handle.go
+++ b/modules/light-clients/07-tendermint/types/proposal_handle.go
@@ -61,7 +61,7 @@ func (cs ClientState) CheckSubstituteAndUpdateState(
 
 	switch {
 
-	case cs.IsFrozen():
+	case !cs.FrozenHeight.IsZero():
 		if !cs.AllowUpdateAfterMisbehaviour {
 			return nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "client is not allowed to be unfrozen")
 		}
diff --git a/modules/light-clients/09-localhost/types/client_state.go b/modules/light-clients/09-localhost/types/client_state.go
index 6336a213ffc..6ef27ba8b73 100644
--- a/modules/light-clients/09-localhost/types/client_state.go
+++ b/modules/light-clients/09-localhost/types/client_state.go
@@ -43,9 +43,10 @@ func (cs ClientState) GetLatestHeight() exported.Height {
 	return cs.Height
 }
 
-// IsFrozen returns false.
-func (cs ClientState) IsFrozen() bool {
-	return false
+// Status always returns Active. The localhost status cannot be changed.
+func (cs ClientState) Status(_ sdk.Context, _ sdk.KVStore, _ codec.BinaryMarshaler,
+) exported.Status {
+	return exported.Active
 }
 
 // GetFrozenHeight returns an uninitialized IBC Height.
diff --git a/modules/light-clients/09-localhost/types/client_state_test.go b/modules/light-clients/09-localhost/types/client_state_test.go
index 658824dff93..f9832303d7b 100644
--- a/modules/light-clients/09-localhost/types/client_state_test.go
+++ b/modules/light-clients/09-localhost/types/client_state_test.go
@@ -19,6 +19,14 @@ const (
 	testSequence     = 1
 )
 
+func (suite *LocalhostTestSuite) TestStatus() {
+	clientState := types.NewClientState("chainID", clienttypes.NewHeight(3, 10))
+
+	// localhost should always return active
+	status := clientState.Status(suite.ctx, nil, nil)
+	suite.Require().Equal(exported.Active, status)
+}
+
 func (suite *LocalhostTestSuite) TestValidate() {
 	testCases := []struct {
 		name        string
diff --git a/proto/ibc/apps/transfer/v1/genesis.proto b/proto/ibc/apps/transfer/v1/genesis.proto
index 39cf7a6520d..84798eb45f4 100644
--- a/proto/ibc/apps/transfer/v1/genesis.proto
+++ b/proto/ibc/apps/transfer/v1/genesis.proto
@@ -9,11 +9,11 @@ import "gogoproto/gogo.proto";
 
 // GenesisState defines the ibc-transfer genesis state
 message GenesisState {
-  string port_id = 1 [ (gogoproto.moretags) = "yaml:\"port_id\"" ];
+  string              port_id      = 1 [(gogoproto.moretags) = "yaml:\"port_id\""];
   repeated DenomTrace denom_traces = 2 [
     (gogoproto.castrepeated) = "Traces",
-    (gogoproto.nullable) = false,
-    (gogoproto.moretags) = "yaml:\"denom_traces\""
+    (gogoproto.nullable)     = false,
+    (gogoproto.moretags)     = "yaml:\"denom_traces\""
   ];
-  Params params = 3 [ (gogoproto.nullable) = false ];
+  Params params = 3 [(gogoproto.nullable) = false];
 }
diff --git a/proto/ibc/apps/transfer/v1/query.proto b/proto/ibc/apps/transfer/v1/query.proto
index f4014d6222b..09e5b458785 100644
--- a/proto/ibc/apps/transfer/v1/query.proto
+++ b/proto/ibc/apps/transfer/v1/query.proto
@@ -52,8 +52,7 @@ message QueryDenomTracesRequest {
 // method.
 message QueryDenomTracesResponse {
   // denom_traces returns all denominations trace information.
-  repeated DenomTrace denom_traces = 1
-      [ (gogoproto.castrepeated) = "Traces", (gogoproto.nullable) = false ];
+  repeated DenomTrace denom_traces = 1 [(gogoproto.castrepeated) = "Traces", (gogoproto.nullable) = false];
   // pagination defines the pagination in the response.
   cosmos.base.query.v1beta1.PageResponse pagination = 2;
 }
diff --git a/proto/ibc/apps/transfer/v1/transfer.proto b/proto/ibc/apps/transfer/v1/transfer.proto
index e43971ee0c8..0aa0224a27d 100644
--- a/proto/ibc/apps/transfer/v1/transfer.proto
+++ b/proto/ibc/apps/transfer/v1/transfer.proto
@@ -37,9 +37,8 @@ message DenomTrace {
 message Params {
   // send_enabled enables or disables all cross-chain token transfers from this
   // chain.
-  bool send_enabled = 1 [ (gogoproto.moretags) = "yaml:\"send_enabled\"" ];
+  bool send_enabled = 1 [(gogoproto.moretags) = "yaml:\"send_enabled\""];
   // receive_enabled enables or disables all cross-chain token transfers to this
   // chain.
-  bool receive_enabled = 2
-      [ (gogoproto.moretags) = "yaml:\"receive_enabled\"" ];
+  bool receive_enabled = 2 [(gogoproto.moretags) = "yaml:\"receive_enabled\""];
 }
diff --git a/proto/ibc/apps/transfer/v1/tx.proto b/proto/ibc/apps/transfer/v1/tx.proto
index 73887e797e1..b746431077d 100644
--- a/proto/ibc/apps/transfer/v1/tx.proto
+++ b/proto/ibc/apps/transfer/v1/tx.proto
@@ -18,30 +18,26 @@ service Msg {
 // ICS20 enabled chains. See ICS Spec here:
 // https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures
 message MsgTransfer {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
   // the port on which the packet will be sent
-  string source_port = 1 [ (gogoproto.moretags) = "yaml:\"source_port\"" ];
+  string source_port = 1 [(gogoproto.moretags) = "yaml:\"source_port\""];
   // the channel by which the packet will be sent
-  string source_channel = 2
-      [ (gogoproto.moretags) = "yaml:\"source_channel\"" ];
+  string source_channel = 2 [(gogoproto.moretags) = "yaml:\"source_channel\""];
   // the tokens to be transferred
-  cosmos.base.v1beta1.Coin token = 3 [ (gogoproto.nullable) = false ];
+  cosmos.base.v1beta1.Coin token = 3 [(gogoproto.nullable) = false];
   // the sender address
   string sender = 4;
   // the recipient address on the destination chain
   string receiver = 5;
   // Timeout height relative to the current block height.
   // The timeout is disabled when set to 0.
-  ibc.core.client.v1.Height timeout_height = 6 [
-    (gogoproto.moretags) = "yaml:\"timeout_height\"",
-    (gogoproto.nullable) = false
-  ];
+  ibc.core.client.v1.Height timeout_height = 6
+      [(gogoproto.moretags) = "yaml:\"timeout_height\"", (gogoproto.nullable) = false];
   // Timeout timestamp (in nanoseconds) relative to the current block timestamp.
   // The timeout is disabled when set to 0.
-  uint64 timeout_timestamp = 7
-      [ (gogoproto.moretags) = "yaml:\"timeout_timestamp\"" ];
+  uint64 timeout_timestamp = 7 [(gogoproto.moretags) = "yaml:\"timeout_timestamp\""];
 }
 
 // MsgTransferResponse defines the Msg/Transfer response type.
diff --git a/proto/ibc/core/channel/v1/channel.proto b/proto/ibc/core/channel/v1/channel.proto
index 81a92a73f98..edb39d04b59 100644
--- a/proto/ibc/core/channel/v1/channel.proto
+++ b/proto/ibc/core/channel/v1/channel.proto
@@ -18,11 +18,10 @@ message Channel {
   // whether the channel is ordered or unordered
   Order ordering = 2;
   // counterparty channel end
-  Counterparty counterparty = 3 [ (gogoproto.nullable) = false ];
+  Counterparty counterparty = 3 [(gogoproto.nullable) = false];
   // list of connection identifiers, in order, along which packets sent on
   // this channel will travel
-  repeated string connection_hops = 4
-      [ (gogoproto.moretags) = "yaml:\"connection_hops\"" ];
+  repeated string connection_hops = 4 [(gogoproto.moretags) = "yaml:\"connection_hops\""];
   // opaque channel version, which is agreed upon during the handshake
   string version = 5;
 }
@@ -37,11 +36,10 @@ message IdentifiedChannel {
   // whether the channel is ordered or unordered
   Order ordering = 2;
   // counterparty channel end
-  Counterparty counterparty = 3 [ (gogoproto.nullable) = false ];
+  Counterparty counterparty = 3 [(gogoproto.nullable) = false];
   // list of connection identifiers, in order, along which packets sent on
   // this channel will travel
-  repeated string connection_hops = 4
-      [ (gogoproto.moretags) = "yaml:\"connection_hops\"" ];
+  repeated string connection_hops = 4 [(gogoproto.moretags) = "yaml:\"connection_hops\""];
   // opaque channel version, which is agreed upon during the handshake
   string version = 5;
   // port identifier
@@ -56,18 +54,17 @@ enum State {
   option (gogoproto.goproto_enum_prefix) = false;
 
   // Default State
-  STATE_UNINITIALIZED_UNSPECIFIED = 0
-      [ (gogoproto.enumvalue_customname) = "UNINITIALIZED" ];
+  STATE_UNINITIALIZED_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "UNINITIALIZED"];
   // A channel has just started the opening handshake.
-  STATE_INIT = 1 [ (gogoproto.enumvalue_customname) = "INIT" ];
+  STATE_INIT = 1 [(gogoproto.enumvalue_customname) = "INIT"];
   // A channel has acknowledged the handshake step on the counterparty chain.
-  STATE_TRYOPEN = 2 [ (gogoproto.enumvalue_customname) = "TRYOPEN" ];
+  STATE_TRYOPEN = 2 [(gogoproto.enumvalue_customname) = "TRYOPEN"];
   // A channel has completed the handshake. Open channels are
   // ready to send and receive packets.
-  STATE_OPEN = 3 [ (gogoproto.enumvalue_customname) = "OPEN" ];
+  STATE_OPEN = 3 [(gogoproto.enumvalue_customname) = "OPEN"];
   // A channel has been closed and can no longer be used to send or receive
   // packets.
-  STATE_CLOSED = 4 [ (gogoproto.enumvalue_customname) = "CLOSED" ];
+  STATE_CLOSED = 4 [(gogoproto.enumvalue_customname) = "CLOSED"];
 }
 
 // Order defines if a channel is ORDERED or UNORDERED
@@ -75,12 +72,12 @@ enum Order {
   option (gogoproto.goproto_enum_prefix) = false;
 
   // zero-value for channel ordering
-  ORDER_NONE_UNSPECIFIED = 0 [ (gogoproto.enumvalue_customname) = "NONE" ];
+  ORDER_NONE_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "NONE"];
   // packets can be delivered in any order, which may differ from the order in
   // which they were sent.
-  ORDER_UNORDERED = 1 [ (gogoproto.enumvalue_customname) = "UNORDERED" ];
+  ORDER_UNORDERED = 1 [(gogoproto.enumvalue_customname) = "UNORDERED"];
   // packets are delivered exactly in the order which they were sent
-  ORDER_ORDERED = 2 [ (gogoproto.enumvalue_customname) = "ORDERED" ];
+  ORDER_ORDERED = 2 [(gogoproto.enumvalue_customname) = "ORDERED"];
 }
 
 // Counterparty defines a channel end counterparty
@@ -88,9 +85,9 @@ message Counterparty {
   option (gogoproto.goproto_getters) = false;
 
   // port on the counterparty chain which owns the other end of the channel.
-  string port_id = 1 [ (gogoproto.moretags) = "yaml:\"port_id\"" ];
+  string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""];
   // channel end on the counterparty chain
-  string channel_id = 2 [ (gogoproto.moretags) = "yaml:\"channel_id\"" ];
+  string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""];
 }
 
 // Packet defines a type that carries data across different chains through IBC
@@ -102,26 +99,20 @@ message Packet {
   // with a later sequence number.
   uint64 sequence = 1;
   // identifies the port on the sending chain.
-  string source_port = 2 [ (gogoproto.moretags) = "yaml:\"source_port\"" ];
+  string source_port = 2 [(gogoproto.moretags) = "yaml:\"source_port\""];
   // identifies the channel end on the sending chain.
-  string source_channel = 3
-      [ (gogoproto.moretags) = "yaml:\"source_channel\"" ];
+  string source_channel = 3 [(gogoproto.moretags) = "yaml:\"source_channel\""];
   // identifies the port on the receiving chain.
-  string destination_port = 4
-      [ (gogoproto.moretags) = "yaml:\"destination_port\"" ];
+  string destination_port = 4 [(gogoproto.moretags) = "yaml:\"destination_port\""];
   // identifies the channel end on the receiving chain.
-  string destination_channel = 5
-      [ (gogoproto.moretags) = "yaml:\"destination_channel\"" ];
+  string destination_channel = 5 [(gogoproto.moretags) = "yaml:\"destination_channel\""];
   // actual opaque bytes transferred directly to the application module
   bytes data = 6;
   // block height after which the packet times out
-  ibc.core.client.v1.Height timeout_height = 7 [
-    (gogoproto.moretags) = "yaml:\"timeout_height\"",
-    (gogoproto.nullable) = false
-  ];
+  ibc.core.client.v1.Height timeout_height = 7
+      [(gogoproto.moretags) = "yaml:\"timeout_height\"", (gogoproto.nullable) = false];
   // block timestamp (in nanoseconds) after which the packet times out
-  uint64 timeout_timestamp = 8
-      [ (gogoproto.moretags) = "yaml:\"timeout_timestamp\"" ];
+  uint64 timeout_timestamp = 8 [(gogoproto.moretags) = "yaml:\"timeout_timestamp\""];
 }
 
 // PacketState defines the generic type necessary to retrieve and store
@@ -132,9 +123,9 @@ message PacketState {
   option (gogoproto.goproto_getters) = false;
 
   // channel port identifier.
-  string port_id = 1 [ (gogoproto.moretags) = "yaml:\"port_id\"" ];
+  string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""];
   // channel unique identifier.
-  string channel_id = 2 [ (gogoproto.moretags) = "yaml:\"channel_id\"" ];
+  string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""];
   // packet sequence.
   uint64 sequence = 3;
   // embedded data that represents packet state.
@@ -151,7 +142,7 @@ message PacketState {
 message Acknowledgement {
   // response contains either a result or an error and must be non-empty
   oneof response {
-    bytes result = 21;
-    string error = 22;
+    bytes  result = 21;
+    string error  = 22;
   }
 }
diff --git a/proto/ibc/core/channel/v1/genesis.proto b/proto/ibc/core/channel/v1/genesis.proto
index 00a7bcbbbf3..75bf1fdb02a 100644
--- a/proto/ibc/core/channel/v1/genesis.proto
+++ b/proto/ibc/core/channel/v1/genesis.proto
@@ -9,34 +9,24 @@ import "ibc/core/channel/v1/channel.proto";
 
 // GenesisState defines the ibc channel submodule's genesis state.
 message GenesisState {
-  repeated IdentifiedChannel channels = 1 [
-    (gogoproto.casttype) = "IdentifiedChannel",
-    (gogoproto.nullable) = false
-  ];
-  repeated PacketState acknowledgements = 2 [ (gogoproto.nullable) = false ];
-  repeated PacketState commitments = 3 [ (gogoproto.nullable) = false ];
-  repeated PacketState receipts = 4 [ (gogoproto.nullable) = false ];
-  repeated PacketSequence send_sequences = 5 [
-    (gogoproto.nullable) = false,
-    (gogoproto.moretags) = "yaml:\"send_sequences\""
-  ];
-  repeated PacketSequence recv_sequences = 6 [
-    (gogoproto.nullable) = false,
-    (gogoproto.moretags) = "yaml:\"recv_sequences\""
-  ];
-  repeated PacketSequence ack_sequences = 7 [
-    (gogoproto.nullable) = false,
-    (gogoproto.moretags) = "yaml:\"ack_sequences\""
-  ];
+  repeated IdentifiedChannel channels = 1 [(gogoproto.casttype) = "IdentifiedChannel", (gogoproto.nullable) = false];
+  repeated PacketState       acknowledgements = 2 [(gogoproto.nullable) = false];
+  repeated PacketState       commitments      = 3 [(gogoproto.nullable) = false];
+  repeated PacketState       receipts         = 4 [(gogoproto.nullable) = false];
+  repeated PacketSequence    send_sequences   = 5
+      [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"send_sequences\""];
+  repeated PacketSequence recv_sequences = 6
+      [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"recv_sequences\""];
+  repeated PacketSequence ack_sequences = 7
+      [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"ack_sequences\""];
   // the sequence for the next generated channel identifier
-  uint64 next_channel_sequence = 8
-      [ (gogoproto.moretags) = "yaml:\"next_channel_sequence\"" ];
+  uint64 next_channel_sequence = 8 [(gogoproto.moretags) = "yaml:\"next_channel_sequence\""];
 }
 
 // PacketSequence defines the genesis type necessary to retrieve and store
 // next send and receive sequences.
 message PacketSequence {
-  string port_id = 1 [ (gogoproto.moretags) = "yaml:\"port_id\"" ];
-  string channel_id = 2 [ (gogoproto.moretags) = "yaml:\"channel_id\"" ];
-  uint64 sequence = 3;
+  string port_id    = 1 [(gogoproto.moretags) = "yaml:\"port_id\""];
+  string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""];
+  uint64 sequence   = 3;
 }
diff --git a/proto/ibc/core/channel/v1/query.proto b/proto/ibc/core/channel/v1/query.proto
index 1c98fe2aa99..194fe86777f 100644
--- a/proto/ibc/core/channel/v1/query.proto
+++ b/proto/ibc/core/channel/v1/query.proto
@@ -15,8 +15,7 @@ import "gogoproto/gogo.proto";
 service Query {
   // Channel queries an IBC Channel.
   rpc Channel(QueryChannelRequest) returns (QueryChannelResponse) {
-    option (google.api.http).get =
-        "/ibc/core/channel/v1/channels/{channel_id}/ports/{port_id}";
+    option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/ports/{port_id}";
   }
 
   // Channels queries all the IBC channels of a chain.
@@ -26,90 +25,76 @@ service Query {
 
   // ConnectionChannels queries all the channels associated with a connection
   // end.
-  rpc ConnectionChannels(QueryConnectionChannelsRequest)
-      returns (QueryConnectionChannelsResponse) {
-    option (google.api.http).get =
-        "/ibc/core/channel/v1/connections/{connection}/channels";
+  rpc ConnectionChannels(QueryConnectionChannelsRequest) returns (QueryConnectionChannelsResponse) {
+    option (google.api.http).get = "/ibc/core/channel/v1/connections/{connection}/channels";
   }
 
   // ChannelClientState queries for the client state for the channel associated
   // with the provided channel identifiers.
-  rpc ChannelClientState(QueryChannelClientStateRequest)
-      returns (QueryChannelClientStateResponse) {
+  rpc ChannelClientState(QueryChannelClientStateRequest) returns (QueryChannelClientStateResponse) {
     option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/"
                                    "ports/{port_id}/client_state";
   }
 
   // ChannelConsensusState queries for the consensus state for the channel
   // associated with the provided channel identifiers.
-  rpc ChannelConsensusState(QueryChannelConsensusStateRequest)
-      returns (QueryChannelConsensusStateResponse) {
+  rpc ChannelConsensusState(QueryChannelConsensusStateRequest) returns (QueryChannelConsensusStateResponse) {
     option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/"
                                    "ports/{port_id}/consensus_state/revision/"
                                    "{revision_number}/height/{revision_height}";
   }
 
   // PacketCommitment queries a stored packet commitment hash.
-  rpc PacketCommitment(QueryPacketCommitmentRequest)
-      returns (QueryPacketCommitmentResponse) {
-    option (google.api.http).get =
-        "/ibc/core/channel/v1/channels/{channel_id}/ports/{port_id}/"
-        "packet_commitments/{sequence}";
+  rpc PacketCommitment(QueryPacketCommitmentRequest) returns (QueryPacketCommitmentResponse) {
+    option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/ports/{port_id}/"
+                                   "packet_commitments/{sequence}";
   }
 
   // PacketCommitments returns all the packet commitments hashes associated
   // with a channel.
-  rpc PacketCommitments(QueryPacketCommitmentsRequest)
-      returns (QueryPacketCommitmentsResponse) {
+  rpc PacketCommitments(QueryPacketCommitmentsRequest) returns (QueryPacketCommitmentsResponse) {
     option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/"
                                    "ports/{port_id}/packet_commitments";
   }
 
   // PacketReceipt queries if a given packet sequence has been received on the
   // queried chain
-  rpc PacketReceipt(QueryPacketReceiptRequest)
-      returns (QueryPacketReceiptResponse) {
+  rpc PacketReceipt(QueryPacketReceiptRequest) returns (QueryPacketReceiptResponse) {
     option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/"
                                    "ports/{port_id}/packet_receipts/{sequence}";
   }
 
   // PacketAcknowledgement queries a stored packet acknowledgement hash.
-  rpc PacketAcknowledgement(QueryPacketAcknowledgementRequest)
-      returns (QueryPacketAcknowledgementResponse) {
+  rpc PacketAcknowledgement(QueryPacketAcknowledgementRequest) returns (QueryPacketAcknowledgementResponse) {
     option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/"
                                    "ports/{port_id}/packet_acks/{sequence}";
   }
 
   // PacketAcknowledgements returns all the packet acknowledgements associated
   // with a channel.
-  rpc PacketAcknowledgements(QueryPacketAcknowledgementsRequest)
-      returns (QueryPacketAcknowledgementsResponse) {
+  rpc PacketAcknowledgements(QueryPacketAcknowledgementsRequest) returns (QueryPacketAcknowledgementsResponse) {
     option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/"
                                    "ports/{port_id}/packet_acknowledgements";
   }
 
   // UnreceivedPackets returns all the unreceived IBC packets associated with a
   // channel and sequences.
-  rpc UnreceivedPackets(QueryUnreceivedPacketsRequest)
-      returns (QueryUnreceivedPacketsResponse) {
-    option (google.api.http).get =
-        "/ibc/core/channel/v1/channels/{channel_id}/ports/{port_id}/"
-        "packet_commitments/"
-        "{packet_commitment_sequences}/unreceived_packets";
+  rpc UnreceivedPackets(QueryUnreceivedPacketsRequest) returns (QueryUnreceivedPacketsResponse) {
+    option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/ports/{port_id}/"
+                                   "packet_commitments/"
+                                   "{packet_commitment_sequences}/unreceived_packets";
   }
 
   // UnreceivedAcks returns all the unreceived IBC acknowledgements associated
   // with a channel and sequences.
-  rpc UnreceivedAcks(QueryUnreceivedAcksRequest)
-      returns (QueryUnreceivedAcksResponse) {
+  rpc UnreceivedAcks(QueryUnreceivedAcksRequest) returns (QueryUnreceivedAcksResponse) {
     option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/"
                                    "ports/{port_id}/packet_commitments/"
                                    "{packet_ack_sequences}/unreceived_acks";
   }
 
   // NextSequenceReceive returns the next receive sequence for a given channel.
-  rpc NextSequenceReceive(QueryNextSequenceReceiveRequest)
-      returns (QueryNextSequenceReceiveResponse) {
+  rpc NextSequenceReceive(QueryNextSequenceReceiveRequest) returns (QueryNextSequenceReceiveResponse) {
     option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/"
                                    "ports/{port_id}/next_sequence";
   }
@@ -132,7 +117,7 @@ message QueryChannelResponse {
   // merkle proof of existence
   bytes proof = 2;
   // height at which the proof was retrieved
-  ibc.core.client.v1.Height proof_height = 3 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false];
 }
 
 // QueryChannelsRequest is the request type for the Query/Channels RPC method
@@ -148,7 +133,7 @@ message QueryChannelsResponse {
   // pagination response
   cosmos.base.query.v1beta1.PageResponse pagination = 2;
   // query block height
-  ibc.core.client.v1.Height height = 3 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height height = 3 [(gogoproto.nullable) = false];
 }
 
 // QueryConnectionChannelsRequest is the request type for the
@@ -168,7 +153,7 @@ message QueryConnectionChannelsResponse {
   // pagination response
   cosmos.base.query.v1beta1.PageResponse pagination = 2;
   // query block height
-  ibc.core.client.v1.Height height = 3 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height height = 3 [(gogoproto.nullable) = false];
 }
 
 // QueryChannelClientStateRequest is the request type for the Query/ClientState
@@ -188,7 +173,7 @@ message QueryChannelClientStateResponse {
   // merkle proof of existence
   bytes proof = 2;
   // height at which the proof was retrieved
-  ibc.core.client.v1.Height proof_height = 3 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false];
 }
 
 // QueryChannelConsensusStateRequest is the request type for the
@@ -214,7 +199,7 @@ message QueryChannelConsensusStateResponse {
   // merkle proof of existence
   bytes proof = 3;
   // height at which the proof was retrieved
-  ibc.core.client.v1.Height proof_height = 4 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height proof_height = 4 [(gogoproto.nullable) = false];
 }
 
 // QueryPacketCommitmentRequest is the request type for the
@@ -237,7 +222,7 @@ message QueryPacketCommitmentResponse {
   // merkle proof of existence
   bytes proof = 2;
   // height at which the proof was retrieved
-  ibc.core.client.v1.Height proof_height = 3 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false];
 }
 
 // QueryPacketCommitmentsRequest is the request type for the
@@ -258,7 +243,7 @@ message QueryPacketCommitmentsResponse {
   // pagination response
   cosmos.base.query.v1beta1.PageResponse pagination = 2;
   // query block height
-  ibc.core.client.v1.Height height = 3 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height height = 3 [(gogoproto.nullable) = false];
 }
 
 // QueryPacketReceiptRequest is the request type for the
@@ -281,7 +266,7 @@ message QueryPacketReceiptResponse {
   // merkle proof of existence
   bytes proof = 3;
   // height at which the proof was retrieved
-  ibc.core.client.v1.Height proof_height = 4 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height proof_height = 4 [(gogoproto.nullable) = false];
 }
 
 // QueryPacketAcknowledgementRequest is the request type for the
@@ -304,7 +289,7 @@ message QueryPacketAcknowledgementResponse {
   // merkle proof of existence
   bytes proof = 2;
   // height at which the proof was retrieved
-  ibc.core.client.v1.Height proof_height = 3 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false];
 }
 
 // QueryPacketAcknowledgementsRequest is the request type for the
@@ -325,7 +310,7 @@ message QueryPacketAcknowledgementsResponse {
   // pagination response
   cosmos.base.query.v1beta1.PageResponse pagination = 2;
   // query block height
-  ibc.core.client.v1.Height height = 3 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height height = 3 [(gogoproto.nullable) = false];
 }
 
 // QueryUnreceivedPacketsRequest is the request type for the
@@ -345,7 +330,7 @@ message QueryUnreceivedPacketsResponse {
   // list of unreceived packet sequences
   repeated uint64 sequences = 1;
   // query block height
-  ibc.core.client.v1.Height height = 2 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height height = 2 [(gogoproto.nullable) = false];
 }
 
 // QueryUnreceivedAcks is the request type for the
@@ -365,7 +350,7 @@ message QueryUnreceivedAcksResponse {
   // list of unreceived acknowledgement sequences
   repeated uint64 sequences = 1;
   // query block height
-  ibc.core.client.v1.Height height = 2 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height height = 2 [(gogoproto.nullable) = false];
 }
 
 // QueryNextSequenceReceiveRequest is the request type for the
@@ -385,5 +370,5 @@ message QueryNextSequenceReceiveResponse {
   // merkle proof of existence
   bytes proof = 2;
   // height at which the proof was retrieved
-  ibc.core.client.v1.Height proof_height = 3 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false];
 }
diff --git a/proto/ibc/core/channel/v1/tx.proto b/proto/ibc/core/channel/v1/tx.proto
index 8fe5feb5373..59af0d3f240 100644
--- a/proto/ibc/core/channel/v1/tx.proto
+++ b/proto/ibc/core/channel/v1/tx.proto
@@ -20,17 +20,14 @@ service Msg {
   rpc ChannelOpenAck(MsgChannelOpenAck) returns (MsgChannelOpenAckResponse);
 
   // ChannelOpenConfirm defines a rpc handler method for MsgChannelOpenConfirm.
-  rpc ChannelOpenConfirm(MsgChannelOpenConfirm)
-      returns (MsgChannelOpenConfirmResponse);
+  rpc ChannelOpenConfirm(MsgChannelOpenConfirm) returns (MsgChannelOpenConfirmResponse);
 
   // ChannelCloseInit defines a rpc handler method for MsgChannelCloseInit.
-  rpc ChannelCloseInit(MsgChannelCloseInit)
-      returns (MsgChannelCloseInitResponse);
+  rpc ChannelCloseInit(MsgChannelCloseInit) returns (MsgChannelCloseInitResponse);
 
   // ChannelCloseConfirm defines a rpc handler method for
   // MsgChannelCloseConfirm.
-  rpc ChannelCloseConfirm(MsgChannelCloseConfirm)
-      returns (MsgChannelCloseConfirmResponse);
+  rpc ChannelCloseConfirm(MsgChannelCloseConfirm) returns (MsgChannelCloseConfirmResponse);
 
   // RecvPacket defines a rpc handler method for MsgRecvPacket.
   rpc RecvPacket(MsgRecvPacket) returns (MsgRecvPacketResponse);
@@ -48,12 +45,12 @@ service Msg {
 // MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It
 // is called by a relayer on Chain A.
 message MsgChannelOpenInit {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
-  string port_id = 1 [ (gogoproto.moretags) = "yaml:\"port_id\"" ];
-  Channel channel = 2 [ (gogoproto.nullable) = false ];
-  string signer = 3;
+  string  port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""];
+  Channel channel = 2 [(gogoproto.nullable) = false];
+  string  signer  = 3;
 }
 
 // MsgChannelOpenInitResponse defines the Msg/ChannelOpenInit response type.
@@ -62,22 +59,18 @@ message MsgChannelOpenInitResponse {}
 // MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel
 // on Chain B.
 message MsgChannelOpenTry {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
-  string port_id = 1 [ (gogoproto.moretags) = "yaml:\"port_id\"" ];
+  string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""];
   // in the case of crossing hello's, when both chains call OpenInit, we need
   // the channel identifier of the previous channel in state INIT
-  string previous_channel_id = 2
-      [ (gogoproto.moretags) = "yaml:\"previous_channel_id\"" ];
-  Channel channel = 3 [ (gogoproto.nullable) = false ];
-  string counterparty_version = 4
-      [ (gogoproto.moretags) = "yaml:\"counterparty_version\"" ];
-  bytes proof_init = 5 [ (gogoproto.moretags) = "yaml:\"proof_init\"" ];
-  ibc.core.client.v1.Height proof_height = 6 [
-    (gogoproto.moretags) = "yaml:\"proof_height\"",
-    (gogoproto.nullable) = false
-  ];
+  string                    previous_channel_id  = 2 [(gogoproto.moretags) = "yaml:\"previous_channel_id\""];
+  Channel                   channel              = 3 [(gogoproto.nullable) = false];
+  string                    counterparty_version = 4 [(gogoproto.moretags) = "yaml:\"counterparty_version\""];
+  bytes                     proof_init           = 5 [(gogoproto.moretags) = "yaml:\"proof_init\""];
+  ibc.core.client.v1.Height proof_height         = 6
+      [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
   string signer = 7;
 }
 
@@ -87,20 +80,16 @@ message MsgChannelOpenTryResponse {}
 // MsgChannelOpenAck defines a msg sent by a Relayer to Chain A to acknowledge
 // the change of channel state to TRYOPEN on Chain B.
 message MsgChannelOpenAck {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
-  string port_id = 1 [ (gogoproto.moretags) = "yaml:\"port_id\"" ];
-  string channel_id = 2 [ (gogoproto.moretags) = "yaml:\"channel_id\"" ];
-  string counterparty_channel_id = 3
-      [ (gogoproto.moretags) = "yaml:\"counterparty_channel_id\"" ];
-  string counterparty_version = 4
-      [ (gogoproto.moretags) = "yaml:\"counterparty_version\"" ];
-  bytes proof_try = 5 [ (gogoproto.moretags) = "yaml:\"proof_try\"" ];
-  ibc.core.client.v1.Height proof_height = 6 [
-    (gogoproto.moretags) = "yaml:\"proof_height\"",
-    (gogoproto.nullable) = false
-  ];
+  string                    port_id                 = 1 [(gogoproto.moretags) = "yaml:\"port_id\""];
+  string                    channel_id              = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""];
+  string                    counterparty_channel_id = 3 [(gogoproto.moretags) = "yaml:\"counterparty_channel_id\""];
+  string                    counterparty_version    = 4 [(gogoproto.moretags) = "yaml:\"counterparty_version\""];
+  bytes                     proof_try               = 5 [(gogoproto.moretags) = "yaml:\"proof_try\""];
+  ibc.core.client.v1.Height proof_height            = 6
+      [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
   string signer = 7;
 }
 
@@ -110,16 +99,14 @@ message MsgChannelOpenAckResponse {}
 // MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain B to
 // acknowledge the change of channel state to OPEN on Chain A.
 message MsgChannelOpenConfirm {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
-  string port_id = 1 [ (gogoproto.moretags) = "yaml:\"port_id\"" ];
-  string channel_id = 2 [ (gogoproto.moretags) = "yaml:\"channel_id\"" ];
-  bytes proof_ack = 3 [ (gogoproto.moretags) = "yaml:\"proof_ack\"" ];
-  ibc.core.client.v1.Height proof_height = 4 [
-    (gogoproto.moretags) = "yaml:\"proof_height\"",
-    (gogoproto.nullable) = false
-  ];
+  string                    port_id      = 1 [(gogoproto.moretags) = "yaml:\"port_id\""];
+  string                    channel_id   = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""];
+  bytes                     proof_ack    = 3 [(gogoproto.moretags) = "yaml:\"proof_ack\""];
+  ibc.core.client.v1.Height proof_height = 4
+      [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
   string signer = 5;
 }
 
@@ -130,12 +117,12 @@ message MsgChannelOpenConfirmResponse {}
 // MsgChannelCloseInit defines a msg sent by a Relayer to Chain A
 // to close a channel with Chain B.
 message MsgChannelCloseInit {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
-  string port_id = 1 [ (gogoproto.moretags) = "yaml:\"port_id\"" ];
-  string channel_id = 2 [ (gogoproto.moretags) = "yaml:\"channel_id\"" ];
-  string signer = 3;
+  string port_id    = 1 [(gogoproto.moretags) = "yaml:\"port_id\""];
+  string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""];
+  string signer     = 3;
 }
 
 // MsgChannelCloseInitResponse defines the Msg/ChannelCloseInit response type.
@@ -144,16 +131,14 @@ message MsgChannelCloseInitResponse {}
 // MsgChannelCloseConfirm defines a msg sent by a Relayer to Chain B
 // to acknowledge the change of channel state to CLOSED on Chain A.
 message MsgChannelCloseConfirm {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
-  string port_id = 1 [ (gogoproto.moretags) = "yaml:\"port_id\"" ];
-  string channel_id = 2 [ (gogoproto.moretags) = "yaml:\"channel_id\"" ];
-  bytes proof_init = 3 [ (gogoproto.moretags) = "yaml:\"proof_init\"" ];
-  ibc.core.client.v1.Height proof_height = 4 [
-    (gogoproto.moretags) = "yaml:\"proof_height\"",
-    (gogoproto.nullable) = false
-  ];
+  string                    port_id      = 1 [(gogoproto.moretags) = "yaml:\"port_id\""];
+  string                    channel_id   = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""];
+  bytes                     proof_init   = 3 [(gogoproto.moretags) = "yaml:\"proof_init\""];
+  ibc.core.client.v1.Height proof_height = 4
+      [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
   string signer = 5;
 }
 
@@ -163,16 +148,13 @@ message MsgChannelCloseConfirmResponse {}
 
 // MsgRecvPacket receives incoming IBC packet
 message MsgRecvPacket {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
-  Packet packet = 1 [ (gogoproto.nullable) = false ];
-  bytes proof_commitment = 2
-      [ (gogoproto.moretags) = "yaml:\"proof_commitment\"" ];
-  ibc.core.client.v1.Height proof_height = 3 [
-    (gogoproto.moretags) = "yaml:\"proof_height\"",
-    (gogoproto.nullable) = false
-  ];
+  Packet                    packet           = 1 [(gogoproto.nullable) = false];
+  bytes                     proof_commitment = 2 [(gogoproto.moretags) = "yaml:\"proof_commitment\""];
+  ibc.core.client.v1.Height proof_height     = 3
+      [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
   string signer = 4;
 }
 
@@ -181,19 +163,15 @@ message MsgRecvPacketResponse {}
 
 // MsgTimeout receives timed-out packet
 message MsgTimeout {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
-  Packet packet = 1 [ (gogoproto.nullable) = false ];
-  bytes proof_unreceived = 2
-      [ (gogoproto.moretags) = "yaml:\"proof_unreceived\"" ];
-  ibc.core.client.v1.Height proof_height = 3 [
-    (gogoproto.moretags) = "yaml:\"proof_height\"",
-    (gogoproto.nullable) = false
-  ];
-  uint64 next_sequence_recv = 4
-      [ (gogoproto.moretags) = "yaml:\"next_sequence_recv\"" ];
-  string signer = 5;
+  Packet                    packet           = 1 [(gogoproto.nullable) = false];
+  bytes                     proof_unreceived = 2 [(gogoproto.moretags) = "yaml:\"proof_unreceived\""];
+  ibc.core.client.v1.Height proof_height     = 3
+      [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
+  uint64 next_sequence_recv = 4 [(gogoproto.moretags) = "yaml:\"next_sequence_recv\""];
+  string signer             = 5;
 }
 
 // MsgTimeoutResponse defines the Msg/Timeout response type.
@@ -201,20 +179,16 @@ message MsgTimeoutResponse {}
 
 // MsgTimeoutOnClose timed-out packet upon counterparty channel closure.
 message MsgTimeoutOnClose {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
-  Packet packet = 1 [ (gogoproto.nullable) = false ];
-  bytes proof_unreceived = 2
-      [ (gogoproto.moretags) = "yaml:\"proof_unreceived\"" ];
-  bytes proof_close = 3 [ (gogoproto.moretags) = "yaml:\"proof_close\"" ];
-  ibc.core.client.v1.Height proof_height = 4 [
-    (gogoproto.moretags) = "yaml:\"proof_height\"",
-    (gogoproto.nullable) = false
-  ];
-  uint64 next_sequence_recv = 5
-      [ (gogoproto.moretags) = "yaml:\"next_sequence_recv\"" ];
-  string signer = 6;
+  Packet                    packet           = 1 [(gogoproto.nullable) = false];
+  bytes                     proof_unreceived = 2 [(gogoproto.moretags) = "yaml:\"proof_unreceived\""];
+  bytes                     proof_close      = 3 [(gogoproto.moretags) = "yaml:\"proof_close\""];
+  ibc.core.client.v1.Height proof_height     = 4
+      [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
+  uint64 next_sequence_recv = 5 [(gogoproto.moretags) = "yaml:\"next_sequence_recv\""];
+  string signer             = 6;
 }
 
 // MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type.
@@ -222,16 +196,14 @@ message MsgTimeoutOnCloseResponse {}
 
 // MsgAcknowledgement receives incoming IBC acknowledgement
 message MsgAcknowledgement {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
-  Packet packet = 1 [ (gogoproto.nullable) = false ];
-  bytes acknowledgement = 2;
-  bytes proof_acked = 3 [ (gogoproto.moretags) = "yaml:\"proof_acked\"" ];
-  ibc.core.client.v1.Height proof_height = 4 [
-    (gogoproto.moretags) = "yaml:\"proof_height\"",
-    (gogoproto.nullable) = false
-  ];
+  Packet                    packet          = 1 [(gogoproto.nullable) = false];
+  bytes                     acknowledgement = 2;
+  bytes                     proof_acked     = 3 [(gogoproto.moretags) = "yaml:\"proof_acked\""];
+  ibc.core.client.v1.Height proof_height    = 4
+      [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
   string signer = 5;
 }
 
diff --git a/proto/ibc/core/client/v1/client.proto b/proto/ibc/core/client/v1/client.proto
index 927287004b3..a4a2cc85def 100644
--- a/proto/ibc/core/client/v1/client.proto
+++ b/proto/ibc/core/client/v1/client.proto
@@ -12,32 +12,28 @@ import "cosmos/upgrade/v1beta1/upgrade.proto";
 // identifier field.
 message IdentifiedClientState {
   // client identifier
-  string client_id = 1 [ (gogoproto.moretags) = "yaml:\"client_id\"" ];
+  string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
   // client state
-  google.protobuf.Any client_state = 2
-      [ (gogoproto.moretags) = "yaml:\"client_state\"" ];
+  google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""];
 }
 
 // ConsensusStateWithHeight defines a consensus state with an additional height
 // field.
 message ConsensusStateWithHeight {
   // consensus state height
-  Height height = 1 [ (gogoproto.nullable) = false ];
+  Height height = 1 [(gogoproto.nullable) = false];
   // consensus state
-  google.protobuf.Any consensus_state = 2
-      [ (gogoproto.moretags) = "yaml\"consensus_state\"" ];
+  google.protobuf.Any consensus_state = 2 [(gogoproto.moretags) = "yaml\"consensus_state\""];
 }
 
 // ClientConsensusStates defines all the stored consensus states for a given
 // client.
 message ClientConsensusStates {
   // client identifier
-  string client_id = 1 [ (gogoproto.moretags) = "yaml:\"client_id\"" ];
+  string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
   // consensus states and their heights associated with the client
-  repeated ConsensusStateWithHeight consensus_states = 2 [
-    (gogoproto.moretags) = "yaml:\"consensus_states\"",
-    (gogoproto.nullable) = false
-  ];
+  repeated ConsensusStateWithHeight consensus_states = 2
+      [(gogoproto.moretags) = "yaml:\"consensus_states\"", (gogoproto.nullable) = false];
 }
 
 // ClientUpdateProposal is a governance proposal. If it passes, the substitute
@@ -53,30 +49,25 @@ message ClientUpdateProposal {
   // the description of the proposal
   string description = 2;
   // the client identifier for the client to be updated if the proposal passes
-  string subject_client_id = 3
-      [ (gogoproto.moretags) = "yaml:\"subject_client_id\"" ];
+  string subject_client_id = 3 [(gogoproto.moretags) = "yaml:\"subject_client_id\""];
   // the substitute client identifier for the client standing in for the subject
   // client
-  string substitute_client_id = 4
-      [ (gogoproto.moretags) = "yaml:\"susbtitute_client_id\"" ];
+  string substitute_client_id = 4 [(gogoproto.moretags) = "yaml:\"susbtitute_client_id\""];
   // the intital height to copy consensus states from the substitute to the
   // subject
-  Height initial_height = 5 [
-    (gogoproto.moretags) = "yaml:\"initial_height\"",
-    (gogoproto.nullable) = false
-  ];
+  Height initial_height = 5 [(gogoproto.moretags) = "yaml:\"initial_height\"", (gogoproto.nullable) = false];
 }
 
 // UpgradeProposal is a gov Content type for initiating an IBC breaking
 // upgrade.
 message UpgradeProposal {
-  option (gogoproto.goproto_getters) = false;
+  option (gogoproto.goproto_getters)  = false;
   option (gogoproto.goproto_stringer) = false;
-  option (gogoproto.equal) = true;
+  option (gogoproto.equal)            = true;
 
-  string title = 1;
-  string description = 2;
-  cosmos.upgrade.v1beta1.Plan plan = 3 [ (gogoproto.nullable) = false ];
+  string                      title       = 1;
+  string                      description = 2;
+  cosmos.upgrade.v1beta1.Plan plan        = 3 [(gogoproto.nullable) = false];
 
   // An UpgradedClientState must be provided to perform an IBC breaking upgrade.
   // This will make the chain commit to the correct upgraded (self) client state
@@ -84,8 +75,7 @@ message UpgradeProposal {
   // new upgraded client is valid by verifying a proof on the previous version
   // of the chain. This will allow IBC connections to persist smoothly across
   // planned chain upgrades
-  google.protobuf.Any upgraded_client_state = 4
-      [ (gogoproto.moretags) = "yaml:\"upgraded_client_state\"" ];
+  google.protobuf.Any upgraded_client_state = 4 [(gogoproto.moretags) = "yaml:\"upgraded_client_state\""];
 }
 
 // Height is a monotonically increasing data type
@@ -99,20 +89,17 @@ message UpgradeProposal {
 // height continues to be monitonically increasing even as the RevisionHeight
 // gets reset
 message Height {
-  option (gogoproto.goproto_getters) = false;
+  option (gogoproto.goproto_getters)  = false;
   option (gogoproto.goproto_stringer) = false;
 
   // the revision that the client is currently on
-  uint64 revision_number = 1
-      [ (gogoproto.moretags) = "yaml:\"revision_number\"" ];
+  uint64 revision_number = 1 [(gogoproto.moretags) = "yaml:\"revision_number\""];
   // the height within the given revision
-  uint64 revision_height = 2
-      [ (gogoproto.moretags) = "yaml:\"revision_height\"" ];
+  uint64 revision_height = 2 [(gogoproto.moretags) = "yaml:\"revision_height\""];
 }
 
 // Params defines the set of IBC light client parameters.
 message Params {
   // allowed_clients defines the list of allowed client state types.
-  repeated string allowed_clients = 1
-      [ (gogoproto.moretags) = "yaml:\"allowed_clients\"" ];
+  repeated string allowed_clients = 1 [(gogoproto.moretags) = "yaml:\"allowed_clients\""];
 }
diff --git a/proto/ibc/core/client/v1/genesis.proto b/proto/ibc/core/client/v1/genesis.proto
index d6a74256afc..30592cf725f 100644
--- a/proto/ibc/core/client/v1/genesis.proto
+++ b/proto/ibc/core/client/v1/genesis.proto
@@ -10,28 +10,22 @@ import "gogoproto/gogo.proto";
 // GenesisState defines the ibc client submodule's genesis state.
 message GenesisState {
   // client states with their corresponding identifiers
-  repeated IdentifiedClientState clients = 1 [
-    (gogoproto.nullable) = false,
-    (gogoproto.castrepeated) = "IdentifiedClientStates"
-  ];
+  repeated IdentifiedClientState clients = 1
+      [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "IdentifiedClientStates"];
   // consensus states from each client
   repeated ClientConsensusStates clients_consensus = 2 [
-    (gogoproto.nullable) = false,
+    (gogoproto.nullable)     = false,
     (gogoproto.castrepeated) = "ClientsConsensusStates",
-    (gogoproto.moretags) = "yaml:\"clients_consensus\""
+    (gogoproto.moretags)     = "yaml:\"clients_consensus\""
   ];
   // metadata from each client
-  repeated IdentifiedGenesisMetadata clients_metadata = 3 [
-    (gogoproto.nullable) = false,
-    (gogoproto.moretags) = "yaml:\"clients_metadata\""
-  ];
-  Params params = 4 [ (gogoproto.nullable) = false ];
+  repeated IdentifiedGenesisMetadata clients_metadata = 3
+      [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"clients_metadata\""];
+  Params params = 4 [(gogoproto.nullable) = false];
   // create localhost on initialization
-  bool create_localhost = 5
-      [ (gogoproto.moretags) = "yaml:\"create_localhost\"" ];
+  bool create_localhost = 5 [(gogoproto.moretags) = "yaml:\"create_localhost\""];
   // the sequence for the next generated client identifier
-  uint64 next_client_sequence = 6
-      [ (gogoproto.moretags) = "yaml:\"next_client_sequence\"" ];
+  uint64 next_client_sequence = 6 [(gogoproto.moretags) = "yaml:\"next_client_sequence\""];
 }
 
 // GenesisMetadata defines the genesis type for metadata that clients may return
@@ -48,9 +42,7 @@ message GenesisMetadata {
 // IdentifiedGenesisMetadata has the client metadata with the corresponding
 // client id.
 message IdentifiedGenesisMetadata {
-  string client_id = 1 [ (gogoproto.moretags) = "yaml:\"client_id\"" ];
-  repeated GenesisMetadata client_metadata = 2 [
-    (gogoproto.nullable) = false,
-    (gogoproto.moretags) = "yaml:\"client_metadata\""
-  ];
+  string                   client_id       = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
+  repeated GenesisMetadata client_metadata = 2
+      [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"client_metadata\""];
 }
diff --git a/proto/ibc/core/client/v1/query.proto b/proto/ibc/core/client/v1/query.proto
index 0aa988ba247..36a5135702d 100644
--- a/proto/ibc/core/client/v1/query.proto
+++ b/proto/ibc/core/client/v1/query.proto
@@ -14,20 +14,17 @@ import "gogoproto/gogo.proto";
 service Query {
   // ClientState queries an IBC light client.
   rpc ClientState(QueryClientStateRequest) returns (QueryClientStateResponse) {
-    option (google.api.http).get =
-        "/ibc/core/client/v1/client_states/{client_id}";
+    option (google.api.http).get = "/ibc/core/client/v1/client_states/{client_id}";
   }
 
   // ClientStates queries all the IBC light clients of a chain.
-  rpc ClientStates(QueryClientStatesRequest)
-      returns (QueryClientStatesResponse) {
+  rpc ClientStates(QueryClientStatesRequest) returns (QueryClientStatesResponse) {
     option (google.api.http).get = "/ibc/core/client/v1/client_states";
   }
 
   // ConsensusState queries a consensus state associated with a client state at
   // a given height.
-  rpc ConsensusState(QueryConsensusStateRequest)
-      returns (QueryConsensusStateResponse) {
+  rpc ConsensusState(QueryConsensusStateRequest) returns (QueryConsensusStateResponse) {
     option (google.api.http).get = "/ibc/core/client/v1/consensus_states/"
                                    "{client_id}/revision/{revision_number}/"
                                    "height/{revision_height}";
@@ -35,30 +32,28 @@ service Query {
 
   // ConsensusStates queries all the consensus state associated with a given
   // client.
-  rpc ConsensusStates(QueryConsensusStatesRequest)
-      returns (QueryConsensusStatesResponse) {
-    option (google.api.http).get =
-        "/ibc/core/client/v1/consensus_states/{client_id}";
+  rpc ConsensusStates(QueryConsensusStatesRequest) returns (QueryConsensusStatesResponse) {
+    option (google.api.http).get = "/ibc/core/client/v1/consensus_states/{client_id}";
+  }
+
+  // Status queries the status of an IBC client.
+  rpc ClientStatus(QueryClientStatusRequest) returns (QueryClientStatusResponse) {
+    option (google.api.http).get = "/ibc/core/client/v1/client_status/{client_id}";
   }
 
   // ClientParams queries all parameters of the ibc client.
-  rpc ClientParams(QueryClientParamsRequest)
-      returns (QueryClientParamsResponse) {
+  rpc ClientParams(QueryClientParamsRequest) returns (QueryClientParamsResponse) {
     option (google.api.http).get = "/ibc/client/v1/params";
   }
 
   // UpgradedClientState queries an Upgraded IBC light client.
-  rpc UpgradedClientState(QueryUpgradedClientStateRequest)
-      returns (QueryUpgradedClientStateResponse) {
-    option (google.api.http).get =
-        "/ibc/core/client/v1/upgraded_client_states";
+  rpc UpgradedClientState(QueryUpgradedClientStateRequest) returns (QueryUpgradedClientStateResponse) {
+    option (google.api.http).get = "/ibc/core/client/v1/upgraded_client_states";
   }
 
   // UpgradedConsensusState queries an Upgraded IBC consensus state.
-  rpc UpgradedConsensusState(QueryUpgradedConsensusStateRequest)
-      returns (QueryUpgradedConsensusStateResponse) {
-    option (google.api.http).get =
-        "/ibc/core/client/v1/upgraded_consensus_states";
+  rpc UpgradedConsensusState(QueryUpgradedConsensusStateRequest) returns (QueryUpgradedConsensusStateResponse) {
+    option (google.api.http).get = "/ibc/core/client/v1/upgraded_consensus_states";
   }
 }
 
@@ -78,7 +73,7 @@ message QueryClientStateResponse {
   // merkle proof of existence
   bytes proof = 2;
   // height at which the proof was retrieved
-  ibc.core.client.v1.Height proof_height = 3 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false];
 }
 
 // QueryClientStatesRequest is the request type for the Query/ClientStates RPC
@@ -92,10 +87,8 @@ message QueryClientStatesRequest {
 // method.
 message QueryClientStatesResponse {
   // list of stored ClientStates of the chain.
-  repeated IdentifiedClientState client_states = 1 [
-    (gogoproto.nullable) = false,
-    (gogoproto.castrepeated) = "IdentifiedClientStates"
-  ];
+  repeated IdentifiedClientState client_states = 1
+      [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "IdentifiedClientStates"];
   // pagination response
   cosmos.base.query.v1beta1.PageResponse pagination = 2;
 }
@@ -123,7 +116,7 @@ message QueryConsensusStateResponse {
   // merkle proof of existence
   bytes proof = 2;
   // height at which the proof was retrieved
-  ibc.core.client.v1.Height proof_height = 3 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false];
 }
 
 // QueryConsensusStatesRequest is the request type for the Query/ConsensusStates
@@ -139,12 +132,24 @@ message QueryConsensusStatesRequest {
 // Query/ConsensusStates RPC method
 message QueryConsensusStatesResponse {
   // consensus states associated with the identifier
-  repeated ConsensusStateWithHeight consensus_states = 1
-      [ (gogoproto.nullable) = false ];
+  repeated ConsensusStateWithHeight consensus_states = 1 [(gogoproto.nullable) = false];
   // pagination response
   cosmos.base.query.v1beta1.PageResponse pagination = 2;
 }
 
+// QueryClientStatusRequest is the request type for the Query/ClientStatus RPC
+// method
+message QueryClientStatusRequest {
+  // client unique identifier
+  string client_id = 1;
+}
+
+// QueryClientStatusResponse is the response type for the Query/ClientStatus RPC
+// method. It returns the current status of the IBC client.
+message QueryClientStatusResponse {
+  string status = 1;
+}
+
 // QueryClientParamsRequest is the request type for the Query/ClientParams RPC
 // method.
 message QueryClientParamsRequest {}
@@ -158,7 +163,7 @@ message QueryClientParamsResponse {
 
 // QueryUpgradedClientStateRequest is the request type for the
 // Query/UpgradedClientState RPC method
-message QueryUpgradedClientStateRequest { }
+message QueryUpgradedClientStateRequest {}
 
 // QueryUpgradedClientStateResponse is the response type for the
 // Query/UpgradedClientState RPC method.
@@ -169,7 +174,7 @@ message QueryUpgradedClientStateResponse {
 
 // QueryUpgradedConsensusStateRequest is the request type for the
 // Query/UpgradedConsensusState RPC method
-message QueryUpgradedConsensusStateRequest { }
+message QueryUpgradedConsensusStateRequest {}
 
 // QueryUpgradedConsensusStateResponse is the response type for the
 // Query/UpgradedConsensusState RPC method.
diff --git a/proto/ibc/core/client/v1/tx.proto b/proto/ibc/core/client/v1/tx.proto
index 56f12911fe5..35386adb8a8 100644
--- a/proto/ibc/core/client/v1/tx.proto
+++ b/proto/ibc/core/client/v1/tx.proto
@@ -20,22 +20,19 @@ service Msg {
   rpc UpgradeClient(MsgUpgradeClient) returns (MsgUpgradeClientResponse);
 
   // SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour.
-  rpc SubmitMisbehaviour(MsgSubmitMisbehaviour)
-      returns (MsgSubmitMisbehaviourResponse);
+  rpc SubmitMisbehaviour(MsgSubmitMisbehaviour) returns (MsgSubmitMisbehaviourResponse);
 }
 
 // MsgCreateClient defines a message to create an IBC client
 message MsgCreateClient {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
   // light client state
-  google.protobuf.Any client_state = 1
-      [ (gogoproto.moretags) = "yaml:\"client_state\"" ];
+  google.protobuf.Any client_state = 1 [(gogoproto.moretags) = "yaml:\"client_state\""];
   // consensus state associated with the client that corresponds to a given
   // height.
-  google.protobuf.Any consensus_state = 2
-      [ (gogoproto.moretags) = "yaml:\"consensus_state\"" ];
+  google.protobuf.Any consensus_state = 2 [(gogoproto.moretags) = "yaml:\"consensus_state\""];
   // signer address
   string signer = 3;
 }
@@ -46,11 +43,11 @@ message MsgCreateClientResponse {}
 // MsgUpdateClient defines an sdk.Msg to update a IBC client state using
 // the given header.
 message MsgUpdateClient {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
   // client unique identifier
-  string client_id = 1 [ (gogoproto.moretags) = "yaml:\"client_id\"" ];
+  string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
   // header to update the light client
   google.protobuf.Any header = 2;
   // signer address
@@ -63,24 +60,20 @@ message MsgUpdateClientResponse {}
 // MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client
 // state
 message MsgUpgradeClient {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
   // client unique identifier
-  string client_id = 1 [ (gogoproto.moretags) = "yaml:\"client_id\"" ];
+  string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
   // upgraded client state
-  google.protobuf.Any client_state = 2
-      [ (gogoproto.moretags) = "yaml:\"client_state\"" ];
+  google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""];
   // upgraded consensus state, only contains enough information to serve as a
   // basis of trust in update logic
-  google.protobuf.Any consensus_state = 3
-      [ (gogoproto.moretags) = "yaml:\"consensus_state\"" ];
+  google.protobuf.Any consensus_state = 3 [(gogoproto.moretags) = "yaml:\"consensus_state\""];
   // proof that old chain committed to new client
-  bytes proof_upgrade_client = 4
-      [ (gogoproto.moretags) = "yaml:\"proof_upgrade_client\"" ];
+  bytes proof_upgrade_client = 4 [(gogoproto.moretags) = "yaml:\"proof_upgrade_client\""];
   // proof that old chain committed to new consensus state
-  bytes proof_upgrade_consensus_state = 5
-      [ (gogoproto.moretags) = "yaml:\"proof_upgrade_consensus_state\"" ];
+  bytes proof_upgrade_consensus_state = 5 [(gogoproto.moretags) = "yaml:\"proof_upgrade_consensus_state\""];
   // signer address
   string signer = 6;
 }
@@ -91,11 +84,11 @@ message MsgUpgradeClientResponse {}
 // MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for
 // light client misbehaviour.
 message MsgSubmitMisbehaviour {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
   // client unique identifier
-  string client_id = 1 [ (gogoproto.moretags) = "yaml:\"client_id\"" ];
+  string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
   // misbehaviour used for freezing the light client
   google.protobuf.Any misbehaviour = 2;
   // signer address
diff --git a/proto/ibc/core/commitment/v1/commitment.proto b/proto/ibc/core/commitment/v1/commitment.proto
index 4fc56fe82f3..47d8239422c 100644
--- a/proto/ibc/core/commitment/v1/commitment.proto
+++ b/proto/ibc/core/commitment/v1/commitment.proto
@@ -19,7 +19,7 @@ message MerkleRoot {
 // The constructed key from the Path and the key will be append(Path.KeyPath,
 // append(Path.KeyPrefix, key...))
 message MerklePrefix {
-  bytes key_prefix = 1 [ (gogoproto.moretags) = "yaml:\"key_prefix\"" ];
+  bytes key_prefix = 1 [(gogoproto.moretags) = "yaml:\"key_prefix\""];
 }
 
 // MerklePath is the path used to verify commitment proofs, which can be an
@@ -28,7 +28,7 @@ message MerklePrefix {
 message MerklePath {
   option (gogoproto.goproto_stringer) = false;
 
-  repeated string key_path = 1 [ (gogoproto.moretags) = "yaml:\"key_path\"" ];
+  repeated string key_path = 1 [(gogoproto.moretags) = "yaml:\"key_path\""];
 }
 
 // MerkleProof is a wrapper type over a chain of CommitmentProofs.
@@ -36,4 +36,6 @@ message MerklePath {
 // elements, verifiable in conjunction with a known commitment root. Proofs
 // should be succinct.
 // MerkleProofs are ordered from leaf-to-root
-message MerkleProof { repeated ics23.CommitmentProof proofs = 1; }
+message MerkleProof {
+  repeated ics23.CommitmentProof proofs = 1;
+}
diff --git a/proto/ibc/core/connection/v1/connection.proto b/proto/ibc/core/connection/v1/connection.proto
index c9112710b23..5b4e32bf856 100644
--- a/proto/ibc/core/connection/v1/connection.proto
+++ b/proto/ibc/core/connection/v1/connection.proto
@@ -17,18 +17,18 @@ import "ibc/core/commitment/v1/commitment.proto";
 message ConnectionEnd {
   option (gogoproto.goproto_getters) = false;
   // client associated with this connection.
-  string client_id = 1 [ (gogoproto.moretags) = "yaml:\"client_id\"" ];
+  string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
   // IBC version which can be utilised to determine encodings or protocols for
   // channels or packets utilising this connection.
   repeated Version versions = 2;
   // current state of the connection end.
   State state = 3;
   // counterparty chain associated with this connection.
-  Counterparty counterparty = 4 [ (gogoproto.nullable) = false ];
+  Counterparty counterparty = 4 [(gogoproto.nullable) = false];
   // delay period that must pass before a consensus state can be used for
   // packet-verification NOTE: delay period logic is only implemented by some
   // clients.
-  uint64 delay_period = 5 [ (gogoproto.moretags) = "yaml:\"delay_period\"" ];
+  uint64 delay_period = 5 [(gogoproto.moretags) = "yaml:\"delay_period\""];
 }
 
 // IdentifiedConnection defines a connection with additional connection
@@ -36,18 +36,18 @@ message ConnectionEnd {
 message IdentifiedConnection {
   option (gogoproto.goproto_getters) = false;
   // connection identifier.
-  string id = 1 [ (gogoproto.moretags) = "yaml:\"id\"" ];
+  string id = 1 [(gogoproto.moretags) = "yaml:\"id\""];
   // client associated with this connection.
-  string client_id = 2 [ (gogoproto.moretags) = "yaml:\"client_id\"" ];
+  string client_id = 2 [(gogoproto.moretags) = "yaml:\"client_id\""];
   // IBC version which can be utilised to determine encodings or protocols for
   // channels or packets utilising this connection
   repeated Version versions = 3;
   // current state of the connection end.
   State state = 4;
   // counterparty chain associated with this connection.
-  Counterparty counterparty = 5 [ (gogoproto.nullable) = false ];
+  Counterparty counterparty = 5 [(gogoproto.nullable) = false];
   // delay period associated with this connection.
-  uint64 delay_period = 6 [ (gogoproto.moretags) = "yaml:\"delay_period\"" ];
+  uint64 delay_period = 6 [(gogoproto.moretags) = "yaml:\"delay_period\""];
 }
 
 // State defines if a connection is in one of the following states:
@@ -56,15 +56,14 @@ enum State {
   option (gogoproto.goproto_enum_prefix) = false;
 
   // Default State
-  STATE_UNINITIALIZED_UNSPECIFIED = 0
-      [ (gogoproto.enumvalue_customname) = "UNINITIALIZED" ];
+  STATE_UNINITIALIZED_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "UNINITIALIZED"];
   // A connection end has just started the opening handshake.
-  STATE_INIT = 1 [ (gogoproto.enumvalue_customname) = "INIT" ];
+  STATE_INIT = 1 [(gogoproto.enumvalue_customname) = "INIT"];
   // A connection end has acknowledged the handshake step on the counterparty
   // chain.
-  STATE_TRYOPEN = 2 [ (gogoproto.enumvalue_customname) = "TRYOPEN" ];
+  STATE_TRYOPEN = 2 [(gogoproto.enumvalue_customname) = "TRYOPEN"];
   // A connection end has completed the handshake.
-  STATE_OPEN = 3 [ (gogoproto.enumvalue_customname) = "OPEN" ];
+  STATE_OPEN = 3 [(gogoproto.enumvalue_customname) = "OPEN"];
 }
 
 // Counterparty defines the counterparty chain associated with a connection end.
@@ -73,13 +72,12 @@ message Counterparty {
 
   // identifies the client on the counterparty chain associated with a given
   // connection.
-  string client_id = 1 [ (gogoproto.moretags) = "yaml:\"client_id\"" ];
+  string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
   // identifies the connection end on the counterparty chain associated with a
   // given connection.
-  string connection_id = 2 [ (gogoproto.moretags) = "yaml:\"connection_id\"" ];
+  string connection_id = 2 [(gogoproto.moretags) = "yaml:\"connection_id\""];
   // commitment merkle prefix of the counterparty chain.
-  ibc.core.commitment.v1.MerklePrefix prefix = 3
-      [ (gogoproto.nullable) = false ];
+  ibc.core.commitment.v1.MerklePrefix prefix = 3 [(gogoproto.nullable) = false];
 }
 
 // ClientPaths define all the connection paths for a client state.
@@ -91,7 +89,7 @@ message ClientPaths {
 // ConnectionPaths define all the connection paths for a given client state.
 message ConnectionPaths {
   // client state unique identifier
-  string client_id = 1 [ (gogoproto.moretags) = "yaml:\"client_id\"" ];
+  string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
   // list of connection paths
   repeated string paths = 2;
 }
diff --git a/proto/ibc/core/connection/v1/genesis.proto b/proto/ibc/core/connection/v1/genesis.proto
index 8a9d9fd0b96..62296e1e6dd 100644
--- a/proto/ibc/core/connection/v1/genesis.proto
+++ b/proto/ibc/core/connection/v1/genesis.proto
@@ -9,13 +9,9 @@ import "ibc/core/connection/v1/connection.proto";
 
 // GenesisState defines the ibc connection submodule's genesis state.
 message GenesisState {
-  repeated IdentifiedConnection connections = 1
-      [ (gogoproto.nullable) = false ];
-  repeated ConnectionPaths client_connection_paths = 2 [
-    (gogoproto.nullable) = false,
-    (gogoproto.moretags) = "yaml:\"client_connection_paths\""
-  ];
+  repeated IdentifiedConnection connections             = 1 [(gogoproto.nullable) = false];
+  repeated ConnectionPaths      client_connection_paths = 2
+      [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"client_connection_paths\""];
   // the sequence for the next generated connection identifier
-  uint64 next_connection_sequence = 3
-      [ (gogoproto.moretags) = "yaml:\"next_connection_sequence\"" ];
+  uint64 next_connection_sequence = 3 [(gogoproto.moretags) = "yaml:\"next_connection_sequence\""];
 }
diff --git a/proto/ibc/core/connection/v1/query.proto b/proto/ibc/core/connection/v1/query.proto
index efd29c2aee7..ca90e0eeb4f 100644
--- a/proto/ibc/core/connection/v1/query.proto
+++ b/proto/ibc/core/connection/v1/query.proto
@@ -15,8 +15,7 @@ import "google/protobuf/any.proto";
 service Query {
   // Connection queries an IBC connection end.
   rpc Connection(QueryConnectionRequest) returns (QueryConnectionResponse) {
-    option (google.api.http).get =
-        "/ibc/core/connection/v1/connections/{connection_id}";
+    option (google.api.http).get = "/ibc/core/connection/v1/connections/{connection_id}";
   }
 
   // Connections queries all the IBC connections of a chain.
@@ -26,27 +25,21 @@ service Query {
 
   // ClientConnections queries the connection paths associated with a client
   // state.
-  rpc ClientConnections(QueryClientConnectionsRequest)
-      returns (QueryClientConnectionsResponse) {
-    option (google.api.http).get =
-        "/ibc/core/connection/v1/client_connections/{client_id}";
+  rpc ClientConnections(QueryClientConnectionsRequest) returns (QueryClientConnectionsResponse) {
+    option (google.api.http).get = "/ibc/core/connection/v1/client_connections/{client_id}";
   }
 
   // ConnectionClientState queries the client state associated with the
   // connection.
-  rpc ConnectionClientState(QueryConnectionClientStateRequest)
-      returns (QueryConnectionClientStateResponse) {
-    option (google.api.http).get =
-        "/ibc/core/connection/v1/connections/{connection_id}/client_state";
+  rpc ConnectionClientState(QueryConnectionClientStateRequest) returns (QueryConnectionClientStateResponse) {
+    option (google.api.http).get = "/ibc/core/connection/v1/connections/{connection_id}/client_state";
   }
 
   // ConnectionConsensusState queries the consensus state associated with the
   // connection.
-  rpc ConnectionConsensusState(QueryConnectionConsensusStateRequest)
-      returns (QueryConnectionConsensusStateResponse) {
-    option (google.api.http).get =
-        "/ibc/core/connection/v1/connections/{connection_id}/consensus_state/"
-        "revision/{revision_number}/height/{revision_height}";
+  rpc ConnectionConsensusState(QueryConnectionConsensusStateRequest) returns (QueryConnectionConsensusStateResponse) {
+    option (google.api.http).get = "/ibc/core/connection/v1/connections/{connection_id}/consensus_state/"
+                                   "revision/{revision_number}/height/{revision_height}";
   }
 }
 
@@ -66,7 +59,7 @@ message QueryConnectionResponse {
   // merkle proof of existence
   bytes proof = 2;
   // height at which the proof was retrieved
-  ibc.core.client.v1.Height proof_height = 3 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false];
 }
 
 // QueryConnectionsRequest is the request type for the Query/Connections RPC
@@ -83,7 +76,7 @@ message QueryConnectionsResponse {
   // pagination response
   cosmos.base.query.v1beta1.PageResponse pagination = 2;
   // query block height
-  ibc.core.client.v1.Height height = 3 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height height = 3 [(gogoproto.nullable) = false];
 }
 
 // QueryClientConnectionsRequest is the request type for the
@@ -101,14 +94,14 @@ message QueryClientConnectionsResponse {
   // merkle proof of existence
   bytes proof = 2;
   // height at which the proof was generated
-  ibc.core.client.v1.Height proof_height = 3 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false];
 }
 
 // QueryConnectionClientStateRequest is the request type for the
 // Query/ConnectionClientState RPC method
 message QueryConnectionClientStateRequest {
   // connection identifier
-  string connection_id = 1 [ (gogoproto.moretags) = "yaml:\"connection_id\"" ];
+  string connection_id = 1 [(gogoproto.moretags) = "yaml:\"connection_id\""];
 }
 
 // QueryConnectionClientStateResponse is the response type for the
@@ -119,14 +112,14 @@ message QueryConnectionClientStateResponse {
   // merkle proof of existence
   bytes proof = 2;
   // height at which the proof was retrieved
-  ibc.core.client.v1.Height proof_height = 3 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false];
 }
 
 // QueryConnectionConsensusStateRequest is the request type for the
 // Query/ConnectionConsensusState RPC method
 message QueryConnectionConsensusStateRequest {
   // connection identifier
-  string connection_id = 1 [ (gogoproto.moretags) = "yaml:\"connection_id\"" ];
+  string connection_id   = 1 [(gogoproto.moretags) = "yaml:\"connection_id\""];
   uint64 revision_number = 2;
   uint64 revision_height = 3;
 }
@@ -141,5 +134,5 @@ message QueryConnectionConsensusStateResponse {
   // merkle proof of existence
   bytes proof = 3;
   // height at which the proof was retrieved
-  ibc.core.client.v1.Height proof_height = 4 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height proof_height = 4 [(gogoproto.nullable) = false];
 }
diff --git a/proto/ibc/core/connection/v1/tx.proto b/proto/ibc/core/connection/v1/tx.proto
index 2a71469c0af..6318f9fd251 100644
--- a/proto/ibc/core/connection/v1/tx.proto
+++ b/proto/ibc/core/connection/v1/tx.proto
@@ -12,34 +12,30 @@ import "ibc/core/connection/v1/connection.proto";
 // Msg defines the ibc/connection Msg service.
 service Msg {
   // ConnectionOpenInit defines a rpc handler method for MsgConnectionOpenInit.
-  rpc ConnectionOpenInit(MsgConnectionOpenInit)
-      returns (MsgConnectionOpenInitResponse);
+  rpc ConnectionOpenInit(MsgConnectionOpenInit) returns (MsgConnectionOpenInitResponse);
 
   // ConnectionOpenTry defines a rpc handler method for MsgConnectionOpenTry.
-  rpc ConnectionOpenTry(MsgConnectionOpenTry)
-      returns (MsgConnectionOpenTryResponse);
+  rpc ConnectionOpenTry(MsgConnectionOpenTry) returns (MsgConnectionOpenTryResponse);
 
   // ConnectionOpenAck defines a rpc handler method for MsgConnectionOpenAck.
-  rpc ConnectionOpenAck(MsgConnectionOpenAck)
-      returns (MsgConnectionOpenAckResponse);
+  rpc ConnectionOpenAck(MsgConnectionOpenAck) returns (MsgConnectionOpenAckResponse);
 
   // ConnectionOpenConfirm defines a rpc handler method for
   // MsgConnectionOpenConfirm.
-  rpc ConnectionOpenConfirm(MsgConnectionOpenConfirm)
-      returns (MsgConnectionOpenConfirmResponse);
+  rpc ConnectionOpenConfirm(MsgConnectionOpenConfirm) returns (MsgConnectionOpenConfirmResponse);
 }
 
 // MsgConnectionOpenInit defines the msg sent by an account on Chain A to
 // initialize a connection with Chain B.
 message MsgConnectionOpenInit {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
-  string client_id = 1 [ (gogoproto.moretags) = "yaml:\"client_id\"" ];
-  Counterparty counterparty = 2 [ (gogoproto.nullable) = false ];
-  Version version = 3;
-  uint64 delay_period = 4 [ (gogoproto.moretags) = "yaml:\"delay_period\"" ];
-  string signer = 5;
+  string       client_id    = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
+  Counterparty counterparty = 2 [(gogoproto.nullable) = false];
+  Version      version      = 3;
+  uint64       delay_period = 4 [(gogoproto.moretags) = "yaml:\"delay_period\""];
+  string       signer       = 5;
 }
 
 // MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response
@@ -49,36 +45,28 @@ message MsgConnectionOpenInitResponse {}
 // MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a
 // connection on Chain B.
 message MsgConnectionOpenTry {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
-  string client_id = 1 [ (gogoproto.moretags) = "yaml:\"client_id\"" ];
+  string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
   // in the case of crossing hello's, when both chains call OpenInit, we need
   // the connection identifier of the previous connection in state INIT
-  string previous_connection_id = 2
-      [ (gogoproto.moretags) = "yaml:\"previous_connection_id\"" ];
-  google.protobuf.Any client_state = 3
-      [ (gogoproto.moretags) = "yaml:\"client_state\"" ];
-  Counterparty counterparty = 4 [ (gogoproto.nullable) = false ];
-  uint64 delay_period = 5 [ (gogoproto.moretags) = "yaml:\"delay_period\"" ];
-  repeated Version counterparty_versions = 6
-      [ (gogoproto.moretags) = "yaml:\"counterparty_versions\"" ];
-  ibc.core.client.v1.Height proof_height = 7 [
-    (gogoproto.moretags) = "yaml:\"proof_height\"",
-    (gogoproto.nullable) = false
-  ];
+  string                    previous_connection_id = 2 [(gogoproto.moretags) = "yaml:\"previous_connection_id\""];
+  google.protobuf.Any       client_state           = 3 [(gogoproto.moretags) = "yaml:\"client_state\""];
+  Counterparty              counterparty           = 4 [(gogoproto.nullable) = false];
+  uint64                    delay_period           = 5 [(gogoproto.moretags) = "yaml:\"delay_period\""];
+  repeated Version          counterparty_versions  = 6 [(gogoproto.moretags) = "yaml:\"counterparty_versions\""];
+  ibc.core.client.v1.Height proof_height           = 7
+      [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
   // proof of the initialization the connection on Chain A: `UNITIALIZED ->
   // INIT`
-  bytes proof_init = 8 [ (gogoproto.moretags) = "yaml:\"proof_init\"" ];
+  bytes proof_init = 8 [(gogoproto.moretags) = "yaml:\"proof_init\""];
   // proof of client state included in message
-  bytes proof_client = 9 [ (gogoproto.moretags) = "yaml:\"proof_client\"" ];
+  bytes proof_client = 9 [(gogoproto.moretags) = "yaml:\"proof_client\""];
   // proof of client consensus state
-  bytes proof_consensus = 10
-      [ (gogoproto.moretags) = "yaml:\"proof_consensus\"" ];
-  ibc.core.client.v1.Height consensus_height = 11 [
-    (gogoproto.moretags) = "yaml:\"consensus_height\"",
-    (gogoproto.nullable) = false
-  ];
+  bytes                     proof_consensus  = 10 [(gogoproto.moretags) = "yaml:\"proof_consensus\""];
+  ibc.core.client.v1.Height consensus_height = 11
+      [(gogoproto.moretags) = "yaml:\"consensus_height\"", (gogoproto.nullable) = false];
   string signer = 12;
 }
 
@@ -88,31 +76,24 @@ message MsgConnectionOpenTryResponse {}
 // MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to
 // acknowledge the change of connection state to TRYOPEN on Chain B.
 message MsgConnectionOpenAck {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
-  string connection_id = 1 [ (gogoproto.moretags) = "yaml:\"connection_id\"" ];
-  string counterparty_connection_id = 2
-      [ (gogoproto.moretags) = "yaml:\"counterparty_connection_id\"" ];
-  Version version = 3;
-  google.protobuf.Any client_state = 4
-      [ (gogoproto.moretags) = "yaml:\"client_state\"" ];
-  ibc.core.client.v1.Height proof_height = 5 [
-    (gogoproto.moretags) = "yaml:\"proof_height\"",
-    (gogoproto.nullable) = false
-  ];
+  string              connection_id              = 1 [(gogoproto.moretags) = "yaml:\"connection_id\""];
+  string              counterparty_connection_id = 2 [(gogoproto.moretags) = "yaml:\"counterparty_connection_id\""];
+  Version             version                    = 3;
+  google.protobuf.Any client_state               = 4 [(gogoproto.moretags) = "yaml:\"client_state\""];
+  ibc.core.client.v1.Height proof_height         = 5
+      [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
   // proof of the initialization the connection on Chain B: `UNITIALIZED ->
   // TRYOPEN`
-  bytes proof_try = 6 [ (gogoproto.moretags) = "yaml:\"proof_try\"" ];
+  bytes proof_try = 6 [(gogoproto.moretags) = "yaml:\"proof_try\""];
   // proof of client state included in message
-  bytes proof_client = 7 [ (gogoproto.moretags) = "yaml:\"proof_client\"" ];
+  bytes proof_client = 7 [(gogoproto.moretags) = "yaml:\"proof_client\""];
   // proof of client consensus state
-  bytes proof_consensus = 8
-      [ (gogoproto.moretags) = "yaml:\"proof_consensus\"" ];
-  ibc.core.client.v1.Height consensus_height = 9 [
-    (gogoproto.moretags) = "yaml:\"consensus_height\"",
-    (gogoproto.nullable) = false
-  ];
+  bytes                     proof_consensus  = 8 [(gogoproto.moretags) = "yaml:\"proof_consensus\""];
+  ibc.core.client.v1.Height consensus_height = 9
+      [(gogoproto.moretags) = "yaml:\"consensus_height\"", (gogoproto.nullable) = false];
   string signer = 10;
 }
 
@@ -122,16 +103,14 @@ message MsgConnectionOpenAckResponse {}
 // MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to
 // acknowledge the change of connection state to OPEN on Chain A.
 message MsgConnectionOpenConfirm {
-  option (gogoproto.equal) = false;
+  option (gogoproto.equal)           = false;
   option (gogoproto.goproto_getters) = false;
 
-  string connection_id = 1 [ (gogoproto.moretags) = "yaml:\"connection_id\"" ];
+  string connection_id = 1 [(gogoproto.moretags) = "yaml:\"connection_id\""];
   // proof for the change of the connection state on Chain A: `INIT -> OPEN`
-  bytes proof_ack = 2 [ (gogoproto.moretags) = "yaml:\"proof_ack\"" ];
-  ibc.core.client.v1.Height proof_height = 3 [
-    (gogoproto.moretags) = "yaml:\"proof_height\"",
-    (gogoproto.nullable) = false
-  ];
+  bytes                     proof_ack    = 2 [(gogoproto.moretags) = "yaml:\"proof_ack\""];
+  ibc.core.client.v1.Height proof_height = 3
+      [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
   string signer = 4;
 }
 
diff --git a/proto/ibc/core/types/v1/genesis.proto b/proto/ibc/core/types/v1/genesis.proto
index 2b5f9cd2aa0..2451da3233a 100644
--- a/proto/ibc/core/types/v1/genesis.proto
+++ b/proto/ibc/core/types/v1/genesis.proto
@@ -12,18 +12,12 @@ import "ibc/core/channel/v1/genesis.proto";
 // GenesisState defines the ibc module's genesis state.
 message GenesisState {
   // ICS002 - Clients genesis state
-  ibc.core.client.v1.GenesisState client_genesis = 1 [
-    (gogoproto.nullable) = false,
-    (gogoproto.moretags) = "yaml:\"client_genesis\""
-  ];
+  ibc.core.client.v1.GenesisState client_genesis = 1
+      [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"client_genesis\""];
   // ICS003 - Connections genesis state
-  ibc.core.connection.v1.GenesisState connection_genesis = 2 [
-    (gogoproto.nullable) = false,
-    (gogoproto.moretags) = "yaml:\"connection_genesis\""
-  ];
+  ibc.core.connection.v1.GenesisState connection_genesis = 2
+      [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"connection_genesis\""];
   // ICS004 - Channel genesis state
-  ibc.core.channel.v1.GenesisState channel_genesis = 3 [
-    (gogoproto.nullable) = false,
-    (gogoproto.moretags) = "yaml:\"channel_genesis\""
-  ];
+  ibc.core.channel.v1.GenesisState channel_genesis = 3
+      [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"channel_genesis\""];
 }
diff --git a/proto/ibc/lightclients/localhost/v1/localhost.proto b/proto/ibc/lightclients/localhost/v1/localhost.proto
index e090e0dea6b..77e17bc3276 100644
--- a/proto/ibc/lightclients/localhost/v1/localhost.proto
+++ b/proto/ibc/lightclients/localhost/v1/localhost.proto
@@ -12,7 +12,7 @@ import "ibc/core/client/v1/client.proto";
 message ClientState {
   option (gogoproto.goproto_getters) = false;
   // self chain ID
-  string chain_id = 1 [ (gogoproto.moretags) = "yaml:\"chain_id\"" ];
+  string chain_id = 1 [(gogoproto.moretags) = "yaml:\"chain_id\""];
   // self latest block height
-  ibc.core.client.v1.Height height = 2 [ (gogoproto.nullable) = false ];
+  ibc.core.client.v1.Height height = 2 [(gogoproto.nullable) = false];
 }
diff --git a/proto/ibc/lightclients/solomachine/v1/solomachine.proto b/proto/ibc/lightclients/solomachine/v1/solomachine.proto
index e7f2b022482..68f0c1ea4e4 100644
--- a/proto/ibc/lightclients/solomachine/v1/solomachine.proto
+++ b/proto/ibc/lightclients/solomachine/v1/solomachine.proto
@@ -16,14 +16,11 @@ message ClientState {
   // latest sequence of the client state
   uint64 sequence = 1;
   // frozen sequence of the solo machine
-  uint64 frozen_sequence = 2
-      [ (gogoproto.moretags) = "yaml:\"frozen_sequence\"" ];
-  ConsensusState consensus_state = 3
-      [ (gogoproto.moretags) = "yaml:\"consensus_state\"" ];
+  uint64         frozen_sequence = 2 [(gogoproto.moretags) = "yaml:\"frozen_sequence\""];
+  ConsensusState consensus_state = 3 [(gogoproto.moretags) = "yaml:\"consensus_state\""];
   // when set to true, will allow governance to update a solo machine client.
   // The client will be unfrozen if it is frozen.
-  bool allow_update_after_proposal = 4
-      [ (gogoproto.moretags) = "yaml:\"allow_update_after_proposal\"" ];
+  bool allow_update_after_proposal = 4 [(gogoproto.moretags) = "yaml:\"allow_update_after_proposal\""];
 }
 
 // ConsensusState defines a solo machine consensus state. The sequence of a
@@ -32,67 +29,62 @@ message ClientState {
 message ConsensusState {
   option (gogoproto.goproto_getters) = false;
   // public key of the solo machine
-  google.protobuf.Any public_key = 1
-      [ (gogoproto.moretags) = "yaml:\"public_key\"" ];
+  google.protobuf.Any public_key = 1 [(gogoproto.moretags) = "yaml:\"public_key\""];
   // diversifier allows the same public key to be re-used across different solo
   // machine clients (potentially on different chains) without being considered
   // misbehaviour.
   string diversifier = 2;
-  uint64 timestamp = 3;
+  uint64 timestamp   = 3;
 }
 
 // Header defines a solo machine consensus header
 message Header {
   option (gogoproto.goproto_getters) = false;
   // sequence to update solo machine public key at
-  uint64 sequence = 1;
-  uint64 timestamp = 2;
-  bytes signature = 3;
-  google.protobuf.Any new_public_key = 4
-      [ (gogoproto.moretags) = "yaml:\"new_public_key\"" ];
-  string new_diversifier = 5
-      [ (gogoproto.moretags) = "yaml:\"new_diversifier\"" ];
+  uint64              sequence        = 1;
+  uint64              timestamp       = 2;
+  bytes               signature       = 3;
+  google.protobuf.Any new_public_key  = 4 [(gogoproto.moretags) = "yaml:\"new_public_key\""];
+  string              new_diversifier = 5 [(gogoproto.moretags) = "yaml:\"new_diversifier\""];
 }
 
 // Misbehaviour defines misbehaviour for a solo machine which consists
 // of a sequence and two signatures over different messages at that sequence.
 message Misbehaviour {
   option (gogoproto.goproto_getters) = false;
-  string client_id = 1 [ (gogoproto.moretags) = "yaml:\"client_id\"" ];
-  uint64 sequence = 2;
-  SignatureAndData signature_one = 3
-      [ (gogoproto.moretags) = "yaml:\"signature_one\"" ];
-  SignatureAndData signature_two = 4
-      [ (gogoproto.moretags) = "yaml:\"signature_two\"" ];
+  string           client_id         = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
+  uint64           sequence          = 2;
+  SignatureAndData signature_one     = 3 [(gogoproto.moretags) = "yaml:\"signature_one\""];
+  SignatureAndData signature_two     = 4 [(gogoproto.moretags) = "yaml:\"signature_two\""];
 }
 
 // SignatureAndData contains a signature and the data signed over to create that
 // signature.
 message SignatureAndData {
   option (gogoproto.goproto_getters) = false;
-  bytes signature = 1;
-  DataType data_type = 2 [ (gogoproto.moretags) = "yaml:\"data_type\"" ];
-  bytes data = 3;
-  uint64 timestamp = 4;
+  bytes    signature                 = 1;
+  DataType data_type                 = 2 [(gogoproto.moretags) = "yaml:\"data_type\""];
+  bytes    data                      = 3;
+  uint64   timestamp                 = 4;
 }
 
 // TimestampedSignatureData contains the signature data and the timestamp of the
 // signature.
 message TimestampedSignatureData {
   option (gogoproto.goproto_getters) = false;
-  bytes signature_data = 1 [ (gogoproto.moretags) = "yaml:\"signature_data\"" ];
-  uint64 timestamp = 2;
+  bytes  signature_data              = 1 [(gogoproto.moretags) = "yaml:\"signature_data\""];
+  uint64 timestamp                   = 2;
 }
 
 // SignBytes defines the signed bytes used for signature verification.
 message SignBytes {
   option (gogoproto.goproto_getters) = false;
 
-  uint64 sequence = 1;
-  uint64 timestamp = 2;
+  uint64 sequence    = 1;
+  uint64 timestamp   = 2;
   string diversifier = 3;
   // type of the data used
-  DataType data_type = 4 [ (gogoproto.moretags) = "yaml:\"data_type\"" ];
+  DataType data_type = 4 [(gogoproto.moretags) = "yaml:\"data_type\""];
   // marshaled data
   bytes data = 5;
 }
@@ -103,32 +95,25 @@ enum DataType {
   option (gogoproto.goproto_enum_prefix) = false;
 
   // Default State
-  DATA_TYPE_UNINITIALIZED_UNSPECIFIED = 0
-      [ (gogoproto.enumvalue_customname) = "UNSPECIFIED" ];
+  DATA_TYPE_UNINITIALIZED_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "UNSPECIFIED"];
   // Data type for client state verification
-  DATA_TYPE_CLIENT_STATE = 1 [ (gogoproto.enumvalue_customname) = "CLIENT" ];
+  DATA_TYPE_CLIENT_STATE = 1 [(gogoproto.enumvalue_customname) = "CLIENT"];
   // Data type for consensus state verification
-  DATA_TYPE_CONSENSUS_STATE = 2
-      [ (gogoproto.enumvalue_customname) = "CONSENSUS" ];
+  DATA_TYPE_CONSENSUS_STATE = 2 [(gogoproto.enumvalue_customname) = "CONSENSUS"];
   // Data type for connection state verification
-  DATA_TYPE_CONNECTION_STATE = 3
-      [ (gogoproto.enumvalue_customname) = "CONNECTION" ];
+  DATA_TYPE_CONNECTION_STATE = 3 [(gogoproto.enumvalue_customname) = "CONNECTION"];
   // Data type for channel state verification
-  DATA_TYPE_CHANNEL_STATE = 4 [ (gogoproto.enumvalue_customname) = "CHANNEL" ];
+  DATA_TYPE_CHANNEL_STATE = 4 [(gogoproto.enumvalue_customname) = "CHANNEL"];
   // Data type for packet commitment verification
-  DATA_TYPE_PACKET_COMMITMENT = 5
-      [ (gogoproto.enumvalue_customname) = "PACKETCOMMITMENT" ];
+  DATA_TYPE_PACKET_COMMITMENT = 5 [(gogoproto.enumvalue_customname) = "PACKETCOMMITMENT"];
   // Data type for packet acknowledgement verification
-  DATA_TYPE_PACKET_ACKNOWLEDGEMENT = 6
-      [ (gogoproto.enumvalue_customname) = "PACKETACKNOWLEDGEMENT" ];
+  DATA_TYPE_PACKET_ACKNOWLEDGEMENT = 6 [(gogoproto.enumvalue_customname) = "PACKETACKNOWLEDGEMENT"];
   // Data type for packet receipt absence verification
-  DATA_TYPE_PACKET_RECEIPT_ABSENCE = 7
-      [ (gogoproto.enumvalue_customname) = "PACKETRECEIPTABSENCE" ];
+  DATA_TYPE_PACKET_RECEIPT_ABSENCE = 7 [(gogoproto.enumvalue_customname) = "PACKETRECEIPTABSENCE"];
   // Data type for next sequence recv verification
-  DATA_TYPE_NEXT_SEQUENCE_RECV = 8
-      [ (gogoproto.enumvalue_customname) = "NEXTSEQUENCERECV" ];
+  DATA_TYPE_NEXT_SEQUENCE_RECV = 8 [(gogoproto.enumvalue_customname) = "NEXTSEQUENCERECV"];
   // Data type for header verification
-  DATA_TYPE_HEADER = 9 [ (gogoproto.enumvalue_customname) = "HEADER" ];
+  DATA_TYPE_HEADER = 9 [(gogoproto.enumvalue_customname) = "HEADER"];
 }
 
 // HeaderData returns the SignBytes data for update verification.
@@ -136,20 +121,17 @@ message HeaderData {
   option (gogoproto.goproto_getters) = false;
 
   // header public key
-  google.protobuf.Any new_pub_key = 1
-      [ (gogoproto.moretags) = "yaml:\"new_pub_key\"" ];
+  google.protobuf.Any new_pub_key = 1 [(gogoproto.moretags) = "yaml:\"new_pub_key\""];
   // header diversifier
-  string new_diversifier = 2
-      [ (gogoproto.moretags) = "yaml:\"new_diversifier\"" ];
+  string new_diversifier = 2 [(gogoproto.moretags) = "yaml:\"new_diversifier\""];
 }
 
 // ClientStateData returns the SignBytes data for client state verification.
 message ClientStateData {
   option (gogoproto.goproto_getters) = false;
 
-  bytes path = 1;
-  google.protobuf.Any client_state = 2
-      [ (gogoproto.moretags) = "yaml:\"client_state\"" ];
+  bytes               path         = 1;
+  google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""];
 }
 
 // ConsensusStateData returns the SignBytes data for consensus state
@@ -157,9 +139,8 @@ message ClientStateData {
 message ConsensusStateData {
   option (gogoproto.goproto_getters) = false;
 
-  bytes path = 1;
-  google.protobuf.Any consensus_state = 2
-      [ (gogoproto.moretags) = "yaml:\"consensus_state\"" ];
+  bytes               path            = 1;
+  google.protobuf.Any consensus_state = 2 [(gogoproto.moretags) = "yaml:\"consensus_state\""];
 }
 
 // ConnectionStateData returns the SignBytes data for connection state
@@ -167,7 +148,7 @@ message ConsensusStateData {
 message ConnectionStateData {
   option (gogoproto.goproto_getters) = false;
 
-  bytes path = 1;
+  bytes                                path       = 1;
   ibc.core.connection.v1.ConnectionEnd connection = 2;
 }
 
@@ -176,31 +157,33 @@ message ConnectionStateData {
 message ChannelStateData {
   option (gogoproto.goproto_getters) = false;
 
-  bytes path = 1;
+  bytes                       path    = 1;
   ibc.core.channel.v1.Channel channel = 2;
 }
 
 // PacketCommitmentData returns the SignBytes data for packet commitment
 // verification.
 message PacketCommitmentData {
-  bytes path = 1;
+  bytes path       = 1;
   bytes commitment = 2;
 }
 
 // PacketAcknowledgementData returns the SignBytes data for acknowledgement
 // verification.
 message PacketAcknowledgementData {
-  bytes path = 1;
+  bytes path            = 1;
   bytes acknowledgement = 2;
 }
 
 // PacketReceiptAbsenceData returns the SignBytes data for
 // packet receipt absence verification.
-message PacketReceiptAbsenceData { bytes path = 1; }
+message PacketReceiptAbsenceData {
+  bytes path = 1;
+}
 
 // NextSequenceRecvData returns the SignBytes data for verification of the next
 // sequence to be received.
 message NextSequenceRecvData {
-  bytes path = 1;
-  uint64 next_seq_recv = 2 [ (gogoproto.moretags) = "yaml:\"next_seq_recv\"" ];
+  bytes  path          = 1;
+  uint64 next_seq_recv = 2 [(gogoproto.moretags) = "yaml:\"next_seq_recv\""];
 }
diff --git a/proto/ibc/lightclients/tendermint/v1/tendermint.proto b/proto/ibc/lightclients/tendermint/v1/tendermint.proto
index de59589bffe..17a6cce40cc 100644
--- a/proto/ibc/lightclients/tendermint/v1/tendermint.proto
+++ b/proto/ibc/lightclients/tendermint/v1/tendermint.proto
@@ -18,44 +18,30 @@ import "gogoproto/gogo.proto";
 message ClientState {
   option (gogoproto.goproto_getters) = false;
 
-  string chain_id = 1;
-  Fraction trust_level = 2 [
-    (gogoproto.nullable) = false,
-    (gogoproto.moretags) = "yaml:\"trust_level\""
-  ];
+  string   chain_id    = 1;
+  Fraction trust_level = 2 [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"trust_level\""];
   // duration of the period since the LastestTimestamp during which the
   // submitted headers are valid for upgrade
-  google.protobuf.Duration trusting_period = 3 [
-    (gogoproto.nullable) = false,
-    (gogoproto.stdduration) = true,
-    (gogoproto.moretags) = "yaml:\"trusting_period\""
-  ];
+  google.protobuf.Duration trusting_period = 3
+      [(gogoproto.nullable) = false, (gogoproto.stdduration) = true, (gogoproto.moretags) = "yaml:\"trusting_period\""];
   // duration of the staking unbonding period
   google.protobuf.Duration unbonding_period = 4 [
-    (gogoproto.nullable) = false,
+    (gogoproto.nullable)    = false,
     (gogoproto.stdduration) = true,
-    (gogoproto.moretags) = "yaml:\"unbonding_period\""
+    (gogoproto.moretags)    = "yaml:\"unbonding_period\""
   ];
   // defines how much new (untrusted) header's Time can drift into the future.
-  google.protobuf.Duration max_clock_drift = 5 [
-    (gogoproto.nullable) = false,
-    (gogoproto.stdduration) = true,
-    (gogoproto.moretags) = "yaml:\"max_clock_drift\""
-  ];
+  google.protobuf.Duration max_clock_drift = 5
+      [(gogoproto.nullable) = false, (gogoproto.stdduration) = true, (gogoproto.moretags) = "yaml:\"max_clock_drift\""];
   // Block height when the client was frozen due to a misbehaviour
-  ibc.core.client.v1.Height frozen_height = 6 [
-    (gogoproto.nullable) = false,
-    (gogoproto.moretags) = "yaml:\"frozen_height\""
-  ];
+  ibc.core.client.v1.Height frozen_height = 6
+      [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"frozen_height\""];
   // Latest height the client was updated to
-  ibc.core.client.v1.Height latest_height = 7 [
-    (gogoproto.nullable) = false,
-    (gogoproto.moretags) = "yaml:\"latest_height\""
-  ];
+  ibc.core.client.v1.Height latest_height = 7
+      [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"latest_height\""];
 
   // Proof specifications used in verifying counterparty state
-  repeated ics23.ProofSpec proof_specs = 8
-      [ (gogoproto.moretags) = "yaml:\"proof_specs\"" ];
+  repeated ics23.ProofSpec proof_specs = 8 [(gogoproto.moretags) = "yaml:\"proof_specs\""];
 
   // Path at which next upgraded client will be committed.
   // Each element corresponds to the key for a single CommitmentProof in the
@@ -64,17 +50,14 @@ message ClientState {
   // under `{upgradepath}/{upgradeHeight}/consensusState` For SDK chains using
   // the default upgrade module, upgrade_path should be []string{"upgrade",
   // "upgradedIBCState"}`
-  repeated string upgrade_path = 9
-      [ (gogoproto.moretags) = "yaml:\"upgrade_path\"" ];
+  repeated string upgrade_path = 9 [(gogoproto.moretags) = "yaml:\"upgrade_path\""];
 
   // This flag, when set to true, will allow governance to recover a client
   // which has expired
-  bool allow_update_after_expiry = 10
-      [ (gogoproto.moretags) = "yaml:\"allow_update_after_expiry\"" ];
+  bool allow_update_after_expiry = 10 [(gogoproto.moretags) = "yaml:\"allow_update_after_expiry\""];
   // This flag, when set to true, will allow governance to unfreeze a client
   // whose chain has experienced a misbehaviour event
-  bool allow_update_after_misbehaviour = 11
-      [ (gogoproto.moretags) = "yaml:\"allow_update_after_misbehaviour\"" ];
+  bool allow_update_after_misbehaviour = 11 [(gogoproto.moretags) = "yaml:\"allow_update_after_misbehaviour\""];
 }
 
 // ConsensusState defines the consensus state from Tendermint.
@@ -83,13 +66,11 @@ message ConsensusState {
 
   // timestamp that corresponds to the block height in which the ConsensusState
   // was stored.
-  google.protobuf.Timestamp timestamp = 1
-      [ (gogoproto.nullable) = false, (gogoproto.stdtime) = true ];
+  google.protobuf.Timestamp timestamp = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
   // commitment root (i.e app hash)
-  ibc.core.commitment.v1.MerkleRoot root = 2 [ (gogoproto.nullable) = false ];
-  bytes next_validators_hash = 3 [
-    (gogoproto.casttype) =
-        "github.com/tendermint/tendermint/libs/bytes.HexBytes",
+  ibc.core.commitment.v1.MerkleRoot root                 = 2 [(gogoproto.nullable) = false];
+  bytes                             next_validators_hash = 3 [
+    (gogoproto.casttype) = "github.com/tendermint/tendermint/libs/bytes.HexBytes",
     (gogoproto.moretags) = "yaml:\"next_validators_hash\""
   ];
 }
@@ -99,15 +80,9 @@ message ConsensusState {
 message Misbehaviour {
   option (gogoproto.goproto_getters) = false;
 
-  string client_id = 1 [ (gogoproto.moretags) = "yaml:\"client_id\"" ];
-  Header header_1 = 2 [
-    (gogoproto.customname) = "Header1",
-    (gogoproto.moretags) = "yaml:\"header_1\""
-  ];
-  Header header_2 = 3 [
-    (gogoproto.customname) = "Header2",
-    (gogoproto.moretags) = "yaml:\"header_2\""
-  ];
+  string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
+  Header header_1  = 2 [(gogoproto.customname) = "Header1", (gogoproto.moretags) = "yaml:\"header_1\""];
+  Header header_2  = 3 [(gogoproto.customname) = "Header2", (gogoproto.moretags) = "yaml:\"header_2\""];
 }
 
 // Header defines the Tendermint client consensus Header.
@@ -123,24 +98,18 @@ message Misbehaviour {
 // hash to TrustedConsensusState.NextValidatorsHash since that is the last
 // trusted validator set at the TrustedHeight.
 message Header {
-  .tendermint.types.SignedHeader signed_header = 1 [
-    (gogoproto.embed) = true,
-    (gogoproto.moretags) = "yaml:\"signed_header\""
-  ];
+  .tendermint.types.SignedHeader signed_header = 1
+      [(gogoproto.embed) = true, (gogoproto.moretags) = "yaml:\"signed_header\""];
 
-  .tendermint.types.ValidatorSet validator_set = 2
-      [ (gogoproto.moretags) = "yaml:\"validator_set\"" ];
-  ibc.core.client.v1.Height trusted_height = 3 [
-    (gogoproto.nullable) = false,
-    (gogoproto.moretags) = "yaml:\"trusted_height\""
-  ];
-  .tendermint.types.ValidatorSet trusted_validators = 4
-      [ (gogoproto.moretags) = "yaml:\"trusted_validators\"" ];
+  .tendermint.types.ValidatorSet validator_set  = 2 [(gogoproto.moretags) = "yaml:\"validator_set\""];
+  ibc.core.client.v1.Height      trusted_height = 3
+      [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"trusted_height\""];
+  .tendermint.types.ValidatorSet trusted_validators = 4 [(gogoproto.moretags) = "yaml:\"trusted_validators\""];
 }
 
 // Fraction defines the protobuf message type for tmmath.Fraction that only
 // supports positive values.
 message Fraction {
-  uint64 numerator = 1;
+  uint64 numerator   = 1;
   uint64 denominator = 2;
 }
diff --git a/testing/chain.go b/testing/chain.go
index 19ee21839f6..92228eed849 100644
--- a/testing/chain.go
+++ b/testing/chain.go
@@ -313,9 +313,17 @@ func (chain *TestChain) GetPrefix() commitmenttypes.MerklePrefix {
 // ConstructUpdateTMClientHeader will construct a valid 07-tendermint Header to update the
 // light client on the source chain.
 func (chain *TestChain) ConstructUpdateTMClientHeader(counterparty *TestChain, clientID string) (*ibctmtypes.Header, error) {
+	return chain.ConstructUpdateTMClientHeaderWithTrustedHeight(counterparty, clientID, clienttypes.ZeroHeight())
+}
+
+// ConstructUpdateTMClientHeader will construct a valid 07-tendermint Header to update the
+// light client on the source chain.
+func (chain *TestChain) ConstructUpdateTMClientHeaderWithTrustedHeight(counterparty *TestChain, clientID string, trustedHeight clienttypes.Height) (*ibctmtypes.Header, error) {
 	header := counterparty.LastHeader
-	// Relayer must query for LatestHeight on client to get TrustedHeight
-	trustedHeight := chain.GetClientState(clientID).GetLatestHeight().(clienttypes.Height)
+	// Relayer must query for LatestHeight on client to get TrustedHeight if the trusted height is not set
+	if trustedHeight.IsZero() {
+		trustedHeight = chain.GetClientState(clientID).GetLatestHeight().(clienttypes.Height)
+	}
 	var (
 		tmTrustedVals *tmtypes.ValidatorSet
 		ok            bool
diff --git a/testing/endpoint.go b/testing/endpoint.go
index 3a9e8dbd9e4..e32d0cdfbf7 100644
--- a/testing/endpoint.go
+++ b/testing/endpoint.go
@@ -433,6 +433,25 @@ func (endpoint *Endpoint) GetClientState() exported.ClientState {
 	return endpoint.Chain.GetClientState(endpoint.ClientID)
 }
 
+// SetClientState sets the client state for this endpoint.
+func (endpoint *Endpoint) SetClientState(clientState exported.ClientState) {
+	endpoint.Chain.App.GetIBCKeeper().ClientKeeper.SetClientState(endpoint.Chain.GetContext(), endpoint.ClientID, clientState)
+}
+
+// GetConsensusState retrieves the Consensus State for this endpoint at the provided height.
+// The consensus state is expected to exist otherwise testing will fail.
+func (endpoint *Endpoint) GetConsensusState(height exported.Height) exported.ConsensusState {
+	consensusState, found := endpoint.Chain.GetConsensusState(endpoint.ClientID, height)
+	require.True(endpoint.Chain.t, found)
+
+	return consensusState
+}
+
+// SetConsensusState sets the consensus state for this endpoint.
+func (endpoint *Endpoint) SetConsensusState(consensusState exported.ConsensusState, height exported.Height) {
+	endpoint.Chain.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(endpoint.Chain.GetContext(), endpoint.ClientID, height, consensusState)
+}
+
 // GetConnection retrieves an IBC Connection for the endpoint. The
 // connection is expected to exist otherwise testing will fail.
 func (endpoint *Endpoint) GetConnection() connectiontypes.ConnectionEnd {
@@ -442,6 +461,11 @@ func (endpoint *Endpoint) GetConnection() connectiontypes.ConnectionEnd {
 	return connection
 }
 
+// SetConnection sets the connection for this endpoint.
+func (endpoint *Endpoint) SetConnection(connection connectiontypes.ConnectionEnd) {
+	endpoint.Chain.App.GetIBCKeeper().ConnectionKeeper.SetConnection(endpoint.Chain.GetContext(), endpoint.ConnectionID, connection)
+}
+
 // GetChannel retrieves an IBC Channel for the endpoint. The channel
 // is expected to exist otherwise testing will fail.
 func (endpoint *Endpoint) GetChannel() channeltypes.Channel {
@@ -451,6 +475,11 @@ func (endpoint *Endpoint) GetChannel() channeltypes.Channel {
 	return channel
 }
 
+// SetChannel sets the channel for this endpoint.
+func (endpoint *Endpoint) SetChannel(channel channeltypes.Channel) {
+	endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.SetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID, channel)
+}
+
 // QueryClientStateProof performs and abci query for a client stat associated
 // with this endpoint and returns the ClientState along with the proof.
 func (endpoint *Endpoint) QueryClientStateProof() (exported.ClientState, []byte) {
diff --git a/testing/values.go b/testing/values.go
index d71356ec401..5ba3ab1dd29 100644
--- a/testing/values.go
+++ b/testing/values.go
@@ -17,6 +17,7 @@ import (
 )
 
 const (
+	FirstClientID     = "07-tendermint-0"
 	FirstChannelID    = "channel-0"
 	FirstConnectionID = "connection-0"