Skip to content

Commit

Permalink
Add message server handler for recovering a client
Browse files Browse the repository at this point in the history
  • Loading branch information
DimitrisJim committed Aug 31, 2023
1 parent 9c5499e commit 7408256
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 1 deletion.
11 changes: 10 additions & 1 deletion modules/core/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,16 @@ func (k Keeper) SubmitMisbehaviour(goCtx context.Context, msg *clienttypes.MsgSu
}

// RecoverClient defines a rpc handler method for MsgRecoverClient.
func (k Keeper) RecoverClient(goCtx context.Context, msg *clienttypes.MsgRecoverClient) (*clienttypes.MsgRecoverClientResponse, error) { //nolint:revive
func (k Keeper) RecoverClient(goCtx context.Context, msg *clienttypes.MsgRecoverClient) (*clienttypes.MsgRecoverClientResponse, error) {
if k.GetAuthority() != msg.Signer {
return nil, errorsmod.Wrapf(ibcerrors.ErrUnauthorized, "expected %s, got %s", k.GetAuthority(), msg.Signer)
}

ctx := sdk.UnwrapSDKContext(goCtx)
if err := k.ClientKeeper.RecoverClient(ctx, msg.SubjectClientId, msg.SubstituteClientId); err != nil {
return nil, errorsmod.Wrap(err, "client recovery failed")
}

return &clienttypes.MsgRecoverClientResponse{}, nil
}

Expand Down
88 changes: 88 additions & 0 deletions modules/core/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,94 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
}
}

func (suite *KeeperTestSuite) TestRecoverClient() {
var (
subject, substitute string
subjectClientState, substituteClientState exported.ClientState
msg *clienttypes.MsgRecoverClient
)

testCases := []struct {
name string
malleate func()
expErr error
}{
{
"success: recover client",
func() {},
nil,
},
{
"signer doesn't match authority",
func() {
msg.Signer = ibctesting.InvalidID
},
ibcerrors.ErrUnauthorized,
},
{
"invalid subject client",
func() {
msg.SubjectClientId = ibctesting.InvalidID
},
clienttypes.ErrClientNotFound,
},
}

for _, tc := range testCases {
tc := tc
suite.Run(tc.name, func() {
suite.SetupTest()

subjectPath := ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupClients(subjectPath)
subject = subjectPath.EndpointA.ClientID
subjectClientState = suite.chainA.GetClientState(subject)

substitutePath := ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupClients(substitutePath)
substitute = substitutePath.EndpointA.ClientID

// update substitute twice
err := substitutePath.EndpointA.UpdateClient()
suite.Require().NoError(err)
err = substitutePath.EndpointA.UpdateClient()
suite.Require().NoError(err)
substituteClientState = suite.chainA.GetClientState(substitute)

tmClientState, ok := subjectClientState.(*ibctm.ClientState)
suite.Require().True(ok)
tmClientState.AllowUpdateAfterMisbehaviour = true
tmClientState.AllowUpdateAfterExpiry = true
tmClientState.FrozenHeight = tmClientState.LatestHeight
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), subject, tmClientState)

tmClientState, ok = substituteClientState.(*ibctm.ClientState)
suite.Require().True(ok)
tmClientState.AllowUpdateAfterMisbehaviour = true
tmClientState.AllowUpdateAfterExpiry = true

msg = clienttypes.NewMsgRecoverClient(suite.chainA.App.GetIBCKeeper().GetAuthority(), subject, substitute)

tc.malleate()

_, err = keeper.Keeper.RecoverClient(*suite.chainA.App.GetIBCKeeper(), suite.chainA.GetContext(), msg)

expPass := tc.expErr == nil
if expPass {
suite.Require().NoError(err)

// Assert that client status is now Active
clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), subjectPath.EndpointA.ClientID)
tmClientState := subjectPath.EndpointA.GetClientState().(*ibctm.ClientState)
suite.Require().Equal(tmClientState.Status(suite.chainA.GetContext(), clientStore, suite.chainA.App.AppCodec()), exported.Active)
} else {
suite.Require().Error(err)
suite.Require().ErrorIs(err, tc.expErr)
}
})
}
}

// TestUpdateClientParams tests the UpdateClientParams rpc handler
func (suite *KeeperTestSuite) TestUpdateClientParams() {
validAuthority := suite.chainA.App.GetIBCKeeper().GetAuthority()
Expand Down

0 comments on commit 7408256

Please sign in to comment.