Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

02-client routing: implement VerifyUpgradeAndUpdateState in light client modules #5827

Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
98230b3
wip: implementation and tests for verify upgrade and update state fun…
crodriguezvega Feb 9, 2024
83ce8cc
add test case
crodriguezvega Feb 9, 2024
fb77005
fix un-marshaling in tendermint light client module
crodriguezvega Feb 9, 2024
a4e8693
add tests for verify upgrade and update state of 08-wasm light client…
crodriguezvega Feb 9, 2024
79fb56f
fix linter warnings
crodriguezvega Feb 9, 2024
623d8c6
check client state post upgrade
crodriguezvega Feb 12, 2024
3e31163
fix: encoding issue: unmarshal to concrete types and not interfaces i…
damiannolan Feb 16, 2024
be1dfdc
Merge branch 'feat/02-client-router' into carlos/client-routing-verif…
crodriguezvega Feb 18, 2024
96a133f
Merge branch 'feat/02-client-router' into carlos/client-routing-verif…
crodriguezvega Feb 18, 2024
0758398
Merge branch 'feat/02-client-router' into carlos/client-routing-verif…
crodriguezvega Feb 18, 2024
e92393b
fix import
crodriguezvega Feb 18, 2024
4dfcf27
cast type before calling zero custom fields
crodriguezvega Feb 18, 2024
70a1182
test: marshal concrete types using chain codec for upgrade tests whic…
damiannolan Feb 19, 2024
1bad03b
chore: remove basic validation of lc types in tm VerifyUpgradeAndUpda…
damiannolan Feb 19, 2024
fbe8b92
marshal to concrete type in tests
crodriguezvega Feb 26, 2024
a9d6113
keep client/consensus state as interface marshalled
crodriguezvega Feb 27, 2024
bcc8273
Merge branch 'feat/02-client-router' into carlos/client-routing-verif…
crodriguezvega Feb 27, 2024
1408152
Apply suggestions from code review
crodriguezvega Mar 11, 2024
5937285
Merge branch 'feat/02-client-router' into carlos/client-routing-verif…
damiannolan Mar 11, 2024
cfa5eec
chore: make lint-fix
damiannolan Mar 11, 2024
a65ab8b
chore: rm redundant test, tested in lightclient module
damiannolan Mar 11, 2024
290a237
fix: remove marshalling of anys to bytes for verify upgrade (#5967)
damiannolan Mar 12, 2024
f7b2192
nit: inline comments in tests last Height -> upgrade height
damiannolan Mar 12, 2024
3b3256a
fix: address 08-wasm upgrade client and tests
damiannolan Mar 12, 2024
6113b5b
Merge branch 'feat/02-client-router' into carlos/client-routing-verif…
damiannolan Mar 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 16 additions & 22 deletions modules/core/02-client/keeper/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,48 +122,42 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, clientMsg exporte

// UpgradeClient upgrades the client to a new client state if this new client was committed to
// by the old client at the specified upgrade height
func (k Keeper) UpgradeClient(ctx sdk.Context, clientID string, upgradedClient exported.ClientState, upgradedConsState exported.ConsensusState,
upgradeClientProof, upgradeConsensusStateProof []byte,
func (k Keeper) UpgradeClient(
ctx sdk.Context,
clientID string,
upgradedClient, upgradedConsState, upgradeClientProof, upgradeConsensusStateProof []byte,
crodriguezvega marked this conversation as resolved.
Show resolved Hide resolved
) error {
clientState, found := k.GetClientState(ctx, clientID)
if !found {
return errorsmod.Wrapf(types.ErrClientNotFound, "cannot update client with ID %s", clientID)
}

clientStore := k.ClientStore(ctx, clientID)

if status := k.GetClientStatus(ctx, clientID); status != exported.Active {
return errorsmod.Wrapf(types.ErrClientNotActive, "cannot upgrade client (%s) with status %s", clientID, status)
}

// TODO: This code is removed in https://github.com/cosmos/ibc-go/pull/5827
// last height of current counterparty chain must be client's latest height
// lastHeight := k.GetLatestHeight(ctx, clientID)
clientType, _, err := types.ParseClientIdentifier(clientID)
if err != nil {
return errorsmod.Wrapf(types.ErrClientNotFound, "clientID (%s)", clientID)
}

// if !upgradedClient.GetLatestHeight().GT(lastHeight) {
// return errorsmod.Wrapf(ibcerrors.ErrInvalidHeight, "upgraded client height %s must be at greater than current client height %s",
// upgradedClient.GetLatestHeight(), lastHeight)
// }
clientModule, found := k.router.GetRoute(clientID)
if !found {
return errorsmod.Wrap(types.ErrRouteNotFound, clientID)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we will want to add this back once LatestHeight is added to the light client module

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

discussed async, this check must be moved to the light client module, and this functionality should likely only exist in the tendermint client module.

At first glance, we do not have the clientID of the upgradedClientState. However, it should be the same clientID as the clientState (target). However, we need the latest height from the upgradedClientState concrete implementation here - this is the client which the counterparty stores in it upgrade path and we prove against within the tm client module.


if err := clientState.VerifyUpgradeAndUpdateState(ctx, k.cdc, clientStore,
upgradedClient, upgradedConsState, upgradeClientProof, upgradeConsensusStateProof,
); err != nil {
if err := clientModule.VerifyUpgradeAndUpdateState(ctx, clientID, upgradedClient, upgradedConsState, upgradeClientProof, upgradeConsensusStateProof); err != nil {
return errorsmod.Wrapf(err, "cannot upgrade client with ID %s", clientID)
}

latestHeight := k.GetLatestHeight(ctx, clientID) // TODO: use clientModule when addressing this func in https://github.com/cosmos/ibc-go/pull/5827
latestHeight := clientModule.LatestHeight(ctx, clientID)
k.Logger(ctx).Info("client state upgraded", "client-id", clientID, "height", latestHeight.String())

defer telemetry.IncrCounterWithLabels(
[]string{"ibc", "client", "upgrade"},
1,
[]metrics.Label{
telemetry.NewLabel(types.LabelClientType, upgradedClient.ClientType()),
telemetry.NewLabel(types.LabelClientType, clientType),
telemetry.NewLabel(types.LabelClientID, clientID),
},
)

emitUpgradeClientEvent(ctx, clientID, upgradedClient.ClientType(), latestHeight)
emitUpgradeClientEvent(ctx, clientID, clientType, latestHeight)

return nil
}
Expand Down
125 changes: 50 additions & 75 deletions modules/core/02-client/keeper/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

upgradetypes "cosmossdk.io/x/upgrade/types"

codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"

clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
Expand Down Expand Up @@ -321,9 +322,9 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
path *ibctesting.Path
upgradedClient *ibctm.ClientState
upgradedConsState exported.ConsensusState
lastHeight exported.Height
upgradeHeight exported.Height
upgradedClientAny, upgradedConsStateAny *codectypes.Any
upgradedClientProof, upgradedConsensusStateProof []byte
upgradedClientBz, upgradedConsStateBz []byte
)

testCases := []struct {
Expand All @@ -334,13 +335,13 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
{
name: "successful upgrade",
setup: func() {
// last Height is at next block
lastHeight = clienttypes.NewHeight(1, uint64(suite.chainB.GetContext().BlockHeight()+1))
// upgrade Height is at next block
upgradeHeight = clienttypes.NewHeight(1, uint64(suite.chainB.GetContext().BlockHeight()+1))

// zero custom fields and store in upgrade store
err := suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz)
err := suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(upgradedClientAny))
suite.Require().NoError(err)
err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz)
err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(upgradedConsStateAny))
suite.Require().NoError(err)

// commit upgrade store changes and update clients
Expand All @@ -353,21 +354,21 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
tmCs, ok := cs.(*ibctm.ClientState)
suite.Require().True(ok)

upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(upgradeHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
},
expPass: true,
},
{
name: "client state not found",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I deleted this test because this is tested in the light client module.

setup: func() {
// last Height is at next block
damiannolan marked this conversation as resolved.
Show resolved Hide resolved
lastHeight = clienttypes.NewHeight(1, uint64(suite.chainB.GetContext().BlockHeight()+1))
upgradeHeight = clienttypes.NewHeight(1, uint64(suite.chainB.GetContext().BlockHeight()+1))

// zero custom fields and store in upgrade store
err := suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz)
err := suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(upgradedClientAny))
suite.Require().NoError(err)
err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz)
err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(upgradedConsStateAny))
suite.Require().NoError(err)

// commit upgrade store changes and update clients
Expand All @@ -381,8 +382,8 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
tmCs, ok := cs.(*ibctm.ClientState)
suite.Require().True(ok)

upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(upgradeHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())

path.EndpointA.ClientID = "wrongclientid"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for some reason it doesnt look like this change is triggering the error code path we would expect, does anyone else see that in the testing code coverage?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can follow up this post merge, maybe? I think all these tests should be using expError and not expPass (bool)

},
Expand All @@ -394,16 +395,15 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
// client is frozen

// last Height is at next block
damiannolan marked this conversation as resolved.
Show resolved Hide resolved
lastHeight = clienttypes.NewHeight(1, uint64(suite.chainB.GetContext().BlockHeight()+1))
upgradeHeight = clienttypes.NewHeight(1, uint64(suite.chainB.GetContext().BlockHeight()+1))

// zero custom fields and store in upgrade store
err := suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz)
err := suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(upgradedClientAny))
suite.Require().NoError(err)
err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz)
err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(upgradedConsStateAny))
suite.Require().NoError(err)

// commit upgrade store changes and update clients

suite.coordinator.CommitBlock(suite.chainB)
err = path.EndpointA.UpdateClient()
suite.Require().NoError(err)
Expand All @@ -413,8 +413,8 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
tmCs, ok := cs.(*ibctm.ClientState)
suite.Require().True(ok)

upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(upgradeHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())

// set frozen client in store
tmClient, ok := cs.(*ibctm.ClientState)
Expand All @@ -425,49 +425,22 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
expPass: false,
},
{
name: "tendermint client VerifyUpgrade fails",
name: "light client module VerifyUpgradeAndUpdateState fails",
setup: func() {
// last Height is at next block
charleenfei marked this conversation as resolved.
Show resolved Hide resolved
damiannolan marked this conversation as resolved.
Show resolved Hide resolved
lastHeight = clienttypes.NewHeight(1, uint64(suite.chainB.GetContext().BlockHeight()+1))
upgradeHeight = clienttypes.NewHeight(1, uint64(suite.chainB.GetContext().BlockHeight()+1))

// zero custom fields and store in upgrade store
err := suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz)
err := suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(upgradedClientAny))
suite.Require().NoError(err)
err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz)
err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(upgradedConsStateAny))
suite.Require().NoError(err)

// change upgradedClient client-specified parameters
upgradedClient.ChainId = "wrongchainID"

suite.coordinator.CommitBlock(suite.chainB)
err = path.EndpointA.UpdateClient()
upgradedClientAny, err = codectypes.NewAnyWithValue(upgradedClient)
suite.Require().NoError(err)

cs, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID)
suite.Require().True(found)
tmCs, ok := cs.(*ibctm.ClientState)
suite.Require().True(ok)

upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
},
expPass: false,
},
{
name: "unsuccessful upgrade: upgraded height is not greater than current height",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this test to the light client module, but can move it back here in the PR where LatestHeight is added to the light client module and then we can move the check back to 02-client.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#5827 (comment)

I guess it can just be removed entirely now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. At the moment this check is performed in 07-tendermint and 08-wasm light client modules. Based on your comment, is that ok? Any reason why the check should not be done in 08-wasm?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can have these tests in the lcm modules for 07-tendermint and 08-wasm already, i think! is that fine @crodriguezvega?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, correct! The check and the tests are currently in the light client module. Happy to leave it there if that's the right place. :)

setup: func() {
// last Height is at next block
lastHeight = clienttypes.NewHeight(1, uint64(suite.chainB.GetContext().BlockHeight()+1))

// zero custom fields and store in upgrade store
err := suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz)
suite.Require().NoError(err)
err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz)
suite.Require().NoError(err)

// change upgradedClient height to be lower than current client state height
upgradedClient.LatestHeight = clienttypes.NewHeight(0, 1)

suite.coordinator.CommitBlock(suite.chainB)
err = path.EndpointA.UpdateClient()
suite.Require().NoError(err)
Expand All @@ -477,44 +450,46 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
tmCs, ok := cs.(*ibctm.ClientState)
suite.Require().True(ok)

upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(upgradeHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight())
},
expPass: false,
},
}

for _, tc := range testCases {
tc := tc
path = ibctesting.NewPath(suite.chainA, suite.chainB)
path.SetupClients()
suite.Run(tc.name, func() {
path = ibctesting.NewPath(suite.chainA, suite.chainB)
path.SetupClients()

clientState := path.EndpointA.GetClientState().(*ibctm.ClientState)
revisionNumber := clienttypes.ParseChainID(clientState.ChainId)
clientState := path.EndpointA.GetClientState().(*ibctm.ClientState)
revisionNumber := clienttypes.ParseChainID(clientState.ChainId)

newChainID, err := clienttypes.SetRevisionNumber(clientState.ChainId, revisionNumber+1)
suite.Require().NoError(err)
newChainID, err := clienttypes.SetRevisionNumber(clientState.ChainId, revisionNumber+1)
suite.Require().NoError(err)

upgradedClient = ibctm.NewClientState(newChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, clienttypes.NewHeight(revisionNumber+1, clientState.LatestHeight.GetRevisionHeight()+1), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath)
upgradedClient = upgradedClient.ZeroCustomFields()
upgradedClientBz, err = clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient)
suite.Require().NoError(err)
upgradedClient = ibctm.NewClientState(newChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, clienttypes.NewHeight(revisionNumber+1, clientState.LatestHeight.GetRevisionHeight()+1), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath)
upgradedClient = upgradedClient.ZeroCustomFields()

upgradedConsState = &ibctm.ConsensusState{
NextValidatorsHash: []byte("nextValsHash"),
}
upgradedConsStateBz, err = clienttypes.MarshalConsensusState(suite.chainA.App.AppCodec(), upgradedConsState)
suite.Require().NoError(err)
upgradedClientAny, err = codectypes.NewAnyWithValue(upgradedClient)
suite.Require().NoError(err)

upgradedConsState = &ibctm.ConsensusState{NextValidatorsHash: []byte("nextValsHash")}

upgradedConsStateAny, err = codectypes.NewAnyWithValue(upgradedConsState)
suite.Require().NoError(err)

tc.setup()
tc.setup()

err = suite.chainA.App.GetIBCKeeper().ClientKeeper.UpgradeClient(suite.chainA.GetContext(), path.EndpointA.ClientID, upgradedClient, upgradedConsState, upgradedClientProof, upgradedConsensusStateProof)
err = suite.chainA.App.GetIBCKeeper().ClientKeeper.UpgradeClient(suite.chainA.GetContext(), path.EndpointA.ClientID, upgradedClientAny.Value, upgradedConsStateAny.Value, upgradedClientProof, upgradedConsensusStateProof)

if tc.expPass {
suite.Require().NoError(err, "verify upgrade failed on valid case: %s", tc.name)
} else {
suite.Require().Error(err, "verify upgrade passed on invalid case: %s", tc.name)
}
if tc.expPass {
suite.Require().NoError(err, "verify upgrade failed on valid case: %s", tc.name)
} else {
suite.Require().Error(err, "verify upgrade passed on invalid case: %s", tc.name)
}
})
}
}

Expand Down
18 changes: 0 additions & 18 deletions modules/core/exported/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (

storetypes "cosmossdk.io/store/types"

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
)

Expand Down Expand Up @@ -141,23 +140,6 @@ type ClientState interface {

ClientType() string
Validate() error

// Upgrade functions
// NOTE: proof heights are not included as upgrade to a new revision is expected to pass only on the last
// height committed by the current revision. Clients are responsible for ensuring that the planned last
// height of the current revision is somehow encoded in the proof verification process.
// This is to ensure that no premature upgrades occur, since upgrade plans committed to by the counterparty
// may be cancelled or modified before the last planned height.
// If the upgrade is verified, the upgraded client and consensus states must be set in the client store.
VerifyUpgradeAndUpdateState(
ctx sdk.Context,
cdc codec.BinaryCodec,
store storetypes.KVStore,
newClient ClientState,
newConsState ConsensusState,
upgradeClientProof,
upgradeConsensusStateProof []byte,
) error
}

// ConsensusState is the state of the consensus process
Expand Down
23 changes: 12 additions & 11 deletions modules/core/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,21 @@ func (k Keeper) UpdateClient(goCtx context.Context, msg *clienttypes.MsgUpdateCl
}

// UpgradeClient defines a rpc handler method for MsgUpgradeClient.
// NOTE: The raw bytes of the conretes types encoded into protobuf.Any is passed to the client keeper.
// The 02-client handler will route to the appropriate light client module based on client identifier and it is the responsibility
// of the light client module to unmarshal and interpret the proto encoded bytes.
// Backwards compatibility with older versions of ibc-go is maintained through the light client module reconstructing and encoding
// the expected concrete type to the protobuf.Any for proof verification.
func (k Keeper) UpgradeClient(goCtx context.Context, msg *clienttypes.MsgUpgradeClient) (*clienttypes.MsgUpgradeClientResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

upgradedClient, err := clienttypes.UnpackClientState(msg.ClientState)
if err != nil {
return nil, err
}
upgradedConsState, err := clienttypes.UnpackConsensusState(msg.ConsensusState)
if err != nil {
return nil, err
}

if err = k.ClientKeeper.UpgradeClient(ctx, msg.ClientId, upgradedClient, upgradedConsState,
msg.ProofUpgradeClient, msg.ProofUpgradeConsensusState); err != nil {
if err := k.ClientKeeper.UpgradeClient(
ctx, msg.ClientId,
msg.ClientState.Value,
msg.ConsensusState.Value,
crodriguezvega marked this conversation as resolved.
Show resolved Hide resolved
crodriguezvega marked this conversation as resolved.
Show resolved Hide resolved
msg.ProofUpgradeClient,
msg.ProofUpgradeConsensusState,
); err != nil {
return nil, err
}

Expand Down
Loading
Loading