From 2e5f08a365e1537b2d47d235d384e067322087e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Federico=20Kunze=20K=C3=BCllmer?= <31522760+fedekunze@users.noreply.github.com> Date: Tue, 31 Jan 2023 14:02:31 +0100 Subject: [PATCH 1/2] chore: Add `HasConnection` and `HasChannel` methods. (#3082) (cherry picked from commit b2fb1192245134607e0e7a294d09d2aa1145f017) # Conflicts: # CHANGELOG.md # modules/core/02-client/migrations/v7/store.go # modules/light-clients/07-tendermint/types/store.go --- CHANGELOG.md | 30 +++ modules/apps/29-fee/keeper/keeper.go | 2 +- modules/apps/transfer/keeper/keeper.go | 2 +- modules/core/02-client/keeper/keeper.go | 6 +- modules/core/02-client/migrations/v7/store.go | 205 ++++++++++++++++++ modules/core/03-connection/keeper/keeper.go | 13 +- modules/core/04-channel/keeper/keeper.go | 20 +- modules/core/04-channel/keeper/keeper_test.go | 2 +- .../07-tendermint/types/store.go | 11 +- 9 files changed, 272 insertions(+), 19 deletions(-) create mode 100644 modules/core/02-client/migrations/v7/store.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 76bf29d3f88..4179efbe60a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,36 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +<<<<<<< HEAD +======= +* (core) [\#3082](https://github.com/cosmos/ibc-go/pull/3082) Add `HasConnection` and `HasChannel` methods. +* (tests) [\#2926](https://github.com/cosmos/ibc-go/pull/2926) Lint tests +* (apps/transfer) [\#2643](https://github.com/cosmos/ibc-go/pull/2643) Add amount, denom, and memo to transfer event emission. +* (core) [\#2746](https://github.com/cosmos/ibc-go/pull/2746) Allow proof height to be zero for all core IBC `sdk.Msg` types that contain proofs. +* (light-clients/06-solomachine) [\#2746](https://github.com/cosmos/ibc-go/pull/2746) Discard proofHeight for solo machines and use the solo machine sequence instead. +* (modules/light-clients/07-tendermint) [\#1713](https://github.com/cosmos/ibc-go/pull/1713) Allow client upgrade proposals to update `TrustingPeriod`. See ADR-026 for context. +* (modules/core/02-client) [\#1188](https://github.com/cosmos/ibc-go/pull/1188/files) Routing `MsgSubmitMisbehaviour` to `UpdateClient` keeper function. Deprecating `SubmitMisbehaviour` endpoint. +* (modules/core/02-client) [\#1208](https://github.com/cosmos/ibc-go/pull/1208) Replace `CheckHeaderAndUpdateState` usage in 02-client with calls to `VerifyClientMessage`, `CheckForMisbehaviour`, `UpdateStateOnMisbehaviour` and `UpdateState`. +* (modules/light-clients/09-localhost) [\#1187](https://github.com/cosmos/ibc-go/pull/1187/) Removing localhost light client implementation as it is not functional. An upgrade handler is provided in `modules/migrations/v5` to prune `09-localhost` clients and consensus states from the store. +* [\#1186](https://github.com/cosmos/ibc-go/pull/1186/files) Removing `GetRoot` function from ConsensusState interface in `02-client`. `GetRoot` is unused by core IBC. +* (modules/core/02-client) [\#1196](https://github.com/cosmos/ibc-go/pull/1196) Adding VerifyClientMessage to ClientState interface. +* (modules/core/02-client) [\#1198](https://github.com/cosmos/ibc-go/pull/1198) Adding UpdateStateOnMisbehaviour to ClientState interface. +* (modules/core/02-client) [\#1170](https://github.com/cosmos/ibc-go/pull/1170) Updating `ClientUpdateProposal` to set client state in lightclient implementations `CheckSubstituteAndUpdateState` methods. +* (modules/core/02-client) [\#1197](https://github.com/cosmos/ibc-go/pull/1197) Adding `CheckForMisbehaviour` to `ClientState` interface. +* (modules/core/02-client) [\#1195](https://github.com/cosmos/ibc-go/pull/1210) Removing `CheckHeaderAndUpdateState` from `ClientState` interface & associated light client implementations. +* (modules/core/02-client) [\#1189](https://github.com/cosmos/ibc-go/pull/1212) Removing `CheckMisbehaviourAndUpdateState` from `ClientState` interface & associated light client implementations. +* (modules/core/exported) [\#1206](https://github.com/cosmos/ibc-go/pull/1206) Adding new method `UpdateState` to `ClientState` interface. +* (modules/core/02-client) [\#1741](https://github.com/cosmos/ibc-go/pull/1741) Emitting a new `upgrade_chain` event upon setting upgrade consensus state. +* (client) [\#724](https://github.com/cosmos/ibc-go/pull/724) `IsRevisionFormat` and `IsClientIDFormat` have been updated to disallow newlines before the dash used to separate the chainID and revision number, and the client type and client sequence. +* (02-client/cli) [\#897](https://github.com/cosmos/ibc-go/pull/897) Remove `GetClientID()` from `Misbehaviour` interface. Submit client misbehaviour cli command requires an explicit client id now. +* (06-solomachine) [\#1972](https://github.com/cosmos/ibc-go/pull/1972) Solo machine implementation of `ZeroCustomFields` fn now panics as the fn is only used for upgrades which solo machine does not support. +* (light-clients/06-solomachine) Moving `verifyMisbehaviour` function from update.go to misbehaviour_handle.go. +* [\#2434](https://github.com/cosmos/ibc-go/pull/2478) Removed all `TypeMsg` constants +* (modules/core/exported) [#1689] (https://github.com/cosmos/ibc-go/pull/2539) Removing `GetVersions` from `ConnectionI` interface. +* (core/02-connection) [#2419](https://github.com/cosmos/ibc-go/pull/2419) Add optional proof data to proto definitions of `MsgConnectionOpenTry` and `MsgConnectionOpenAck` for host state machines that are unable to introspect their own consensus state. +* (modules/light-clients/07-tendermint) [#2007](https://github.com/cosmos/ibc-go/pull/3046) Moved non-verification misbehaviour checks to `CheckForMisbehaviour` + +>>>>>>> b2fb1192 (chore: Add `HasConnection` and `HasChannel` methods. (#3082)) ### Features ### Bug Fixes diff --git a/modules/apps/29-fee/keeper/keeper.go b/modules/apps/29-fee/keeper/keeper.go index e506ef8118f..5d0ef4b3811 100644 --- a/modules/apps/29-fee/keeper/keeper.go +++ b/modules/apps/29-fee/keeper/keeper.go @@ -291,7 +291,7 @@ func (k Keeper) GetFeesInEscrow(ctx sdk.Context, packetID channeltypes.PacketId) store := ctx.KVStore(k.storeKey) key := types.KeyFeesInEscrow(packetID) bz := store.Get(key) - if bz == nil { + if len(bz) == 0 { return types.PacketFees{}, false } diff --git a/modules/apps/transfer/keeper/keeper.go b/modules/apps/transfer/keeper/keeper.go index 9688d57aff2..4d57d95b28b 100644 --- a/modules/apps/transfer/keeper/keeper.go +++ b/modules/apps/transfer/keeper/keeper.go @@ -93,7 +93,7 @@ func (k Keeper) SetPort(ctx sdk.Context, portID string) { func (k Keeper) GetDenomTrace(ctx sdk.Context, denomTraceHash tmbytes.HexBytes) (types.DenomTrace, bool) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.DenomTraceKey) bz := store.Get(denomTraceHash) - if bz == nil { + if len(bz) == 0 { return types.DenomTrace{}, false } diff --git a/modules/core/02-client/keeper/keeper.go b/modules/core/02-client/keeper/keeper.go index 634c70494fc..fba24dd5147 100644 --- a/modules/core/02-client/keeper/keeper.go +++ b/modules/core/02-client/keeper/keeper.go @@ -67,7 +67,7 @@ func (k Keeper) GenerateClientIdentifier(ctx sdk.Context, clientType string) str func (k Keeper) GetClientState(ctx sdk.Context, clientID string) (exported.ClientState, bool) { store := k.ClientStore(ctx, clientID) bz := store.Get(host.ClientStateKey()) - if bz == nil { + if len(bz) == 0 { return nil, false } @@ -85,7 +85,7 @@ func (k Keeper) SetClientState(ctx sdk.Context, clientID string, clientState exp func (k Keeper) GetClientConsensusState(ctx sdk.Context, clientID string, height exported.Height) (exported.ConsensusState, bool) { store := k.ClientStore(ctx, clientID) bz := store.Get(host.ConsensusStateKey(height)) - if bz == nil { + if len(bz) == 0 { return nil, false } @@ -104,7 +104,7 @@ func (k Keeper) SetClientConsensusState(ctx sdk.Context, clientID string, height func (k Keeper) GetNextClientSequence(ctx sdk.Context) uint64 { store := ctx.KVStore(k.storeKey) bz := store.Get([]byte(types.KeyNextClientSequence)) - if bz == nil { + if len(bz) == 0 { panic("next client sequence is nil") } diff --git a/modules/core/02-client/migrations/v7/store.go b/modules/core/02-client/migrations/v7/store.go new file mode 100644 index 00000000000..b70e541e671 --- /dev/null +++ b/modules/core/02-client/migrations/v7/store.go @@ -0,0 +1,205 @@ +package v7 + +import ( + "fmt" + "strings" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" + host "github.com/cosmos/ibc-go/v7/modules/core/24-host" + "github.com/cosmos/ibc-go/v7/modules/core/exported" + solomachine "github.com/cosmos/ibc-go/v7/modules/light-clients/06-solomachine" + ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" +) + +// Localhost is the client type for a localhost client. It is also used as the clientID +// for the localhost client. +const Localhost string = "09-localhost" + +// MigrateStore performs in-place store migrations from ibc-go v6 to ibc-go v7. +// The migration includes: +// +// - Migrating solo machine client states from v2 to v3 protobuf definition +// - Pruning all solo machine consensus states +// - Removing the localhost client +// - Asserting existing tendermint clients are properly registered on the chain codec +func MigrateStore(ctx sdk.Context, storeKey storetypes.StoreKey, cdc codec.BinaryCodec, clientKeeper ClientKeeper) error { + store := ctx.KVStore(storeKey) + + if err := handleSolomachineMigration(ctx, store, cdc, clientKeeper); err != nil { + return err + } + + if err := handleTendermintMigration(ctx, store, cdc, clientKeeper); err != nil { + return err + } + + if err := handleLocalhostMigration(ctx, store, cdc, clientKeeper); err != nil { + return err + } + + return nil +} + +// handleSolomachineMigration iterates over the solo machine clients and migrates client state from +// protobuf definition v2 to v3. All consensus states stored outside of the client state are pruned. +func handleSolomachineMigration(ctx sdk.Context, store sdk.KVStore, cdc codec.BinaryCodec, clientKeeper ClientKeeper) error { + clients, err := collectClients(ctx, store, exported.Solomachine) + if err != nil { + return err + } + + for _, clientID := range clients { + clientStore := clientKeeper.ClientStore(ctx, clientID) + + bz := clientStore.Get(host.ClientStateKey()) + if len(bz) == 0 { + return sdkerrors.Wrapf(clienttypes.ErrClientNotFound, "clientID %s", clientID) + } + + var any codectypes.Any + if err := cdc.Unmarshal(bz, &any); err != nil { + return sdkerrors.Wrap(err, "failed to unmarshal client state bytes into solo machine client state") + } + + var clientState ClientState + if err := cdc.Unmarshal(any.Value, &clientState); err != nil { + return sdkerrors.Wrap(err, "failed to unmarshal client state bytes into solo machine client state") + } + + updatedClientState := migrateSolomachine(clientState) + + // update solomachine in store + clientKeeper.SetClientState(ctx, clientID, &updatedClientState) + + removeAllClientConsensusStates(clientStore) + } + + return nil +} + +// handlerTendermintMigration asserts that the tendermint client in state can be decoded properly. +// This ensures the upgrading chain properly registered the tendermint client types on the chain codec. +func handleTendermintMigration(ctx sdk.Context, store sdk.KVStore, cdc codec.BinaryCodec, clientKeeper ClientKeeper) error { + clients, err := collectClients(ctx, store, exported.Tendermint) + if err != nil { + return err + } + + if len(clients) == 0 { + return nil // no-op if no tm clients exist + } + + if len(clients) > 1 { + return sdkerrors.Wrap(sdkerrors.ErrLogic, "more than one Tendermint client collected") + } + + clientID := clients[0] + + // unregistered tendermint client types will panic when unmarshaling the client state + // in GetClientState + clientState, ok := clientKeeper.GetClientState(ctx, clientID) + if !ok { + return sdkerrors.Wrapf(clienttypes.ErrClientNotFound, "clientID %s", clientID) + } + + _, ok = clientState.(*ibctm.ClientState) + if !ok { + return sdkerrors.Wrap(clienttypes.ErrInvalidClient, "client state is not tendermint even though client id contains 07-tendermint") + } + + return nil +} + +// handleLocalhostMigration removes all client and consensus states associated with the localhost client type. +func handleLocalhostMigration(ctx sdk.Context, store sdk.KVStore, cdc codec.BinaryCodec, clientKeeper ClientKeeper) error { + clients, err := collectClients(ctx, store, Localhost) + if err != nil { + return err + } + + for _, clientID := range clients { + clientStore := clientKeeper.ClientStore(ctx, clientID) + + // delete the client state + clientStore.Delete(host.ClientStateKey()) + + removeAllClientConsensusStates(clientStore) + } + + return nil +} + +// collectClients will iterate over the provided client type prefix in the client store +// and return a list of clientIDs associated with the client type. This is necessary to +// avoid state corruption as modifying state during iteration is unsafe. A special case +// for tendermint clients is included as only one tendermint clientID is required for +// v7 migrations. +func collectClients(ctx sdk.Context, store sdk.KVStore, clientType string) (clients []string, err error) { + clientPrefix := []byte(fmt.Sprintf("%s/%s", host.KeyClientStorePrefix, clientType)) + iterator := sdk.KVStorePrefixIterator(store, clientPrefix) + + defer sdk.LogDeferred(ctx.Logger(), func() error { return iterator.Close() }) + for ; iterator.Valid(); iterator.Next() { + path := string(iterator.Key()) + if !strings.Contains(path, host.KeyClientState) { + // skip non client state keys + continue + } + + clientID := host.MustParseClientStatePath(path) + clients = append(clients, clientID) + + // optimization: exit after a single tendermint client iteration + if strings.Contains(clientID, exported.Tendermint) { + return clients, nil + } + } + + return clients, nil +} + +// removeAllClientConsensusStates removes all client consensus states from the associated +// client store. +func removeAllClientConsensusStates(clientStore sdk.KVStore) { + iterator := sdk.KVStorePrefixIterator(clientStore, []byte(host.KeyConsensusStatePrefix)) + var heights []exported.Height + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + keySplit := strings.Split(string(iterator.Key()), "/") + // key is in the format "consensusStates/" + if len(keySplit) != 2 || keySplit[0] != string(host.KeyConsensusStatePrefix) { + continue + } + + // collect consensus states to be pruned + heights = append(heights, clienttypes.MustParseHeight(keySplit[1])) + } + + // delete all consensus states + for _, height := range heights { + clientStore.Delete(host.ConsensusStateKey(height)) + } +} + +// migrateSolomachine migrates the solomachine from v2 to v3 solo machine protobuf definition. +// Notably it drops the AllowUpdateAfterProposal field. +func migrateSolomachine(clientState ClientState) solomachine.ClientState { + consensusState := &solomachine.ConsensusState{ + PublicKey: clientState.ConsensusState.PublicKey, + Diversifier: clientState.ConsensusState.Diversifier, + Timestamp: clientState.ConsensusState.Timestamp, + } + + return solomachine.ClientState{ + Sequence: clientState.Sequence, + IsFrozen: clientState.IsFrozen, + ConsensusState: consensusState, + } +} diff --git a/modules/core/03-connection/keeper/keeper.go b/modules/core/03-connection/keeper/keeper.go index 6620673ab24..ddff53f5224 100644 --- a/modules/core/03-connection/keeper/keeper.go +++ b/modules/core/03-connection/keeper/keeper.go @@ -66,7 +66,7 @@ func (k Keeper) GenerateConnectionIdentifier(ctx sdk.Context) string { func (k Keeper) GetConnection(ctx sdk.Context, connectionID string) (types.ConnectionEnd, bool) { store := ctx.KVStore(k.storeKey) bz := store.Get(host.ConnectionKey(connectionID)) - if bz == nil { + if len(bz) == 0 { return types.ConnectionEnd{}, false } @@ -76,6 +76,13 @@ func (k Keeper) GetConnection(ctx sdk.Context, connectionID string) (types.Conne return connection, true } +// HasConnection returns a true if the connection with the given identifier +// exists in the store. +func (k Keeper) HasConnection(ctx sdk.Context, connectionID string) bool { + store := ctx.KVStore(k.storeKey) + return store.Has(host.ConnectionKey(connectionID)) +} + // SetConnection sets a connection to the store func (k Keeper) SetConnection(ctx sdk.Context, connectionID string, connection types.ConnectionEnd) { store := ctx.KVStore(k.storeKey) @@ -105,7 +112,7 @@ func (k Keeper) GetTimestampAtHeight(ctx sdk.Context, connection types.Connectio func (k Keeper) GetClientConnectionPaths(ctx sdk.Context, clientID string) ([]string, bool) { store := ctx.KVStore(k.storeKey) bz := store.Get(host.ClientConnectionsKey(clientID)) - if bz == nil { + if len(bz) == 0 { return nil, false } @@ -126,7 +133,7 @@ func (k Keeper) SetClientConnectionPaths(ctx sdk.Context, clientID string, paths func (k Keeper) GetNextConnectionSequence(ctx sdk.Context) uint64 { store := ctx.KVStore(k.storeKey) bz := store.Get([]byte(types.KeyNextConnectionSequence)) - if bz == nil { + if len(bz) == 0 { panic("next connection sequence is nil") } diff --git a/modules/core/04-channel/keeper/keeper.go b/modules/core/04-channel/keeper/keeper.go index db05a8457a5..a6d5c4bf967 100644 --- a/modules/core/04-channel/keeper/keeper.go +++ b/modules/core/04-channel/keeper/keeper.go @@ -66,11 +66,17 @@ func (k Keeper) GenerateChannelIdentifier(ctx sdk.Context) string { return channelID } +// HasChannel true if the channel with the given identifiers exists in state. +func (k Keeper) HasChannel(ctx sdk.Context, portID, channelID string) bool { + store := ctx.KVStore(k.storeKey) + return store.Has(host.ChannelKey(portID, channelID)) +} + // GetChannel returns a channel with a particular identifier binded to a specific port func (k Keeper) GetChannel(ctx sdk.Context, portID, channelID string) (types.Channel, bool) { store := ctx.KVStore(k.storeKey) bz := store.Get(host.ChannelKey(portID, channelID)) - if bz == nil { + if len(bz) == 0 { return types.Channel{}, false } @@ -100,7 +106,7 @@ func (k Keeper) GetAppVersion(ctx sdk.Context, portID, channelID string) (string func (k Keeper) GetNextChannelSequence(ctx sdk.Context) uint64 { store := ctx.KVStore(k.storeKey) bz := store.Get([]byte(types.KeyNextChannelSequence)) - if bz == nil { + if len(bz) == 0 { panic("next channel sequence is nil") } @@ -118,7 +124,7 @@ func (k Keeper) SetNextChannelSequence(ctx sdk.Context, sequence uint64) { func (k Keeper) GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) { store := ctx.KVStore(k.storeKey) bz := store.Get(host.NextSequenceSendKey(portID, channelID)) - if bz == nil { + if len(bz) == 0 { return 0, false } @@ -136,7 +142,7 @@ func (k Keeper) SetNextSequenceSend(ctx sdk.Context, portID, channelID string, s func (k Keeper) GetNextSequenceRecv(ctx sdk.Context, portID, channelID string) (uint64, bool) { store := ctx.KVStore(k.storeKey) bz := store.Get(host.NextSequenceRecvKey(portID, channelID)) - if bz == nil { + if len(bz) == 0 { return 0, false } @@ -154,7 +160,7 @@ func (k Keeper) SetNextSequenceRecv(ctx sdk.Context, portID, channelID string, s func (k Keeper) GetNextSequenceAck(ctx sdk.Context, portID, channelID string) (uint64, bool) { store := ctx.KVStore(k.storeKey) bz := store.Get(host.NextSequenceAckKey(portID, channelID)) - if bz == nil { + if len(bz) == 0 { return 0, false } @@ -172,7 +178,7 @@ func (k Keeper) SetNextSequenceAck(ctx sdk.Context, portID, channelID string, se func (k Keeper) GetPacketReceipt(ctx sdk.Context, portID, channelID string, sequence uint64) (string, bool) { store := ctx.KVStore(k.storeKey) bz := store.Get(host.PacketReceiptKey(portID, channelID, sequence)) - if bz == nil { + if len(bz) == 0 { return "", false } @@ -219,7 +225,7 @@ func (k Keeper) SetPacketAcknowledgement(ctx sdk.Context, portID, channelID stri func (k Keeper) GetPacketAcknowledgement(ctx sdk.Context, portID, channelID string, sequence uint64) ([]byte, bool) { store := ctx.KVStore(k.storeKey) bz := store.Get(host.PacketAcknowledgementKey(portID, channelID, sequence)) - if bz == nil { + if len(bz) == 0 { return nil, false } return bz, true diff --git a/modules/core/04-channel/keeper/keeper_test.go b/modules/core/04-channel/keeper/keeper_test.go index ac97d72e7c3..2fcf10e4fb0 100644 --- a/modules/core/04-channel/keeper/keeper_test.go +++ b/modules/core/04-channel/keeper/keeper_test.go @@ -46,7 +46,7 @@ func (suite *KeeperTestSuite) TestSetChannel() { suite.coordinator.SetupConnections(path) // check for channel to be created on chainA - _, found := suite.chainA.App.GetIBCKeeper().ChannelKeeper.GetChannel(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) + found := suite.chainA.App.GetIBCKeeper().ChannelKeeper.HasChannel(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) suite.False(found) path.SetChannelOrdered() diff --git a/modules/light-clients/07-tendermint/types/store.go b/modules/light-clients/07-tendermint/types/store.go index 2a8eacee2e6..f7e58e44c3f 100644 --- a/modules/light-clients/07-tendermint/types/store.go +++ b/modules/light-clients/07-tendermint/types/store.go @@ -54,11 +54,16 @@ func SetConsensusState(clientStore sdk.KVStore, cdc codec.BinaryCodec, consensus // store. An error is returned if the consensus state does not exist. func GetConsensusState(store sdk.KVStore, cdc codec.BinaryCodec, height exported.Height) (*ConsensusState, error) { bz := store.Get(host.ConsensusStateKey(height)) +<<<<<<< HEAD:modules/light-clients/07-tendermint/types/store.go if bz == nil { return nil, sdkerrors.Wrapf( clienttypes.ErrConsensusStateNotFound, "consensus state does not exist for height %s", height, ) +======= + if len(bz) == 0 { + return nil, false +>>>>>>> b2fb1192 (chore: Add `HasConnection` and `HasChannel` methods. (#3082)):modules/light-clients/07-tendermint/store.go } consensusStateI, err := clienttypes.UnmarshalConsensusState(cdc, bz) @@ -138,7 +143,7 @@ func SetProcessedTime(clientStore sdk.KVStore, height exported.Height, timeNs ui func GetProcessedTime(clientStore sdk.KVStore, height exported.Height) (uint64, bool) { key := ProcessedTimeKey(height) bz := clientStore.Get(key) - if bz == nil { + if len(bz) == 0 { return 0, false } return sdk.BigEndianToUint64(bz), true @@ -169,7 +174,7 @@ func SetProcessedHeight(clientStore sdk.KVStore, consHeight, processedHeight exp func GetProcessedHeight(clientStore sdk.KVStore, height exported.Height) (exported.Height, bool) { key := ProcessedHeightKey(height) bz := clientStore.Get(key) - if bz == nil { + if len(bz) == 0 { return nil, false } processedHeight, err := clienttypes.ParseHeight(string(bz)) @@ -320,7 +325,7 @@ func PruneAllExpiredConsensusStates( // Helper function for GetNextConsensusState and GetPreviousConsensusState func getTmConsensusState(clientStore sdk.KVStore, cdc codec.BinaryCodec, key []byte) (*ConsensusState, bool) { bz := clientStore.Get(key) - if bz == nil { + if len(bz) == 0 { return nil, false } From ac6f5ec49a6b296f8c487bb628c29ff9f052199f Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Mon, 15 May 2023 09:14:48 +0200 Subject: [PATCH 2/2] fix conflicts --- CHANGELOG.md | 30 +-- modules/core/02-client/migrations/v7/store.go | 205 ------------------ .../07-tendermint/types/store.go | 7 +- .../09-localhost/types/client_state.go | 6 +- 4 files changed, 5 insertions(+), 243 deletions(-) delete mode 100644 modules/core/02-client/migrations/v7/store.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 4179efbe60a..fb3d5f423e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,36 +46,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements -<<<<<<< HEAD -======= * (core) [\#3082](https://github.com/cosmos/ibc-go/pull/3082) Add `HasConnection` and `HasChannel` methods. -* (tests) [\#2926](https://github.com/cosmos/ibc-go/pull/2926) Lint tests -* (apps/transfer) [\#2643](https://github.com/cosmos/ibc-go/pull/2643) Add amount, denom, and memo to transfer event emission. -* (core) [\#2746](https://github.com/cosmos/ibc-go/pull/2746) Allow proof height to be zero for all core IBC `sdk.Msg` types that contain proofs. -* (light-clients/06-solomachine) [\#2746](https://github.com/cosmos/ibc-go/pull/2746) Discard proofHeight for solo machines and use the solo machine sequence instead. -* (modules/light-clients/07-tendermint) [\#1713](https://github.com/cosmos/ibc-go/pull/1713) Allow client upgrade proposals to update `TrustingPeriod`. See ADR-026 for context. -* (modules/core/02-client) [\#1188](https://github.com/cosmos/ibc-go/pull/1188/files) Routing `MsgSubmitMisbehaviour` to `UpdateClient` keeper function. Deprecating `SubmitMisbehaviour` endpoint. -* (modules/core/02-client) [\#1208](https://github.com/cosmos/ibc-go/pull/1208) Replace `CheckHeaderAndUpdateState` usage in 02-client with calls to `VerifyClientMessage`, `CheckForMisbehaviour`, `UpdateStateOnMisbehaviour` and `UpdateState`. -* (modules/light-clients/09-localhost) [\#1187](https://github.com/cosmos/ibc-go/pull/1187/) Removing localhost light client implementation as it is not functional. An upgrade handler is provided in `modules/migrations/v5` to prune `09-localhost` clients and consensus states from the store. -* [\#1186](https://github.com/cosmos/ibc-go/pull/1186/files) Removing `GetRoot` function from ConsensusState interface in `02-client`. `GetRoot` is unused by core IBC. -* (modules/core/02-client) [\#1196](https://github.com/cosmos/ibc-go/pull/1196) Adding VerifyClientMessage to ClientState interface. -* (modules/core/02-client) [\#1198](https://github.com/cosmos/ibc-go/pull/1198) Adding UpdateStateOnMisbehaviour to ClientState interface. -* (modules/core/02-client) [\#1170](https://github.com/cosmos/ibc-go/pull/1170) Updating `ClientUpdateProposal` to set client state in lightclient implementations `CheckSubstituteAndUpdateState` methods. -* (modules/core/02-client) [\#1197](https://github.com/cosmos/ibc-go/pull/1197) Adding `CheckForMisbehaviour` to `ClientState` interface. -* (modules/core/02-client) [\#1195](https://github.com/cosmos/ibc-go/pull/1210) Removing `CheckHeaderAndUpdateState` from `ClientState` interface & associated light client implementations. -* (modules/core/02-client) [\#1189](https://github.com/cosmos/ibc-go/pull/1212) Removing `CheckMisbehaviourAndUpdateState` from `ClientState` interface & associated light client implementations. -* (modules/core/exported) [\#1206](https://github.com/cosmos/ibc-go/pull/1206) Adding new method `UpdateState` to `ClientState` interface. -* (modules/core/02-client) [\#1741](https://github.com/cosmos/ibc-go/pull/1741) Emitting a new `upgrade_chain` event upon setting upgrade consensus state. -* (client) [\#724](https://github.com/cosmos/ibc-go/pull/724) `IsRevisionFormat` and `IsClientIDFormat` have been updated to disallow newlines before the dash used to separate the chainID and revision number, and the client type and client sequence. -* (02-client/cli) [\#897](https://github.com/cosmos/ibc-go/pull/897) Remove `GetClientID()` from `Misbehaviour` interface. Submit client misbehaviour cli command requires an explicit client id now. -* (06-solomachine) [\#1972](https://github.com/cosmos/ibc-go/pull/1972) Solo machine implementation of `ZeroCustomFields` fn now panics as the fn is only used for upgrades which solo machine does not support. -* (light-clients/06-solomachine) Moving `verifyMisbehaviour` function from update.go to misbehaviour_handle.go. -* [\#2434](https://github.com/cosmos/ibc-go/pull/2478) Removed all `TypeMsg` constants -* (modules/core/exported) [#1689] (https://github.com/cosmos/ibc-go/pull/2539) Removing `GetVersions` from `ConnectionI` interface. -* (core/02-connection) [#2419](https://github.com/cosmos/ibc-go/pull/2419) Add optional proof data to proto definitions of `MsgConnectionOpenTry` and `MsgConnectionOpenAck` for host state machines that are unable to introspect their own consensus state. -* (modules/light-clients/07-tendermint) [#2007](https://github.com/cosmos/ibc-go/pull/3046) Moved non-verification misbehaviour checks to `CheckForMisbehaviour` - ->>>>>>> b2fb1192 (chore: Add `HasConnection` and `HasChannel` methods. (#3082)) + ### Features ### Bug Fixes diff --git a/modules/core/02-client/migrations/v7/store.go b/modules/core/02-client/migrations/v7/store.go deleted file mode 100644 index b70e541e671..00000000000 --- a/modules/core/02-client/migrations/v7/store.go +++ /dev/null @@ -1,205 +0,0 @@ -package v7 - -import ( - "fmt" - "strings" - - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - storetypes "github.com/cosmos/cosmos-sdk/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - - clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" - host "github.com/cosmos/ibc-go/v7/modules/core/24-host" - "github.com/cosmos/ibc-go/v7/modules/core/exported" - solomachine "github.com/cosmos/ibc-go/v7/modules/light-clients/06-solomachine" - ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" -) - -// Localhost is the client type for a localhost client. It is also used as the clientID -// for the localhost client. -const Localhost string = "09-localhost" - -// MigrateStore performs in-place store migrations from ibc-go v6 to ibc-go v7. -// The migration includes: -// -// - Migrating solo machine client states from v2 to v3 protobuf definition -// - Pruning all solo machine consensus states -// - Removing the localhost client -// - Asserting existing tendermint clients are properly registered on the chain codec -func MigrateStore(ctx sdk.Context, storeKey storetypes.StoreKey, cdc codec.BinaryCodec, clientKeeper ClientKeeper) error { - store := ctx.KVStore(storeKey) - - if err := handleSolomachineMigration(ctx, store, cdc, clientKeeper); err != nil { - return err - } - - if err := handleTendermintMigration(ctx, store, cdc, clientKeeper); err != nil { - return err - } - - if err := handleLocalhostMigration(ctx, store, cdc, clientKeeper); err != nil { - return err - } - - return nil -} - -// handleSolomachineMigration iterates over the solo machine clients and migrates client state from -// protobuf definition v2 to v3. All consensus states stored outside of the client state are pruned. -func handleSolomachineMigration(ctx sdk.Context, store sdk.KVStore, cdc codec.BinaryCodec, clientKeeper ClientKeeper) error { - clients, err := collectClients(ctx, store, exported.Solomachine) - if err != nil { - return err - } - - for _, clientID := range clients { - clientStore := clientKeeper.ClientStore(ctx, clientID) - - bz := clientStore.Get(host.ClientStateKey()) - if len(bz) == 0 { - return sdkerrors.Wrapf(clienttypes.ErrClientNotFound, "clientID %s", clientID) - } - - var any codectypes.Any - if err := cdc.Unmarshal(bz, &any); err != nil { - return sdkerrors.Wrap(err, "failed to unmarshal client state bytes into solo machine client state") - } - - var clientState ClientState - if err := cdc.Unmarshal(any.Value, &clientState); err != nil { - return sdkerrors.Wrap(err, "failed to unmarshal client state bytes into solo machine client state") - } - - updatedClientState := migrateSolomachine(clientState) - - // update solomachine in store - clientKeeper.SetClientState(ctx, clientID, &updatedClientState) - - removeAllClientConsensusStates(clientStore) - } - - return nil -} - -// handlerTendermintMigration asserts that the tendermint client in state can be decoded properly. -// This ensures the upgrading chain properly registered the tendermint client types on the chain codec. -func handleTendermintMigration(ctx sdk.Context, store sdk.KVStore, cdc codec.BinaryCodec, clientKeeper ClientKeeper) error { - clients, err := collectClients(ctx, store, exported.Tendermint) - if err != nil { - return err - } - - if len(clients) == 0 { - return nil // no-op if no tm clients exist - } - - if len(clients) > 1 { - return sdkerrors.Wrap(sdkerrors.ErrLogic, "more than one Tendermint client collected") - } - - clientID := clients[0] - - // unregistered tendermint client types will panic when unmarshaling the client state - // in GetClientState - clientState, ok := clientKeeper.GetClientState(ctx, clientID) - if !ok { - return sdkerrors.Wrapf(clienttypes.ErrClientNotFound, "clientID %s", clientID) - } - - _, ok = clientState.(*ibctm.ClientState) - if !ok { - return sdkerrors.Wrap(clienttypes.ErrInvalidClient, "client state is not tendermint even though client id contains 07-tendermint") - } - - return nil -} - -// handleLocalhostMigration removes all client and consensus states associated with the localhost client type. -func handleLocalhostMigration(ctx sdk.Context, store sdk.KVStore, cdc codec.BinaryCodec, clientKeeper ClientKeeper) error { - clients, err := collectClients(ctx, store, Localhost) - if err != nil { - return err - } - - for _, clientID := range clients { - clientStore := clientKeeper.ClientStore(ctx, clientID) - - // delete the client state - clientStore.Delete(host.ClientStateKey()) - - removeAllClientConsensusStates(clientStore) - } - - return nil -} - -// collectClients will iterate over the provided client type prefix in the client store -// and return a list of clientIDs associated with the client type. This is necessary to -// avoid state corruption as modifying state during iteration is unsafe. A special case -// for tendermint clients is included as only one tendermint clientID is required for -// v7 migrations. -func collectClients(ctx sdk.Context, store sdk.KVStore, clientType string) (clients []string, err error) { - clientPrefix := []byte(fmt.Sprintf("%s/%s", host.KeyClientStorePrefix, clientType)) - iterator := sdk.KVStorePrefixIterator(store, clientPrefix) - - defer sdk.LogDeferred(ctx.Logger(), func() error { return iterator.Close() }) - for ; iterator.Valid(); iterator.Next() { - path := string(iterator.Key()) - if !strings.Contains(path, host.KeyClientState) { - // skip non client state keys - continue - } - - clientID := host.MustParseClientStatePath(path) - clients = append(clients, clientID) - - // optimization: exit after a single tendermint client iteration - if strings.Contains(clientID, exported.Tendermint) { - return clients, nil - } - } - - return clients, nil -} - -// removeAllClientConsensusStates removes all client consensus states from the associated -// client store. -func removeAllClientConsensusStates(clientStore sdk.KVStore) { - iterator := sdk.KVStorePrefixIterator(clientStore, []byte(host.KeyConsensusStatePrefix)) - var heights []exported.Height - - defer iterator.Close() - for ; iterator.Valid(); iterator.Next() { - keySplit := strings.Split(string(iterator.Key()), "/") - // key is in the format "consensusStates/" - if len(keySplit) != 2 || keySplit[0] != string(host.KeyConsensusStatePrefix) { - continue - } - - // collect consensus states to be pruned - heights = append(heights, clienttypes.MustParseHeight(keySplit[1])) - } - - // delete all consensus states - for _, height := range heights { - clientStore.Delete(host.ConsensusStateKey(height)) - } -} - -// migrateSolomachine migrates the solomachine from v2 to v3 solo machine protobuf definition. -// Notably it drops the AllowUpdateAfterProposal field. -func migrateSolomachine(clientState ClientState) solomachine.ClientState { - consensusState := &solomachine.ConsensusState{ - PublicKey: clientState.ConsensusState.PublicKey, - Diversifier: clientState.ConsensusState.Diversifier, - Timestamp: clientState.ConsensusState.Timestamp, - } - - return solomachine.ClientState{ - Sequence: clientState.Sequence, - IsFrozen: clientState.IsFrozen, - ConsensusState: consensusState, - } -} diff --git a/modules/light-clients/07-tendermint/types/store.go b/modules/light-clients/07-tendermint/types/store.go index f7e58e44c3f..e7c79e49cb8 100644 --- a/modules/light-clients/07-tendermint/types/store.go +++ b/modules/light-clients/07-tendermint/types/store.go @@ -54,16 +54,11 @@ func SetConsensusState(clientStore sdk.KVStore, cdc codec.BinaryCodec, consensus // store. An error is returned if the consensus state does not exist. func GetConsensusState(store sdk.KVStore, cdc codec.BinaryCodec, height exported.Height) (*ConsensusState, error) { bz := store.Get(host.ConsensusStateKey(height)) -<<<<<<< HEAD:modules/light-clients/07-tendermint/types/store.go - if bz == nil { + if len(bz) == 0 { return nil, sdkerrors.Wrapf( clienttypes.ErrConsensusStateNotFound, "consensus state does not exist for height %s", height, ) -======= - if len(bz) == 0 { - return nil, false ->>>>>>> b2fb1192 (chore: Add `HasConnection` and `HasChannel` methods. (#3082)):modules/light-clients/07-tendermint/store.go } consensusStateI, err := clienttypes.UnmarshalConsensusState(cdc, bz) diff --git a/modules/light-clients/09-localhost/types/client_state.go b/modules/light-clients/09-localhost/types/client_state.go index 961d84837b5..02ee525e473 100644 --- a/modules/light-clients/09-localhost/types/client_state.go +++ b/modules/light-clients/09-localhost/types/client_state.go @@ -121,7 +121,7 @@ func (cs ClientState) VerifyClientState( ) error { path := host.KeyClientState bz := store.Get([]byte(path)) - if bz == nil { + if len(bz) == 0 { return sdkerrors.Wrapf(clienttypes.ErrFailedClientStateVerification, "not found for path: %s", path) } @@ -160,7 +160,7 @@ func (cs ClientState) VerifyConnectionState( ) error { path := host.ConnectionKey(connectionID) bz := store.Get(path) - if bz == nil { + if len(bz) == 0 { return sdkerrors.Wrapf(clienttypes.ErrFailedConnectionStateVerification, "not found for path %s", path) } @@ -194,7 +194,7 @@ func (cs ClientState) VerifyChannelState( ) error { path := host.ChannelKey(portID, channelID) bz := store.Get(path) - if bz == nil { + if len(bz) == 0 { return sdkerrors.Wrapf(clienttypes.ErrFailedChannelStateVerification, "not found for path %s", path) }