diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6aff1fcc83e..9845d1492ee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -44,7 +44,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### API Breaking
-* (core/03-connection) [\#1797](https://github.com/cosmos/ibc-go/pull/1797) Remove `PreviousConnectionID` from `NewMsgConnectionOpenTry` arguments. `MsgConnectionOpenTry.ValidateBasic()` returns error if the deprecated `PreviousConnectionID` is not empty.
+* (core/03-connection) [\#1797](https://github.com/cosmos/ibc-go/pull/1797) Remove `PreviousConnectionID` from `NewMsgConnectionOpenTry` arguments. `MsgConnectionOpenTry.ValidateBasic()` returns error if the deprecated `PreviousConnectionID` is not empty
* (core/04-channel) [\#1792](https://github.com/cosmos/ibc-go/pull/1792) Remove `PreviousChannelID` from `NewMsgChannelOpenTry` arguments. `MsgChannelOpenTry.ValidateBasic()` returns error if the deprecated `PreviousChannelID` is not empty.
* (core/04-channel) [\#1418](https://github.com/cosmos/ibc-go/pull/1418) `NewPacketId` has been renamed to `NewPacketID` to comply with go linting rules.
* (core/ante) [\#1418](https://github.com/cosmos/ibc-go/pull/1418) `AnteDecorator` has been renamed to `RedundancyDecorator` to comply with go linting rules and to give more clarity to the purpose of the Decorator.
@@ -61,6 +61,18 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (transfer)[\#1565](https://github.com/cosmos/ibc-go/pull/1565) Removing `NewErrorAcknowledgement` in favour of `channeltypes.NewErrorAcknowledgement`.
* (channel)[\#1565](https://github.com/cosmos/ibc-go/pull/1565) Updating `NewErrorAcknowledgement` to accept an error instead of a string and removing the possibility of non-deterministic writes to application state.
* (core/04-channel)[\#1636](https://github.com/cosmos/ibc-go/pull/1636) Removing `SplitChannelVersion` and `MergeChannelVersions` functions since they are not used.
+-
+* (06-solomachine) [\#1679](https://github.com/cosmos/ibc-go/pull/1679) Remove `types` sub-package from `06-solomachine` lightclient directory.
+* (07-tendermint) [\#1677](https://github.com/cosmos/ibc-go/pull/1677) Remove `types` sub-package from `07-tendermint` lightclient directory.
+* (06-solomachine) [\#1687](https://github.com/cosmos/ibc-go/pull/1687) Bump `06-solomachine` protobuf version from `v2` to `v3`.
+* (06-solomachine) [\#1687](https://github.com/cosmos/ibc-go/pull/1687) Removed `DataType` enum and associated message types from `06-solomachine`. `DataType` has been removed from `SignBytes` and `SignatureAndData` in favour of `path`.
+* (02-client) [\#598](https://github.com/cosmos/ibc-go/pull/598) The client state and consensus state return value has been removed from `VerifyUpgradeAndUpdateState`. Light client implementations must update the client state and consensus state after verifying a valid client upgrade.
+* (06-solomachine) [\#1100](https://github.com/cosmos/ibc-go/pull/1100) Remove `GetClientID` function from 06-solomachine `Misbehaviour` type.
+* (06-solomachine) [\#1100](https://github.com/cosmos/ibc-go/pull/1100) Deprecate `ClientId` field in 06-solomachine `Misbehaviour` type.
+* (07-tendermint) [\#1097](https://github.com/cosmos/ibc-go/pull/1097) Remove `GetClientID` function from 07-tendermint `Misbehaviour` type.
+* (07-tendermint) [\#1097](https://github.com/cosmos/ibc-go/pull/1097) Deprecate `ClientId` field in 07-tendermint `Misbehaviour` type.
+* (modules/core/exported) [\#1107](https://github.com/cosmos/ibc-go/pull/1107) Merging the `Header` and `Misbehaviour` interfaces into a single `ClientMessage` type.
+* (07-tendermint) [\#1896](https://github.com/cosmos/ibc-go/pull/1896) Remove error return from `IterateConsensusStateAscending` in `07-tendermint`.
### State Machine Breaking
@@ -79,7 +91,22 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (app/29-fee) [\#1341](https://github.com/cosmos/ibc-go/pull/1341) Check if the fee module is locked and if the fee module is enabled before refunding all fees
* (transfer) [\#1414](https://github.com/cosmos/ibc-go/pull/1414) Emitting Sender address from `fungible_token_packet` events in `OnRecvPacket` and `OnAcknowledgementPacket`.
* (testing/simapp) [\#1397](https://github.com/cosmos/ibc-go/pull/1397) Adding mock module to maccperms and adding check to ensure mock module is not a blocked account address.
+-
* (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.
### Features
@@ -94,6 +121,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (apps/29-fee) [\#1774](https://github.com/cosmos/ibc-go/pull/1774) Change non nil relayer assertion to non empty to avoid import/export issues for genesis upgrades.
* (makefile) [\#1785](https://github.com/cosmos/ibc-go/pull/1785) Fetch the correct versions of protocol buffers dependencies from tendermint, cosmos-sdk, and ics23.
* (apps/29-fee) [\#1278](https://github.com/cosmos/ibc-go/pull/1278) The URI path for the query to get all incentivized packets for a specific channel did not follow the same format as the rest of queries.
+-
+* (light-clients/solomachine) [#1839](https://github.com/cosmos/ibc-go/issues/1839) Fixed usage of the new diversifier in validation of changing diversifiers for the solo machine. The current diversifier must sign over the new diversifier.
+* (light-clients/07-tendermint) [\#1674](https://github.com/cosmos/ibc-go/pull/1674) Submitted ClientState is zeroed out before checking the proof in order to prevent the proposal from containing information governance is not actually voting on.
+* (modules/core/02-client)[\#1676](https://github.com/cosmos/ibc-go/pull/1676) ClientState must be zeroed out for `UpgradeProposals` to pass validation. This prevents a proposal containing information governance is not actually voting on.
## [v3.1.1](https://github.com/cosmos/ibc-go/releases/tag/v3.1.1) - 2022-08-02
@@ -191,6 +222,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Improvements
+* (client) [\#888](https://github.com/cosmos/ibc-go/pull/888) Add `GetTimestampAtHeight` to `ClientState`
* (interchain-accounts) [\#1037](https://github.com/cosmos/ibc-go/pull/1037) Add a function `InitModule` to the interchain accounts `AppModule`. This function should be called within the upgrade handler when adding the interchain accounts module to a chain. It should be called in place of InitGenesis (set the consensus version in the version map).
* (testing) [\#942](https://github.com/cosmos/ibc-go/pull/942) `NewTestChain` will create 4 validators in validator set by default. A new constructor function `NewTestChainWithValSet` is provided for test writers who want custom control over the validator set of test chains.
* (testing) [\#904](https://github.com/cosmos/ibc-go/pull/904) Add `ParsePacketFromEvents` function to the testing package. Useful when sending/relaying packets via the testing package.
@@ -200,9 +232,9 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (channel) [\#692](https://github.com/cosmos/ibc-go/pull/692) Minimize channel logging by only emitting the packet sequence, source port/channel, destination port/channel upon packet receives, acknowledgements and timeouts.
* [\#383](https://github.com/cosmos/ibc-go/pull/383) Adds helper functions for merging and splitting middleware versions from the underlying app version.
* (modules/core/05-port) [\#288](https://github.com/cosmos/ibc-go/issues/288) Making the 05-port keeper function IsBound public. The IsBound function checks if the provided portID is already binded to a module.
+* (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.
* (channel) [\#644](https://github.com/cosmos/ibc-go/pull/644) Adds `GetChannelConnection` to the ChannelKeeper. This function returns the connectionID and connection state associated with a channel.
* (channel) [\647](https://github.com/cosmos/ibc-go/pull/647) Reorganizes channel handshake handling to set channel state after IBC application callbacks.
-* (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.
* (interchain-accounts) [\#1466](https://github.com/cosmos/ibc-go/pull/1466) Emit event when there is an acknowledgement during `OnRecvPacket`.
### Features
diff --git a/README.md b/README.md
index f4a830c5149..ff3e074b04f 100644
--- a/README.md
+++ b/README.md
@@ -64,8 +64,6 @@ The Inter-Blockchain Communication protocol (IBC) allows blockchains to talk to
3.2 [ICS 06 Solo Machine](https://github.com/cosmos/ibc-go/tree/main/modules/light-clients/06-solomachine)
-Note: The localhost client is currently non-functional.
-
## Roadmap
For an overview of upcoming changes to ibc-go take a look at the [roadmap](./docs/roadmap/roadmap.md).
diff --git a/docs/OLD_README.md b/docs/OLD_README.md
index 47bb2547732..df9cd52112a 100644
--- a/docs/OLD_README.md
+++ b/docs/OLD_README.md
@@ -28,8 +28,6 @@ For the general specification please refer to the [Interchain Standards](https:/
3.2 [Tendermint Client](./../light-clients/07-tendermint/spec/README.md)
- 3.3 [Localhost Client](./../light-clients/09-localhost/spec/README.md)
-
## Implementation Details
As stated above, the IBC implementation on the Cosmos SDK introduces some changes
@@ -114,4 +112,4 @@ x/ibc
│ └── 09-localhost/
└── testing/
```
-
\ No newline at end of file
+
diff --git a/docs/architecture/adr-005-consensus-height-events.md b/docs/architecture/adr-005-consensus-height-events.md
new file mode 100644
index 00000000000..430d7064a1e
--- /dev/null
+++ b/docs/architecture/adr-005-consensus-height-events.md
@@ -0,0 +1,88 @@
+# ADR 005: UpdateClient Events - ClientState Consensus Heights
+
+## Changelog
+* 25/04/2022: initial draft
+
+## Status
+
+Accepted
+
+## Context
+
+The `ibc-go` implementation leverages the [Cosmos-SDK's EventManager](https://github.com/cosmos/cosmos-sdk/blob/v0.45.4/docs/core/events.md#EventManager) to provide subscribers a method of reacting to application specific events.
+Some IBC relayers depend on the [`consensus_height`](https://github.com/cosmos/ibc-go/blob/v3.0.0/modules/core/02-client/keeper/events.go#L33) attribute emitted as part of `UpdateClient` events in order to run `07-tendermint` misbehaviour detection by cross-checking the details of the *Header* emitted at a given consensus height against those of the *Header* from the originating chain. This includes such details as:
+
+- The `SignedHeader` containing the commitment root.
+- The `ValidatorSet` that signed the *Header*.
+- The `TrustedHeight` seen by the client at less than or equal to the height of *Header*.
+- The last `TrustedValidatorSet` at the trusted height.
+
+Following the refactor of the `02-client` submodule and associated `ClientState` interfaces, it will now be possible for
+light client implementations to perform such actions as batch updates, inserting `N` number of `ConsensusState`s into the application state tree with a single `UpdateClient` message. This flexibility is provided in `ibc-go` by the usage of the [Protobuf `Any`](https://developers.google.com/protocol-buffers/docs/proto3#any) field contained within the [`UpdateClient`](https://github.com/cosmos/ibc-go/blob/v3.0.0/proto/ibc/core/client/v1/tx.proto#L44) message.
+For example, a batched client update message serialized as a Protobuf `Any` type for the `07-tendermint` lightclient implementation could be defined as follows:
+
+```protobuf
+message BatchedHeaders {
+ repeated Header headers = 1;
+}
+```
+
+To complement this flexibility, the `UpdateClient` handler will now support the submission of [client misbehaviour](https://github.com/cosmos/ibc/tree/master/spec/core/ics-002-client-semantics#misbehaviour) by consolidating the `Header` and `Misbehaviour` interfaces into a single `ClientMessage` interface type:
+
+```go
+// ClientMessage is an interface used to update an IBC client.
+// The update may be done by a single header, a batch of headers, misbehaviour, or any type which when verified produces
+// a change to state of the IBC client
+type ClientMessage interface {
+ proto.Message
+
+ ClientType() string
+ ValidateBasic() error
+}
+```
+
+To support this functionality the `GetHeight()` method has been omitted from the new `ClientMessage` interface.
+Emission of standardised events from the `02-client` submodule now becomes problematic and is two-fold:
+
+1. The `02-client` submodule previously depended upon the `GetHeight()` method of `Header` types in order to [retrieve the updated consensus height](https://github.com/cosmos/ibc-go/blob/v3.0.0/modules/core/02-client/keeper/client.go#L90).
+2. Emitting a single `consensus_height` event attribute is not sufficient in the case of a batched client update containing multiple *Headers*.
+
+## Decision
+
+The following decisions have been made in order to provide flexibility to consumers of `UpdateClient` events in a non-breaking fashion:
+
+1. Return a list of updated consensus heights `[]exported.Height` from the new `UpdateState` method of the `ClientState` interface.
+
+```go
+// UpdateState updates and stores as necessary any associated information for an IBC client, such as the ClientState and corresponding ConsensusState.
+// Upon successful update, a list of consensus heights is returned. It assumes the ClientMessage has already been verified.
+UpdateState(sdk.Context, codec.BinaryCodec, sdk.KVStore, ClientMessage) []Height
+```
+
+2. Maintain the `consensus_height` event attribute emitted from the `02-client` update handler, but mark as deprecated for future removal. For example, with tendermint lightclients this will simply be `consensusHeights[0]` following a successful update using a single *Header*.
+
+3. Add an additional `consensus_heights` event attribute, containing a comma separated list of updated heights. This provides flexibility for emitting a single consensus height or multiple consensus heights in the example use-case of batched header updates.
+
+## Consequences
+
+### Positive
+
+- Subscribers of IBC core events can act upon `UpdateClient` events containing one or more consensus heights.
+- Deprecation of the existing `consensus_height` attribute allows consumers to continue to process `UpdateClient` events as normal, with a path to upgrade to using the `consensus_heights` attribute moving forward.
+
+### Negative
+
+- Consumers of IBC core `UpdateClient` events are forced to make future code changes.
+
+### Neutral
+
+## References
+
+Discussions:
+- [#1208](https://github.com/cosmos/ibc-go/pull/1208#discussion_r839691927)
+
+Issues:
+- [#594](https://github.com/cosmos/ibc-go/issues/594)
+
+PRs:
+- [#1285](https://github.com/cosmos/ibc-go/pull/1285)
diff --git a/docs/architecture/adr-027-ibc-wasm.md b/docs/architecture/adr-027-ibc-wasm.md
index d105c9854b4..4197735e3a7 100644
--- a/docs/architecture/adr-027-ibc-wasm.md
+++ b/docs/architecture/adr-027-ibc-wasm.md
@@ -100,7 +100,7 @@ packaged inside a payload which is json serialized and passed to `callContract`
array of bytes returned by the smart contract. This data is deserialized and passed as return argument.
```go
-func (c *ClientState) CheckProposedHeaderAndUpdateState(context sdk.Context, marshaler codec.BinaryMarshaler, store sdk.KVStore, header exported.Header) (exported.ClientState, exported.ConsensusState, error) {
+func (c *ClientState) CheckProposedHeaderAndUpdateState(context sdk.Context, marshaler codec.BinaryMarshaler, store sdk.KVStore, header exported.ClientMessage) (exported.ClientState, exported.ConsensusState, error) {
// get consensus state corresponding to client state to check if the client is expired
consensusState, err := GetConsensusState(store, marshaler, c.LatestHeight)
if err != nil {
diff --git a/docs/ibc/integration.md b/docs/ibc/integration.md
index d2d9f057ea3..0b01ffd7347 100644
--- a/docs/ibc/integration.md
+++ b/docs/ibc/integration.md
@@ -175,17 +175,6 @@ at each height during the `BeginBlock` call. The historical info is required to
past historical info at any given height in order to verify the light client `ConsensusState` during the
connection handhake.
-The IBC module also has
-[`BeginBlock`](https://github.com/cosmos/ibc-go/blob/main/modules/core/02-client/abci.go) logic as
-well. This is optional as it is only required if your application uses the [localhost
-client](https://github.com/cosmos/ibc/blob/master/spec/client/ics-009-loopback-client) to connect two
-different modules from the same chain.
-
-::: tip
-Only register the ibc module to the `SetOrderBeginBlockers` if your application will use the
-localhost (_aka_ loopback) client.
-:::
-
```go
// app.go
func NewApp(...args) *App {
diff --git a/docs/ibc/middleware/develop.md b/docs/ibc/middleware/develop.md
index 3c0c74a0186..7ee020ca9c8 100644
--- a/docs/ibc/middleware/develop.md
+++ b/docs/ibc/middleware/develop.md
@@ -408,6 +408,26 @@ func GetAppVersion(
return metadata.AppVersion, true
}
+
+// middleware must return the underlying application version
+func GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) {
+ version, found := ics4Keeper.GetAppVersion(ctx, portID, channelID)
+ if !found {
+ return "", false
+ }
+
+ if !MiddlewareEnabled {
+ return version, true
+ }
+
+ // unwrap channel version
+ metadata, err := Unmarshal(version)
+ if err != nil {
+ panic(fmt.Errof("unable to unmarshal version: %w", err))
+ }
+
+ return metadata.AppVersion, true
+}
```
See [here](https://github.com/cosmos/ibc-go/blob/48a6ae512b4ea42c29fdf6c6f5363f50645591a2/modules/apps/29-fee/ibc_middleware.go#L355-L358) an example implementation of this function for the ICS29 Fee Middleware module.
diff --git a/docs/ibc/proto-docs.md b/docs/ibc/proto-docs.md
index c612a0180b3..48219f3d66b 100644
--- a/docs/ibc/proto-docs.md
+++ b/docs/ibc/proto-docs.md
@@ -295,9 +295,6 @@
- [ibc/core/types/v1/genesis.proto](#ibc/core/types/v1/genesis.proto)
- [GenesisState](#ibc.core.types.v1.GenesisState)
-- [ibc/lightclients/localhost/v1/localhost.proto](#ibc/lightclients/localhost/v1/localhost.proto)
- - [ClientState](#ibc.lightclients.localhost.v1.ClientState)
-
- [ibc/lightclients/solomachine/v1/solomachine.proto](#ibc/lightclients/solomachine/v1/solomachine.proto)
- [ChannelStateData](#ibc.lightclients.solomachine.v1.ChannelStateData)
- [ClientState](#ibc.lightclients.solomachine.v1.ClientState)
@@ -338,6 +335,16 @@
- [DataType](#ibc.lightclients.solomachine.v2.DataType)
+- [ibc/lightclients/solomachine/v3/solomachine.proto](#ibc/lightclients/solomachine/v3/solomachine.proto)
+ - [ClientState](#ibc.lightclients.solomachine.v3.ClientState)
+ - [ConsensusState](#ibc.lightclients.solomachine.v3.ConsensusState)
+ - [Header](#ibc.lightclients.solomachine.v3.Header)
+ - [HeaderData](#ibc.lightclients.solomachine.v3.HeaderData)
+ - [Misbehaviour](#ibc.lightclients.solomachine.v3.Misbehaviour)
+ - [SignBytes](#ibc.lightclients.solomachine.v3.SignBytes)
+ - [SignatureAndData](#ibc.lightclients.solomachine.v3.SignatureAndData)
+ - [TimestampedSignatureData](#ibc.lightclients.solomachine.v3.TimestampedSignatureData)
+
- [ibc/lightclients/tendermint/v1/tendermint.proto](#ibc/lightclients/tendermint/v1/tendermint.proto)
- [ClientState](#ibc.lightclients.tendermint.v1.ClientState)
- [ConsensusState](#ibc.lightclients.tendermint.v1.ConsensusState)
@@ -3549,13 +3556,14 @@ MsgCreateClientResponse defines the Msg/CreateClient response type.
### MsgSubmitMisbehaviour
MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for
light client misbehaviour.
+Warning: DEPRECATED
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
-| `client_id` | [string](#string) | | client unique identifier |
-| `misbehaviour` | [google.protobuf.Any](#google.protobuf.Any) | | misbehaviour used for freezing the light client |
-| `signer` | [string](#string) | | signer address |
+| `client_id` | [string](#string) | | **Deprecated.** client unique identifier |
+| `misbehaviour` | [google.protobuf.Any](#google.protobuf.Any) | | **Deprecated.** misbehaviour used for freezing the light client |
+| `signer` | [string](#string) | | **Deprecated.** signer address |
@@ -3577,13 +3585,13 @@ type.
### MsgUpdateClient
MsgUpdateClient defines an sdk.Msg to update a IBC client state using
-the given header.
+the given client message.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `client_id` | [string](#string) | | client unique identifier |
-| `header` | [google.protobuf.Any](#google.protobuf.Any) | | header to update the light client |
+| `client_message` | [google.protobuf.Any](#google.protobuf.Any) | | client message to update the light client |
| `signer` | [string](#string) | | signer address |
@@ -4316,39 +4324,6 @@ GenesisState defines the ibc module's genesis state.
-
-
-
-
-
-
-
-
-
-
-
-
Top
-
-## ibc/lightclients/localhost/v1/localhost.proto
-
-
-
-
-
-### ClientState
-ClientState defines a loopback (localhost) client. It requires (read-only)
-access to keys outside the client prefix.
-
-
-| Field | Type | Label | Description |
-| ----- | ---- | ----- | ----------- |
-| `chain_id` | [string](#string) | | self chain ID |
-| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | self latest block height |
-
-
-
-
-
@@ -4995,6 +4970,169 @@ to preserve uniqueness of different data sign byte encodings.
+
+Top
+
+## ibc/lightclients/solomachine/v3/solomachine.proto
+
+
+
+
+
+### ClientState
+ClientState defines a solo machine client that tracks the current consensus
+state and if the client is frozen.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| `sequence` | [uint64](#uint64) | | latest sequence of the client state |
+| `is_frozen` | [bool](#bool) | | frozen sequence of the solo machine |
+| `consensus_state` | [ConsensusState](#ibc.lightclients.solomachine.v3.ConsensusState) | | |
+| `allow_update_after_proposal` | [bool](#bool) | | when set to true, will allow governance to update a solo machine client. The client will be unfrozen if it is frozen. |
+
+
+
+
+
+
+
+
+### ConsensusState
+ConsensusState defines a solo machine consensus state. The sequence of a
+consensus state is contained in the "height" key used in storing the
+consensus state.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public key of the solo machine |
+| `diversifier` | [string](#string) | | diversifier allows the same public key to be re-used across different solo machine clients (potentially on different chains) without being considered misbehaviour. |
+| `timestamp` | [uint64](#uint64) | | |
+
+
+
+
+
+
+
+
+### Header
+Header defines a solo machine consensus header
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| `sequence` | [uint64](#uint64) | | sequence to update solo machine public key at |
+| `timestamp` | [uint64](#uint64) | | |
+| `signature` | [bytes](#bytes) | | |
+| `new_public_key` | [google.protobuf.Any](#google.protobuf.Any) | | |
+| `new_diversifier` | [string](#string) | | |
+
+
+
+
+
+
+
+
+### HeaderData
+HeaderData returns the SignBytes data for update verification.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| `new_pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | header public key |
+| `new_diversifier` | [string](#string) | | header diversifier |
+
+
+
+
+
+
+
+
+### Misbehaviour
+Misbehaviour defines misbehaviour for a solo machine which consists
+of a sequence and two signatures over different messages at that sequence.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| `client_id` | [string](#string) | | **Deprecated.** ClientID is deprecated |
+| `sequence` | [uint64](#uint64) | | |
+| `signature_one` | [SignatureAndData](#ibc.lightclients.solomachine.v3.SignatureAndData) | | |
+| `signature_two` | [SignatureAndData](#ibc.lightclients.solomachine.v3.SignatureAndData) | | |
+
+
+
+
+
+
+
+
+### SignBytes
+SignBytes defines the signed bytes used for signature verification.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| `sequence` | [uint64](#uint64) | | the sequence number |
+| `timestamp` | [uint64](#uint64) | | the proof timestamp |
+| `diversifier` | [string](#string) | | the public key diversifier |
+| `path` | [bytes](#bytes) | | the standardised path bytes |
+| `data` | [bytes](#bytes) | | the marshaled data bytes |
+
+
+
+
+
+
+
+
+### SignatureAndData
+SignatureAndData contains a signature and the data signed over to create that
+signature.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| `signature` | [bytes](#bytes) | | |
+| `path` | [bytes](#bytes) | | |
+| `data` | [bytes](#bytes) | | |
+| `timestamp` | [uint64](#uint64) | | |
+
+
+
+
+
+
+
+
+### TimestampedSignatureData
+TimestampedSignatureData contains the signature data and the timestamp of the
+signature.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| `signature_data` | [bytes](#bytes) | | |
+| `timestamp` | [uint64](#uint64) | | |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Top
@@ -5100,7 +5238,7 @@ that implements Misbehaviour interface expected by ICS-02
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
-| `client_id` | [string](#string) | | |
+| `client_id` | [string](#string) | | **Deprecated.** ClientID is deprecated |
| `header_1` | [Header](#ibc.lightclients.tendermint.v1.Header) | | |
| `header_2` | [Header](#ibc.lightclients.tendermint.v1.Header) | | |
diff --git a/docs/migrations/v5-to-v6.md b/docs/migrations/v5-to-v6.md
new file mode 100644
index 00000000000..70e9519f4e3
--- /dev/null
+++ b/docs/migrations/v5-to-v6.md
@@ -0,0 +1,101 @@
+# Migrating from ibc-go v5 to v6
+
+This document is intended to highlight significant changes which may require more information than presented in the CHANGELOG.
+Any changes that must be done by a user of ibc-go should be documented here.
+
+There are four sections based on the four potential user groups of this document:
+- Chains
+- IBC Apps
+- Relayers
+- IBC Light Clients
+
+**Note:** ibc-go supports golang semantic versioning and therefore all imports must be updated to bump the version number on major releases.
+
+## Chains
+
+- No relevant changes were made in this release.
+
+## IBC Apps
+
+- No relevant changes were made in this release.
+
+## Relayers
+
+- No relevant changes were made in this release.
+
+## IBC Light Clients
+
+### `ClientState` interface changes
+
+The `VerifyUpgradeAndUpdateState` function has been modified. The client state and consensus state return values have been removed.
+
+Light clients **must** handle all management of client and consensus states including the setting of updated client state and consensus state in the client store.
+
+The `CheckHeaderAndUpdateState` function has been split into 4 new functions:
+
+- `VerifyClientMessage` verifies a `ClientMessage`. A `ClientMessage` could be a `Header`, `Misbehaviour`, or batch update. Calls to `CheckForMisbehaviour`, `UpdateState`, and `UpdateStateOnMisbehaviour` will assume that the content of the `ClientMessage` has been verified and can be trusted. An error should be returned if the `ClientMessage` fails to verify.
+
+- `CheckForMisbehaviour` checks for evidence of a misbehaviour in `Header` or `Misbehaviour` types.
+
+- `UpdateStateOnMisbehaviour` performs appropriate state changes on a `ClientState` given that misbehaviour has been detected and verified.
+
+- `UpdateState` updates and stores as necessary any associated information for an IBC client, such as the `ClientState` and corresponding `ConsensusState`. An error is returned if `ClientMessage` is of type `Misbehaviour`. Upon successful update, a list containing the updated consensus state height is returned.
+
+The `CheckMisbehaviourAndUpdateState` function has been removed from `ClientState` interface. This functionality is now encapsulated by the usage of `VerifyClientMessage`, `CheckForMisbehaviour`, `UpdateStateOnMisbehaviour`.
+
+The function `GetTimestampAtHeight` has been added to the `ClientState` interface. It should return the timestamp for a consensus state associated with the provided height.
+
+### `Header` and `Misbehaviour`
+
+`exported.Header` and `exported.Misbehaviour` interface types have been merged and renamed to `ClientMessage` interface.
+
+`GetHeight` function has been removed from `exported.Header` and thus is not included in the `ClientMessage` interface
+
+### `ConsensusState`
+
+The `GetRoot` function has been removed from consensus state interface since it was not used by core IBC.
+
+### Light client implementations
+
+The `09-localhost` light client implementation has been removed because it is currently non-functional.
+
+An upgrade handler has been added to supply chain developers with the logic needed to prune the ibc client store and successfully complete the removal of `09-localhost`.
+Add the following to the application upgrade handler in `app/app.go`, calling `MigrateToV6` to perform store migration logic.
+
+```go
+import (
+ // ...
+ ibcv6 "github.com/cosmos/ibc-go/v6/modules/core/migrations/v6"
+)
+
+// ...
+
+app.UpgradeKeeper.SetUpgradeHandler(
+ upgradeName,
+ func(ctx sdk.Context, _ upgradetypes.Plan, _ module.VersionMap) (module.VersionMap, error) {
+ // prune the 09-localhost client from the ibc client store
+ ibcv6.MigrateToV6(ctx, app.IBCKeeper.ClientKeeper)
+
+ return app.mm.RunMigrations(ctx, app.configurator, fromVM)
+ },
+)
+```
+
+Please note the above upgrade handler is optional and should only be run if chains have an existing `09-localhost` client stored in state.
+A simple query can be performed to check for a `09-localhost` client on chain.
+
+For example:
+
+```
+simd query ibc client states | grep 09-localhost
+```
+
+### Client Keeper
+
+Keeper function `CheckMisbehaviourAndUpdateState` has been removed since function `UpdateClient` can now handle updating `ClientState` on `ClientMessage` type which can be any `Misbehaviour` implementations.
+
+### SDK Message
+
+`MsgSubmitMisbehaviour` is deprecated since `MsgUpdateClient` can now submit a `ClientMessage` type which can be any `Misbehaviour` implementations.
+
+The field `header` in `MsgUpdateClient` has been renamed to `client_message`.
diff --git a/modules/apps/27-interchain-accounts/host/keeper/relay_test.go b/modules/apps/27-interchain-accounts/host/keeper/relay_test.go
index 02d4ff07179..89058aad4e1 100644
--- a/modules/apps/27-interchain-accounts/host/keeper/relay_test.go
+++ b/modules/apps/27-interchain-accounts/host/keeper/relay_test.go
@@ -308,7 +308,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
Token: sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)),
Sender: interchainAccountAddr,
Receiver: suite.chainA.SenderAccount.GetAddress().String(),
- TimeoutHeight: clienttypes.NewHeight(0, 100),
+ TimeoutHeight: clienttypes.NewHeight(1, 100),
TimeoutTimestamp: uint64(0),
}
@@ -464,7 +464,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
path.EndpointA.ChannelID,
path.EndpointB.ChannelConfig.PortID,
path.EndpointB.ChannelID,
- clienttypes.NewHeight(0, 100),
+ clienttypes.NewHeight(1, 100),
0,
)
diff --git a/modules/apps/29-fee/ica_test.go b/modules/apps/29-fee/ica_test.go
index bcc8098d0dc..a1ab7ef6d03 100644
--- a/modules/apps/29-fee/ica_test.go
+++ b/modules/apps/29-fee/ica_test.go
@@ -189,7 +189,7 @@ func buildInterchainAccountsPacket(path *ibctesting.Path, data []byte, seq uint6
path.EndpointA.ChannelID,
path.EndpointB.ChannelConfig.PortID,
path.EndpointB.ChannelID,
- clienttypes.NewHeight(0, 100),
+ clienttypes.NewHeight(1, 100),
0,
)
diff --git a/modules/apps/29-fee/transfer_test.go b/modules/apps/29-fee/transfer_test.go
index 74d7089faf7..8aeb6ffeac0 100644
--- a/modules/apps/29-fee/transfer_test.go
+++ b/modules/apps/29-fee/transfer_test.go
@@ -30,7 +30,7 @@ func (suite *FeeTestSuite) TestFeeTransfer() {
msgs := []sdk.Msg{
types.NewMsgPayPacketFee(fee, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, suite.chainA.SenderAccount.GetAddress().String(), nil),
- transfertypes.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, coin, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(0, 100), 0),
+ transfertypes.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, coin, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(1, 100), 0),
}
res, err := suite.chainA.SendMsgs(msgs...)
suite.Require().NoError(err) // message committed
diff --git a/modules/apps/transfer/keeper/mbt_relay_test.go b/modules/apps/transfer/keeper/mbt_relay_test.go
index a09c4203e8f..6a4706f9f5a 100644
--- a/modules/apps/transfer/keeper/mbt_relay_test.go
+++ b/modules/apps/transfer/keeper/mbt_relay_test.go
@@ -313,7 +313,7 @@ func (suite *KeeperTestSuite) TestModelBasedRelay() {
description := file_info.Name() + " # " + strconv.Itoa(i+1)
suite.Run(fmt.Sprintf("Case %s", description), func() {
seq := uint64(1)
- packet := channeltypes.NewPacket(tc.packet.Data.GetBytes(), seq, tc.packet.SourcePort, tc.packet.SourceChannel, tc.packet.DestPort, tc.packet.DestChannel, clienttypes.NewHeight(0, 100), 0)
+ packet := channeltypes.NewPacket(tc.packet.Data.GetBytes(), seq, tc.packet.SourcePort, tc.packet.SourceChannel, tc.packet.DestPort, tc.packet.DestChannel, clienttypes.NewHeight(1, 100), 0)
bankBefore := BankFromBalances(tc.bankBefore)
realBankBefore := BankOfChain(suite.chainB)
// First validate the packet itself (mimics what happens when the packet is being sent and/or received)
@@ -345,7 +345,7 @@ func (suite *KeeperTestSuite) TestModelBasedRelay() {
sdk.NewCoin(denom, amount),
sender,
tc.packet.Data.Receiver,
- clienttypes.NewHeight(0, 110),
+ clienttypes.NewHeight(1, 110),
0)
}
case "OnRecvPacket":
diff --git a/modules/apps/transfer/keeper/relay_test.go b/modules/apps/transfer/keeper/relay_test.go
index 7cfb0cae2fc..1e57e3f2236 100644
--- a/modules/apps/transfer/keeper/relay_test.go
+++ b/modules/apps/transfer/keeper/relay_test.go
@@ -112,13 +112,13 @@ func (suite *KeeperTestSuite) TestSendTransfer() {
if !tc.sendFromSource {
// send coin from chainB to chainA
coinFromBToA := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))
- transferMsg := types.NewMsgTransfer(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinFromBToA, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), clienttypes.NewHeight(0, 110), 0)
+ transferMsg := types.NewMsgTransfer(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinFromBToA, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), clienttypes.NewHeight(1, 110), 0)
_, err = suite.chainB.SendMsgs(transferMsg)
suite.Require().NoError(err) // message committed
// receive coin on chainA from chainB
fungibleTokenPacket := types.NewFungibleTokenPacketData(coinFromBToA.Denom, coinFromBToA.Amount.String(), suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String())
- packet := channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, clienttypes.NewHeight(0, 110), 0)
+ packet := channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, clienttypes.NewHeight(1, 110), 0)
// get proof of packet commitment from chainB
err = path.EndpointA.UpdateClient()
@@ -133,7 +133,7 @@ func (suite *KeeperTestSuite) TestSendTransfer() {
err = suite.chainA.GetSimApp().TransferKeeper.SendTransfer(
suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, amount,
- suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(0, 110), 0,
+ suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(1, 110), 0,
)
if tc.expPass {
@@ -210,7 +210,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
if tc.recvIsSource {
// send coin from chainB to chainA, receive them, acknowledge them, and send back to chainB
coinFromBToA := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))
- transferMsg := types.NewMsgTransfer(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinFromBToA, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), clienttypes.NewHeight(0, 110), 0)
+ transferMsg := types.NewMsgTransfer(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinFromBToA, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), clienttypes.NewHeight(1, 110), 0)
res, err := suite.chainB.SendMsgs(transferMsg)
suite.Require().NoError(err) // message committed
@@ -229,14 +229,14 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
}
// send coin from chainA to chainB
- transferMsg := types.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, sdk.NewCoin(trace.IBCDenom(), amount), suite.chainA.SenderAccount.GetAddress().String(), receiver, clienttypes.NewHeight(0, 110), 0)
+ transferMsg := types.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, sdk.NewCoin(trace.IBCDenom(), amount), suite.chainA.SenderAccount.GetAddress().String(), receiver, clienttypes.NewHeight(1, 110), 0)
_, err := suite.chainA.SendMsgs(transferMsg)
suite.Require().NoError(err) // message committed
tc.malleate()
data := types.NewFungibleTokenPacketData(trace.GetFullDenomPath(), amount.String(), suite.chainA.SenderAccount.GetAddress().String(), receiver)
- packet := channeltypes.NewPacket(data.GetBytes(), seq, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(0, 100), 0)
+ packet := channeltypes.NewPacket(data.GetBytes(), seq, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(1, 100), 0)
err = suite.chainB.GetSimApp().TransferKeeper.OnRecvPacket(suite.chainB.GetContext(), packet, data)
@@ -309,7 +309,7 @@ func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() {
tc.malleate()
data := types.NewFungibleTokenPacketData(trace.GetFullDenomPath(), amount.String(), suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String())
- packet := channeltypes.NewPacket(data.GetBytes(), 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(0, 100), 0)
+ packet := channeltypes.NewPacket(data.GetBytes(), 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(1, 100), 0)
preCoin := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), trace.IBCDenom())
@@ -405,7 +405,7 @@ func (suite *KeeperTestSuite) TestOnTimeoutPacket() {
tc.malleate()
data := types.NewFungibleTokenPacketData(trace.GetFullDenomPath(), amount.String(), sender, suite.chainB.SenderAccount.GetAddress().String())
- packet := channeltypes.NewPacket(data.GetBytes(), 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(0, 100), 0)
+ packet := channeltypes.NewPacket(data.GetBytes(), 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(1, 100), 0)
preCoin := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), trace.IBCDenom())
diff --git a/modules/apps/transfer/transfer_test.go b/modules/apps/transfer/transfer_test.go
index 95aa0c4d4e3..b6a88f7e651 100644
--- a/modules/apps/transfer/transfer_test.go
+++ b/modules/apps/transfer/transfer_test.go
@@ -47,7 +47,7 @@ func (suite *TransferTestSuite) TestHandleMsgTransfer() {
suite.coordinator.Setup(path)
// originalBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), sdk.DefaultBondDenom)
- timeoutHeight := clienttypes.NewHeight(0, 110)
+ timeoutHeight := clienttypes.NewHeight(1, 110)
amount, ok := sdk.NewIntFromString("9223372036854775808") // 2^63 (one above int64)
suite.Require().True(ok)
diff --git a/modules/core/02-client/abci.go b/modules/core/02-client/abci.go
index 9fe681e2276..c4fcc91ec37 100644
--- a/modules/core/02-client/abci.go
+++ b/modules/core/02-client/abci.go
@@ -4,11 +4,10 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/ibc-go/v5/modules/core/02-client/keeper"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
)
-// BeginBlocker updates an existing localhost client with the latest block height.
+// BeginBlocker is used to perform IBC client upgrades
func BeginBlocker(ctx sdk.Context, k keeper.Keeper) {
plan, found := k.GetUpgradePlan(ctx)
if found {
@@ -20,7 +19,7 @@ func BeginBlocker(ctx sdk.Context, k keeper.Keeper) {
// within the trusting period of the last block time on this chain.
_, exists := k.GetUpgradedClient(ctx, plan.Height)
if exists && ctx.BlockHeight() == plan.Height-1 {
- upgradedConsState := &ibctmtypes.ConsensusState{
+ upgradedConsState := &ibctm.ConsensusState{
Timestamp: ctx.BlockTime(),
NextValidatorsHash: ctx.BlockHeader().NextValidatorsHash,
}
@@ -29,16 +28,7 @@ func BeginBlocker(ctx sdk.Context, k keeper.Keeper) {
// SetUpgradedConsensusState always returns nil, hence the blank here.
_ = k.SetUpgradedConsensusState(ctx, plan.Height, bz)
+ keeper.EmitUpgradeChainEvent(ctx, plan.Height)
}
}
-
- _, found = k.GetClientState(ctx, exported.Localhost)
- if !found {
- return
- }
-
- // update the localhost client with the latest block height
- if err := k.UpdateClient(ctx, exported.Localhost, nil); err != nil {
- panic(err)
- }
}
diff --git a/modules/core/02-client/abci_test.go b/modules/core/02-client/abci_test.go
index c3bbb187892..acdfd32f389 100644
--- a/modules/core/02-client/abci_test.go
+++ b/modules/core/02-client/abci_test.go
@@ -1,8 +1,10 @@
package client_test
import (
+ "strings"
"testing"
+ sdk "github.com/cosmos/cosmos-sdk/types"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
"github.com/stretchr/testify/suite"
abci "github.com/tendermint/tendermint/abci/types"
@@ -10,9 +12,7 @@ import (
client "github.com/cosmos/ibc-go/v5/modules/core/02-client"
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
- localhosttypes "github.com/cosmos/ibc-go/v5/modules/light-clients/09-localhost/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -30,13 +30,6 @@ func (suite *ClientTestSuite) SetupTest() {
suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(1))
suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(2))
-
- // set localhost client
- revision := types.ParseChainID(suite.chainA.GetContext().ChainID())
- localHostClient := localhosttypes.NewClientState(
- suite.chainA.GetContext().ChainID(), types.NewHeight(revision, uint64(suite.chainA.GetContext().BlockHeight())),
- )
- suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), exported.Localhost, localHostClient)
}
func TestClientTestSuite(t *testing.T) {
@@ -44,11 +37,6 @@ func TestClientTestSuite(t *testing.T) {
}
func (suite *ClientTestSuite) TestBeginBlocker() {
- prevHeight := types.GetSelfHeight(suite.chainA.GetContext())
-
- localHostClient := suite.chainA.GetClientState(exported.Localhost)
- suite.Require().Equal(prevHeight, localHostClient.GetLatestHeight())
-
for i := 0; i < 10; i++ {
// increment height
suite.coordinator.CommitBlock(suite.chainA, suite.chainB)
@@ -56,10 +44,6 @@ func (suite *ClientTestSuite) TestBeginBlocker() {
suite.Require().NotPanics(func() {
client.BeginBlocker(suite.chainA.GetContext(), suite.chainA.App.GetIBCKeeper().ClientKeeper)
}, "BeginBlocker shouldn't panic")
-
- localHostClient = suite.chainA.GetClientState(exported.Localhost)
- suite.Require().Equal(prevHeight.Increment(), localHostClient.GetLatestHeight())
- prevHeight = localHostClient.GetLatestHeight().(types.Height)
}
}
@@ -88,7 +72,59 @@ func (suite *ClientTestSuite) TestBeginBlockerConsensusState() {
// plan Height is at ctx.BlockHeight+1
consState, found := suite.chainA.GetSimApp().UpgradeKeeper.GetUpgradedConsensusState(newCtx, plan.Height)
suite.Require().True(found)
- bz, err = types.MarshalConsensusState(suite.chainA.App.AppCodec(), &ibctmtypes.ConsensusState{Timestamp: newCtx.BlockTime(), NextValidatorsHash: nextValsHash})
+ bz, err = types.MarshalConsensusState(suite.chainA.App.AppCodec(), &ibctm.ConsensusState{Timestamp: newCtx.BlockTime(), NextValidatorsHash: nextValsHash})
suite.Require().NoError(err)
suite.Require().Equal(bz, consState)
}
+
+func (suite *ClientTestSuite) TestBeginBlockerUpgradeEvents() {
+ plan := &upgradetypes.Plan{
+ Name: "test",
+ Height: suite.chainA.GetContext().BlockHeight() + 1,
+ }
+ // set upgrade plan in the upgrade store
+ store := suite.chainA.GetContext().KVStore(suite.chainA.GetSimApp().GetKey(upgradetypes.StoreKey))
+ bz := suite.chainA.App.AppCodec().MustMarshal(plan)
+ store.Set(upgradetypes.PlanKey(), bz)
+
+ nextValsHash := []byte("nextValsHash")
+ newCtx := suite.chainA.GetContext().WithBlockHeader(tmproto.Header{
+ Height: suite.chainA.GetContext().BlockHeight(),
+ NextValidatorsHash: nextValsHash,
+ })
+
+ err := suite.chainA.GetSimApp().UpgradeKeeper.SetUpgradedClient(newCtx, plan.Height, []byte("client state"))
+ suite.Require().NoError(err)
+
+ cacheCtx, writeCache := suite.chainA.GetContext().CacheContext()
+
+ client.BeginBlocker(cacheCtx, suite.chainA.App.GetIBCKeeper().ClientKeeper)
+ writeCache()
+
+ suite.requireContainsEvent(cacheCtx.EventManager().Events(), types.EventTypeUpgradeChain, true)
+}
+
+func (suite *ClientTestSuite) TestBeginBlockerUpgradeEventsAbsence() {
+ cacheCtx, writeCache := suite.chainA.GetContext().CacheContext()
+ client.BeginBlocker(suite.chainA.GetContext(), suite.chainA.App.GetIBCKeeper().ClientKeeper)
+ writeCache()
+ suite.requireContainsEvent(cacheCtx.EventManager().Events(), types.EventTypeUpgradeChain, false)
+}
+
+// requireContainsEvent verifies if an event of a specific type was emitted.
+func (suite *ClientTestSuite) requireContainsEvent(events sdk.Events, eventType string, shouldContain bool) {
+ found := false
+ var eventTypes []string
+ for _, e := range events {
+ eventTypes = append(eventTypes, e.Type)
+ if e.Type == eventType {
+ found = true
+ break
+ }
+ }
+ if shouldContain {
+ suite.Require().True(found, "event type %s was not found in %s", eventType, strings.Join(eventTypes, ","))
+ } else {
+ suite.Require().False(found, "event type %s was found in %s", eventType, strings.Join(eventTypes, ","))
+ }
+}
diff --git a/modules/core/02-client/client/cli/cli.go b/modules/core/02-client/client/cli/cli.go
index 57e9425f995..bdf42460573 100644
--- a/modules/core/02-client/client/cli/cli.go
+++ b/modules/core/02-client/client/cli/cli.go
@@ -45,7 +45,7 @@ func NewTxCmd() *cobra.Command {
txCmd.AddCommand(
NewCreateClientCmd(),
NewUpdateClientCmd(),
- NewSubmitMisbehaviourCmd(),
+ NewSubmitMisbehaviourCmd(), // Deprecated
NewUpgradeClientCmd(),
)
diff --git a/modules/core/02-client/client/cli/tx.go b/modules/core/02-client/client/cli/tx.go
index 71d50f90dae..794b6f5ca5e 100644
--- a/modules/core/02-client/client/cli/tx.go
+++ b/modules/core/02-client/client/cli/tx.go
@@ -86,10 +86,10 @@ func NewCreateClientCmd() *cobra.Command {
// NewUpdateClientCmd defines the command to update an IBC client.
func NewUpdateClientCmd() *cobra.Command {
return &cobra.Command{
- Use: "update [client-id] [path/to/header.json]",
- Short: "update existing client with a header",
- Long: "update existing client with a header",
- Example: fmt.Sprintf("%s tx ibc %s update [client-id] [path/to/header.json] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName),
+ Use: "update [client-id] [path/to/client_msg.json]",
+ Short: "update existing client with a client message",
+ Long: "update existing client with a client message, for example a header, misbehaviour or batch update",
+ Example: fmt.Sprintf("%s tx ibc %s update [client-id] [path/to/client_msg.json] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
@@ -100,22 +100,22 @@ func NewUpdateClientCmd() *cobra.Command {
cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry)
- var header exported.Header
- headerContentOrFileName := args[1]
- if err := cdc.UnmarshalInterfaceJSON([]byte(headerContentOrFileName), &header); err != nil {
+ var clientMsg exported.ClientMessage
+ clientMsgContentOrFileName := args[1]
+ if err := cdc.UnmarshalInterfaceJSON([]byte(clientMsgContentOrFileName), &clientMsg); err != nil {
// check for file path if JSON input is not provided
- contents, err := ioutil.ReadFile(headerContentOrFileName)
+ contents, err := ioutil.ReadFile(clientMsgContentOrFileName)
if err != nil {
return fmt.Errorf("neither JSON input nor path to .json file for header were provided: %w", err)
}
- if err := cdc.UnmarshalInterfaceJSON(contents, &header); err != nil {
+ if err := cdc.UnmarshalInterfaceJSON(contents, &clientMsg); err != nil {
return fmt.Errorf("error unmarshalling header file: %w", err)
}
}
- msg, err := types.NewMsgUpdateClient(clientID, header, clientCtx.GetFromAddress().String())
+ msg, err := types.NewMsgUpdateClient(clientID, clientMsg, clientCtx.GetFromAddress().String())
if err != nil {
return err
}
@@ -127,13 +127,15 @@ func NewUpdateClientCmd() *cobra.Command {
// NewSubmitMisbehaviourCmd defines the command to submit a misbehaviour to prevent
// future updates.
+// Deprecated: NewSubmitMisbehaviourCmd is deprecated and will be removed in a future release.
+// Please use NewUpdateClientCmd instead.
func NewSubmitMisbehaviourCmd() *cobra.Command {
return &cobra.Command{
- Use: "misbehaviour [path/to/misbehaviour.json]",
+ Use: "misbehaviour [clientID] [path/to/misbehaviour.json]",
Short: "submit a client misbehaviour",
Long: "submit a client misbehaviour to prevent future updates",
- Example: fmt.Sprintf("%s tx ibc %s misbehaviour [path/to/misbehaviour.json] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName),
- Args: cobra.ExactArgs(1),
+ Example: fmt.Sprintf("%s tx ibc %s misbehaviour [clientID] [path/to/misbehaviour.json] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName),
+ Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
@@ -141,8 +143,9 @@ func NewSubmitMisbehaviourCmd() *cobra.Command {
}
cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry)
- var misbehaviour exported.Misbehaviour
- misbehaviourContentOrFileName := args[0]
+ var misbehaviour exported.ClientMessage
+ clientID := args[0]
+ misbehaviourContentOrFileName := args[1]
if err := cdc.UnmarshalInterfaceJSON([]byte(misbehaviourContentOrFileName), &misbehaviour); err != nil {
// check for file path if JSON input is not provided
@@ -156,7 +159,7 @@ func NewSubmitMisbehaviourCmd() *cobra.Command {
}
}
- msg, err := types.NewMsgSubmitMisbehaviour(misbehaviour.GetClientID(), misbehaviour, clientCtx.GetFromAddress().String())
+ msg, err := types.NewMsgSubmitMisbehaviour(clientID, misbehaviour, clientCtx.GetFromAddress().String())
if err != nil {
return err
}
diff --git a/modules/core/02-client/client/utils/utils.go b/modules/core/02-client/client/utils/utils.go
index 6005e58ddce..61e49ae2b3a 100644
--- a/modules/core/02-client/client/utils/utils.go
+++ b/modules/core/02-client/client/utils/utils.go
@@ -13,7 +13,7 @@ import (
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
ibcclient "github.com/cosmos/ibc-go/v5/modules/core/client"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
)
// QueryClientState returns a client state. If prove is true, it performs an ABCI store query
@@ -119,15 +119,15 @@ func QueryConsensusStateABCI(
// QueryTendermintHeader takes a client context and returns the appropriate
// tendermint header
-func QueryTendermintHeader(clientCtx client.Context) (ibctmtypes.Header, int64, error) {
+func QueryTendermintHeader(clientCtx client.Context) (ibctm.Header, int64, error) {
node, err := clientCtx.GetNode()
if err != nil {
- return ibctmtypes.Header{}, 0, err
+ return ibctm.Header{}, 0, err
}
info, err := node.ABCIInfo(context.Background())
if err != nil {
- return ibctmtypes.Header{}, 0, err
+ return ibctm.Header{}, 0, err
}
var height int64
@@ -139,7 +139,7 @@ func QueryTendermintHeader(clientCtx client.Context) (ibctmtypes.Header, int64,
commit, err := node.Commit(context.Background(), &height)
if err != nil {
- return ibctmtypes.Header{}, 0, err
+ return ibctm.Header{}, 0, err
}
page := 1
@@ -147,16 +147,16 @@ func QueryTendermintHeader(clientCtx client.Context) (ibctmtypes.Header, int64,
validators, err := node.Validators(context.Background(), &height, &page, &count)
if err != nil {
- return ibctmtypes.Header{}, 0, err
+ return ibctm.Header{}, 0, err
}
protoCommit := commit.SignedHeader.ToProto()
protoValset, err := tmtypes.NewValidatorSet(validators.Validators).ToProto()
if err != nil {
- return ibctmtypes.Header{}, 0, err
+ return ibctm.Header{}, 0, err
}
- header := ibctmtypes.Header{
+ header := ibctm.Header{
SignedHeader: protoCommit,
ValidatorSet: protoValset,
}
@@ -166,15 +166,15 @@ func QueryTendermintHeader(clientCtx client.Context) (ibctmtypes.Header, int64,
// QuerySelfConsensusState takes a client context and returns the appropriate
// tendermint consensus state
-func QuerySelfConsensusState(clientCtx client.Context) (*ibctmtypes.ConsensusState, int64, error) {
+func QuerySelfConsensusState(clientCtx client.Context) (*ibctm.ConsensusState, int64, error) {
node, err := clientCtx.GetNode()
if err != nil {
- return &ibctmtypes.ConsensusState{}, 0, err
+ return &ibctm.ConsensusState{}, 0, err
}
info, err := node.ABCIInfo(context.Background())
if err != nil {
- return &ibctmtypes.ConsensusState{}, 0, err
+ return &ibctm.ConsensusState{}, 0, err
}
var height int64
@@ -186,7 +186,7 @@ func QuerySelfConsensusState(clientCtx client.Context) (*ibctmtypes.ConsensusSta
commit, err := node.Commit(context.Background(), &height)
if err != nil {
- return &ibctmtypes.ConsensusState{}, 0, err
+ return &ibctm.ConsensusState{}, 0, err
}
page := 1
@@ -195,10 +195,10 @@ func QuerySelfConsensusState(clientCtx client.Context) (*ibctmtypes.ConsensusSta
nextHeight := height + 1
nextVals, err := node.Validators(context.Background(), &nextHeight, &page, &count)
if err != nil {
- return &ibctmtypes.ConsensusState{}, 0, err
+ return &ibctm.ConsensusState{}, 0, err
}
- state := &ibctmtypes.ConsensusState{
+ state := &ibctm.ConsensusState{
Timestamp: commit.Time,
Root: commitmenttypes.NewMerkleRoot(commit.AppHash),
NextValidatorsHash: tmtypes.NewValidatorSet(nextVals.Validators).Hash(),
diff --git a/modules/core/02-client/genesis.go b/modules/core/02-client/genesis.go
index 602b13aba42..18dc745620d 100644
--- a/modules/core/02-client/genesis.go
+++ b/modules/core/02-client/genesis.go
@@ -46,14 +46,9 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, gs types.GenesisState) {
}
k.SetNextClientSequence(ctx, gs.NextClientSequence)
-
- // NOTE: localhost creation is specifically disallowed for the time being.
- // Issue: https://github.com/cosmos/cosmos-sdk/issues/7871
}
// ExportGenesis returns the ibc client submodule's exported genesis.
-// NOTE: CreateLocalhost should always be false on export since a
-// created localhost will be included in the exported clients.
func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState {
genClients := k.GetAllGenesisClients(ctx)
clientsMetadata, err := k.GetAllClientMetadata(ctx, genClients)
@@ -61,10 +56,11 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState {
panic(err)
}
return types.GenesisState{
- Clients: genClients,
- ClientsMetadata: clientsMetadata,
- ClientsConsensus: k.GetAllConsensusStates(ctx),
- Params: k.GetParams(ctx),
+ Clients: genClients,
+ ClientsMetadata: clientsMetadata,
+ ClientsConsensus: k.GetAllConsensusStates(ctx),
+ Params: k.GetParams(ctx),
+ // Warning: CreateLocalhost is deprecated
CreateLocalhost: false,
NextClientSequence: k.GetNextClientSequence(ctx),
}
diff --git a/modules/core/02-client/keeper/client.go b/modules/core/02-client/keeper/client.go
index fbfe2d0eab5..21ffba25e90 100644
--- a/modules/core/02-client/keeper/client.go
+++ b/modules/core/02-client/keeper/client.go
@@ -1,8 +1,6 @@
package keeper
import (
- "encoding/hex"
-
metrics "github.com/armon/go-metrics"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
@@ -27,7 +25,6 @@ func (k Keeper) CreateClient(
clientID := k.GenerateClientIdentifier(ctx, clientState.ClientType())
- k.SetClientState(ctx, clientID, clientState)
k.Logger(ctx).Info("client created at height", "client-id", clientID, "height", clientState.GetLatestHeight().String())
// verifies initial consensus state against client state and initializes client store with any client-specific metadata
@@ -36,20 +33,16 @@ func (k Keeper) CreateClient(
return "", err
}
- // check if consensus state is nil in case the created client is Localhost
- if consensusState != nil {
- k.SetClientConsensusState(ctx, clientID, clientState.GetLatestHeight(), consensusState)
- }
+ k.SetClientState(ctx, clientID, clientState)
+ k.SetClientConsensusState(ctx, clientID, clientState.GetLatestHeight(), consensusState)
k.Logger(ctx).Info("client created at height", "client-id", clientID, "height", clientState.GetLatestHeight().String())
- defer func() {
- telemetry.IncrCounterWithLabels(
- []string{"ibc", "client", "create"},
- 1,
- []metrics.Label{telemetry.NewLabel(types.LabelClientType, clientState.ClientType())},
- )
- }()
+ defer telemetry.IncrCounterWithLabels(
+ []string{"ibc", "client", "create"},
+ 1,
+ []metrics.Label{telemetry.NewLabel(types.LabelClientType, clientState.ClientType())},
+ )
EmitCreateClientEvent(ctx, clientID, clientState)
@@ -57,7 +50,7 @@ func (k Keeper) CreateClient(
}
// UpdateClient updates the consensus state and the state root from a provided header.
-func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.Header) error {
+func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) error {
clientState, found := k.GetClientState(ctx, clientID)
if !found {
return sdkerrors.Wrapf(types.ErrClientNotFound, "cannot update client with ID %s", clientID)
@@ -69,77 +62,48 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H
return sdkerrors.Wrapf(types.ErrClientNotActive, "cannot update client (%s) with status %s", clientID, status)
}
- // Any writes made in CheckHeaderAndUpdateState are persisted on both valid updates and misbehaviour updates.
- // Light client implementations are responsible for writing the correct metadata (if any) in either case.
- newClientState, newConsensusState, err := clientState.CheckHeaderAndUpdateState(ctx, k.cdc, clientStore, header)
- if err != nil {
- return sdkerrors.Wrapf(err, "cannot update client with ID %s", clientID)
+ if err := clientState.VerifyClientMessage(ctx, k.cdc, clientStore, clientMsg); err != nil {
+ return err
}
- // emit the full header in events
- var (
- headerStr string
- consensusHeight exported.Height
- )
- if header != nil {
- // Marshal the Header as an Any and encode the resulting bytes to hex.
- // This prevents the event value from containing invalid UTF-8 characters
- // which may cause data to be lost when JSON encoding/decoding.
- headerStr = hex.EncodeToString(types.MustMarshalHeader(k.cdc, header))
- // set default consensus height with header height
- consensusHeight = header.GetHeight()
+ foundMisbehaviour := clientState.CheckForMisbehaviour(ctx, k.cdc, clientStore, clientMsg)
+ if foundMisbehaviour {
+ clientState.UpdateStateOnMisbehaviour(ctx, k.cdc, clientStore, clientMsg)
- }
+ k.Logger(ctx).Info("client frozen due to misbehaviour", "client-id", clientID)
- // set new client state regardless of if update is valid update or misbehaviour
- k.SetClientState(ctx, clientID, newClientState)
- // If client state is not frozen after clientState CheckHeaderAndUpdateState,
- // then update was valid. Write the update state changes, and set new consensus state.
- // Else the update was proof of misbehaviour and we must emit appropriate misbehaviour events.
- if status := newClientState.Status(ctx, clientStore, k.cdc); status != exported.Frozen {
- // if update is not misbehaviour then update the consensus state
- // we don't set consensus state for localhost client
- if header != nil && clientID != exported.Localhost {
- k.SetClientConsensusState(ctx, clientID, header.GetHeight(), newConsensusState)
- } else {
- consensusHeight = types.GetSelfHeight(ctx)
- }
-
- k.Logger(ctx).Info("client state updated", "client-id", clientID, "height", consensusHeight.String())
-
- defer func() {
- telemetry.IncrCounterWithLabels(
- []string{"ibc", "client", "update"},
- 1,
- []metrics.Label{
- telemetry.NewLabel(types.LabelClientType, clientState.ClientType()),
- telemetry.NewLabel(types.LabelClientID, clientID),
- telemetry.NewLabel(types.LabelUpdateType, "msg"),
- },
- )
- }()
-
- // emitting events in the keeper emits for both begin block and handler client updates
- EmitUpdateClientEvent(ctx, clientID, newClientState, consensusHeight, headerStr)
- } else {
+ defer telemetry.IncrCounterWithLabels(
+ []string{"ibc", "client", "misbehaviour"},
+ 1,
+ []metrics.Label{
+ telemetry.NewLabel(types.LabelClientType, clientState.ClientType()),
+ telemetry.NewLabel(types.LabelClientID, clientID),
+ telemetry.NewLabel(types.LabelMsgType, "update"),
+ },
+ )
- k.Logger(ctx).Info("client frozen due to misbehaviour", "client-id", clientID)
+ EmitSubmitMisbehaviourEvent(ctx, clientID, clientState)
- defer func() {
- telemetry.IncrCounterWithLabels(
- []string{"ibc", "client", "misbehaviour"},
- 1,
- []metrics.Label{
- telemetry.NewLabel(types.LabelClientType, clientState.ClientType()),
- telemetry.NewLabel(types.LabelClientID, clientID),
- telemetry.NewLabel(types.LabelMsgType, "update"),
- },
- )
- }()
-
- EmitSubmitMisbehaviourEventOnUpdate(ctx, clientID, newClientState, consensusHeight, headerStr)
+ return nil
}
+ consensusHeights := clientState.UpdateState(ctx, k.cdc, clientStore, clientMsg)
+
+ k.Logger(ctx).Info("client state updated", "client-id", clientID, "heights", consensusHeights)
+
+ defer telemetry.IncrCounterWithLabels(
+ []string{"ibc", "client", "update"},
+ 1,
+ []metrics.Label{
+ telemetry.NewLabel(types.LabelClientType, clientState.ClientType()),
+ telemetry.NewLabel(types.LabelClientID, clientID),
+ telemetry.NewLabel(types.LabelUpdateType, "msg"),
+ },
+ )
+
+ // emitting events in the keeper emits for both begin block and handler client updates
+ EmitUpdateClientEvent(ctx, clientID, clientState.ClientType(), consensusHeights, k.cdc, clientMsg)
+
return nil
}
@@ -159,72 +123,24 @@ func (k Keeper) UpgradeClient(ctx sdk.Context, clientID string, upgradedClient e
return sdkerrors.Wrapf(types.ErrClientNotActive, "cannot upgrade client (%s) with status %s", clientID, status)
}
- updatedClientState, updatedConsState, err := clientState.VerifyUpgradeAndUpdateState(ctx, k.cdc, clientStore,
- upgradedClient, upgradedConsState, proofUpgradeClient, proofUpgradeConsState)
- if err != nil {
+ if err := clientState.VerifyUpgradeAndUpdateState(ctx, k.cdc, clientStore,
+ upgradedClient, upgradedConsState, proofUpgradeClient, proofUpgradeConsState,
+ ); err != nil {
return sdkerrors.Wrapf(err, "cannot upgrade client with ID %s", clientID)
}
- k.SetClientState(ctx, clientID, updatedClientState)
- k.SetClientConsensusState(ctx, clientID, updatedClientState.GetLatestHeight(), updatedConsState)
-
- k.Logger(ctx).Info("client state upgraded", "client-id", clientID, "height", updatedClientState.GetLatestHeight().String())
-
- defer func() {
- telemetry.IncrCounterWithLabels(
- []string{"ibc", "client", "upgrade"},
- 1,
- []metrics.Label{
- telemetry.NewLabel(types.LabelClientType, updatedClientState.ClientType()),
- telemetry.NewLabel(types.LabelClientID, clientID),
- },
- )
- }()
-
- // emitting events in the keeper emits for client upgrades
- EmitUpgradeClientEvent(ctx, clientID, updatedClientState)
-
- return nil
-}
-
-// CheckMisbehaviourAndUpdateState checks for client misbehaviour and freezes the
-// client if so.
-func (k Keeper) CheckMisbehaviourAndUpdateState(ctx sdk.Context, misbehaviour exported.Misbehaviour) error {
- clientState, found := k.GetClientState(ctx, misbehaviour.GetClientID())
- if !found {
- return sdkerrors.Wrapf(types.ErrClientNotFound, "cannot check misbehaviour for client with ID %s", misbehaviour.GetClientID())
- }
-
- 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)
- }
+ k.Logger(ctx).Info("client state upgraded", "client-id", clientID, "height", upgradedClient.GetLatestHeight().String())
- if err := misbehaviour.ValidateBasic(); err != nil {
- return err
- }
-
- clientState, err := clientState.CheckMisbehaviourAndUpdateState(ctx, k.cdc, clientStore, misbehaviour)
- if err != nil {
- return err
- }
-
- k.SetClientState(ctx, misbehaviour.GetClientID(), clientState)
- k.Logger(ctx).Info("client frozen due to misbehaviour", "client-id", misbehaviour.GetClientID())
-
- defer func() {
- telemetry.IncrCounterWithLabels(
- []string{"ibc", "client", "misbehaviour"},
- 1,
- []metrics.Label{
- telemetry.NewLabel(types.LabelClientType, misbehaviour.ClientType()),
- telemetry.NewLabel(types.LabelClientID, misbehaviour.GetClientID()),
- },
- )
- }()
+ defer telemetry.IncrCounterWithLabels(
+ []string{"ibc", "client", "upgrade"},
+ 1,
+ []metrics.Label{
+ telemetry.NewLabel(types.LabelClientType, upgradedClient.ClientType()),
+ telemetry.NewLabel(types.LabelClientID, clientID),
+ },
+ )
- EmitSubmitMisbehaviourEvent(ctx, misbehaviour.GetClientID(), clientState)
+ EmitUpgradeClientEvent(ctx, clientID, upgradedClient)
return nil
}
diff --git a/modules/core/02-client/keeper/client_test.go b/modules/core/02-client/keeper/client_test.go
index 09fd3078cc4..22b3c3556fd 100644
--- a/modules/core/02-client/keeper/client_test.go
+++ b/modules/core/02-client/keeper/client_test.go
@@ -6,16 +6,14 @@ import (
"time"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
- tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
- localhosttypes "github.com/cosmos/ibc-go/v5/modules/light-clients/09-localhost/types"
+ solomachinetypes "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
- ibctestingmock "github.com/cosmos/ibc-go/v5/testing/mock"
)
func (suite *KeeperTestSuite) TestCreateClient() {
@@ -24,8 +22,8 @@ func (suite *KeeperTestSuite) TestCreateClient() {
clientState exported.ClientState
expPass bool
}{
- {"success", ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), true},
- {"client type not supported", localhosttypes.NewClientState(testChainID, clienttypes.NewHeight(0, 1)), false},
+ {"success", ibctm.NewClientState(testChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), true},
+ {"client type not supported", solomachinetypes.NewClientState(0, &solomachinetypes.ConsensusState{suite.solomachine.ConsensusState().PublicKey, suite.solomachine.Diversifier, suite.solomachine.Time}, false), false},
}
for i, tc := range cases {
@@ -44,20 +42,20 @@ func (suite *KeeperTestSuite) TestCreateClient() {
func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
var (
path *ibctesting.Path
- updateHeader *ibctmtypes.Header
+ updateHeader *ibctm.Header
)
// Must create header creation functions since suite.header gets recreated on each test case
- createFutureUpdateFn := func(trustedHeight clienttypes.Height) *ibctmtypes.Header {
+ createFutureUpdateFn := func(trustedHeight clienttypes.Height) *ibctm.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 {
+ createPastUpdateFn := func(fillHeight, trustedHeight clienttypes.Height) *ibctm.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),
+ return suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(fillHeight.RevisionHeight), trustedHeight, consState.(*ibctm.ConsensusState).Timestamp.Add(time.Second*5),
suite.chainB.Vals, suite.chainB.Vals, suite.chainB.Vals, suite.chainB.Signers)
}
@@ -68,7 +66,7 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
expFreeze bool
}{
{"valid update", func() {
- clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+ clientState := path.EndpointA.GetClientState().(*ibctm.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
@@ -102,24 +100,24 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
{"valid duplicate update", func() {
clientID := path.EndpointA.ClientID
- height1 := types.NewHeight(0, 1)
+ height1 := types.NewHeight(1, 1)
// store previous consensus state
- prevConsState := &ibctmtypes.ConsensusState{
+ prevConsState := &ibctm.ConsensusState{
Timestamp: suite.past,
NextValidatorsHash: suite.chainB.Vals.Hash(),
}
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), clientID, height1, prevConsState)
- height5 := types.NewHeight(0, 5)
+ height5 := types.NewHeight(1, 5)
// store next consensus state to check that trustedHeight does not need to be hightest consensus state before header height
- nextConsState := &ibctmtypes.ConsensusState{
+ nextConsState := &ibctm.ConsensusState{
Timestamp: suite.past.Add(time.Minute),
NextValidatorsHash: suite.chainB.Vals.Hash(),
}
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), clientID, height5, nextConsState)
- height3 := types.NewHeight(0, 3)
+ height3 := types.NewHeight(1, 3)
// updateHeader will fill in consensus state between prevConsState and suite.consState
// clientState should not be updated
updateHeader = createPastUpdateFn(height3, height1)
@@ -129,23 +127,23 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
{"misbehaviour detection: conflicting header", func() {
clientID := path.EndpointA.ClientID
- height1 := types.NewHeight(0, 1)
+ height1 := types.NewHeight(1, 1)
// store previous consensus state
- prevConsState := &ibctmtypes.ConsensusState{
+ prevConsState := &ibctm.ConsensusState{
Timestamp: suite.past,
NextValidatorsHash: suite.chainB.Vals.Hash(),
}
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), clientID, height1, prevConsState)
- height5 := types.NewHeight(0, 5)
+ height5 := types.NewHeight(1, 5)
// store next consensus state to check that trustedHeight does not need to be hightest consensus state before header height
- nextConsState := &ibctmtypes.ConsensusState{
+ nextConsState := &ibctm.ConsensusState{
Timestamp: suite.past.Add(time.Minute),
NextValidatorsHash: suite.chainB.Vals.Hash(),
}
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), clientID, height5, nextConsState)
- height3 := types.NewHeight(0, 3)
+ height3 := types.NewHeight(1, 3)
// updateHeader will fill in consensus state between prevConsState and suite.consState
// clientState should not be updated
updateHeader = createPastUpdateFn(height3, height1)
@@ -155,21 +153,21 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), clientID, updateHeader.GetHeight(), conflictConsState)
}, true, true},
{"misbehaviour detection: monotonic time violation", func() {
- clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+ clientState := path.EndpointA.GetClientState().(*ibctm.ClientState)
clientID := path.EndpointA.ClientID
trustedHeight := clientState.GetLatestHeight().(types.Height)
// store intermediate consensus state at a time greater than updateHeader time
// this will break time monotonicity
incrementedClientHeight := clientState.GetLatestHeight().Increment().(types.Height)
- intermediateConsState := &ibctmtypes.ConsensusState{
+ intermediateConsState := &ibctm.ConsensusState{
Timestamp: suite.coordinator.CurrentTime.Add(2 * time.Hour),
NextValidatorsHash: suite.chainB.Vals.Hash(),
}
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), clientID, incrementedClientHeight, intermediateConsState)
// set iteration key
clientStore := suite.keeper.ClientStore(suite.ctx, clientID)
- ibctmtypes.SetIterationKey(clientStore, incrementedClientHeight)
+ ibctm.SetIterationKey(clientStore, incrementedClientHeight)
clientState.LatestHeight = incrementedClientHeight
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), clientID, clientState)
@@ -183,7 +181,7 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
}, false, false},
{"consensus state not found", func() {
clientState := path.EndpointA.GetClientState()
- tmClient, ok := clientState.(*ibctmtypes.ClientState)
+ tmClient, ok := clientState.(*ibctm.ClientState)
suite.Require().True(ok)
tmClient.LatestHeight = tmClient.LatestHeight.Increment().(types.Height)
@@ -191,8 +189,8 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
updateHeader = createFutureUpdateFn(clientState.GetLatestHeight().(types.Height))
}, false, false},
{"client is not active", func() {
- clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
- clientState.FrozenHeight = types.NewHeight(0, 1)
+ clientState := path.EndpointA.GetClientState().(*ibctm.ClientState)
+ clientState.FrozenHeight = types.NewHeight(1, 1)
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID, clientState)
updateHeader = createFutureUpdateFn(clientState.GetLatestHeight().(types.Height))
}, false, false},
@@ -224,9 +222,9 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
newClientState := path.EndpointA.GetClientState()
if tc.expFreeze {
- suite.Require().True(!newClientState.(*ibctmtypes.ClientState).FrozenHeight.IsZero(), "client did not freeze after conflicting header was submitted to UpdateClient")
+ suite.Require().True(!newClientState.(*ibctm.ClientState).FrozenHeight.IsZero(), "client did not freeze after conflicting header was submitted to UpdateClient")
} else {
- expConsensusState := &ibctmtypes.ConsensusState{
+ expConsensusState := &ibctm.ConsensusState{
Timestamp: updateHeader.GetTime(),
Root: commitmenttypes.NewMerkleRoot(updateHeader.Header.GetAppHash()),
NextValidatorsHash: updateHeader.Header.NextValidatorsHash,
@@ -254,19 +252,6 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
}
}
-func (suite *KeeperTestSuite) TestUpdateClientLocalhost() {
- revision := types.ParseChainID(suite.chainA.ChainID)
- var localhostClient exported.ClientState = localhosttypes.NewClientState(suite.chainA.ChainID, types.NewHeight(revision, uint64(suite.chainA.GetContext().BlockHeight())))
-
- ctx := suite.chainA.GetContext().WithBlockHeight(suite.chainA.GetContext().BlockHeight() + 1)
- err := suite.chainA.App.GetIBCKeeper().ClientKeeper.UpdateClient(ctx, exported.Localhost, nil)
- suite.Require().NoError(err)
-
- clientState, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientState(ctx, exported.Localhost)
- suite.Require().True(found)
- suite.Require().Equal(localhostClient.GetLatestHeight().(types.Height).Increment(), clientState.GetLatestHeight())
-}
-
func (suite *KeeperTestSuite) TestUpgradeClient() {
var (
path *ibctesting.Path
@@ -275,7 +260,6 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
lastHeight exported.Height
proofUpgradedClient, proofUpgradedConsState []byte
upgradedClientBz, upgradedConsStateBz []byte
- err error
)
testCases := []struct {
@@ -287,7 +271,7 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
name: "successful upgrade",
setup: func() {
// last Height is at next block
- lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
+ 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)
@@ -296,7 +280,6 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
suite.Require().NoError(err)
// commit upgrade store changes and update clients
-
suite.coordinator.CommitBlock(suite.chainB)
err = path.EndpointA.UpdateClient()
suite.Require().NoError(err)
@@ -313,7 +296,7 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
name: "client state not found",
setup: func() {
// last Height is at next block
- lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
+ 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)
@@ -343,7 +326,7 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
// client is frozen
// last Height is at next block
- lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
+ 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)
@@ -364,9 +347,9 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight())
// set frozen client in store
- tmClient, ok := cs.(*ibctmtypes.ClientState)
+ tmClient, ok := cs.(*ibctm.ClientState)
suite.Require().True(ok)
- tmClient.FrozenHeight = types.NewHeight(0, 1)
+ tmClient.FrozenHeight = types.NewHeight(1, 1)
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID, tmClient)
},
expPass: false,
@@ -375,7 +358,7 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
name: "tendermint client VerifyUpgrade fails",
setup: func() {
// last Height is at next block
- lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
+ 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)
@@ -384,7 +367,9 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
suite.Require().NoError(err)
// change upgradedClient client-specified parameters
- upgradedClient = ibctmtypes.NewClientState("wrongchainID", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, true, true)
+ tmClient := upgradedClient.(*ibctm.ClientState)
+ tmClient.ChainId = "wrongchainID"
+ upgradedClient = tmClient
suite.coordinator.CommitBlock(suite.chainB)
err = path.EndpointA.UpdateClient()
@@ -404,12 +389,19 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
tc := tc
path = ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupClients(path)
- upgradedClient = ibctmtypes.NewClientState("newChainId-1", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
+
+ clientState := path.EndpointA.GetClientState().(*ibctm.ClientState)
+ revisionNumber := clienttypes.ParseChainID(clientState.ChainId)
+
+ 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.GetLatestHeight().GetRevisionHeight()+1), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
upgradedClient = upgradedClient.ZeroCustomFields()
upgradedClientBz, err = types.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient)
suite.Require().NoError(err)
- upgradedConsState = &ibctmtypes.ConsensusState{
+ upgradedConsState = &ibctm.ConsensusState{
NextValidatorsHash: []byte("nextValsHash"),
}
upgradedConsStateBz, err = types.MarshalConsensusState(suite.chainA.App.AppCodec(), upgradedConsState)
@@ -417,9 +409,6 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
tc.setup()
- // Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient
- upgradedClient = upgradedClient.ZeroCustomFields()
-
err = suite.chainA.App.GetIBCKeeper().ClientKeeper.UpgradeClient(suite.chainA.GetContext(), path.EndpointA.ClientID, upgradedClient, upgradedConsState, proofUpgradedClient, proofUpgradedConsState)
if tc.expPass {
@@ -430,256 +419,10 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
}
}
-func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
- var (
- clientID string
- err error
- )
-
- altPrivVal := ibctestingmock.NewPV()
- altPubKey, err := altPrivVal.GetPubKey()
- suite.Require().NoError(err)
- altVal := tmtypes.NewValidator(altPubKey, 4)
-
- // Set valSet here with suite.valSet, so it doesn't get reset on each testcase
- valSet := suite.valSet
- valsHash := valSet.Hash()
-
- // Create bothValSet with both suite validator and altVal
- bothValSet := tmtypes.NewValidatorSet(append(suite.valSet.Validators, altVal))
- bothValsHash := bothValSet.Hash()
- // Create alternative validator set with only altVal
- altValSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{altVal})
-
- // Create signer array and ensure it is in same order as bothValSet
- _, suiteVal := suite.valSet.GetByIndex(0)
- bothSigners := make(map[string]tmtypes.PrivValidator, 2)
- bothSigners[suiteVal.Address.String()] = suite.privVal
- bothSigners[altVal.Address.String()] = altPrivVal
-
- altSigners := make(map[string]tmtypes.PrivValidator, 1)
- altSigners[altVal.Address.String()] = altPrivVal
-
- // Create valid Misbehaviour by making a duplicate header that signs over different block time
- altTime := suite.ctx.BlockTime().Add(time.Minute)
-
- heightPlus3 := types.NewHeight(0, height+3)
- heightPlus5 := types.NewHeight(0, height+5)
-
- testCases := []struct {
- name string
- misbehaviour *ibctmtypes.Misbehaviour
- malleate func() error
- expPass bool
- }{
- {
- "trusting period misbehavior should pass",
- &ibctmtypes.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+1), testClientHeight, altTime, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+1), testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: clientID,
- },
- func() error {
- suite.consensusState.NextValidatorsHash = bothValsHash
- 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)
-
- return err
- },
- true,
- },
- {
- "time misbehavior should pass",
- &ibctmtypes.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+5), testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+1), testClientHeight, altTime, bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: clientID,
- },
- func() error {
- suite.consensusState.NextValidatorsHash = bothValsHash
- 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)
-
- return err
- },
- true,
- },
- {
- "misbehavior at later height should pass",
- &ibctmtypes.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), testClientHeight, altTime, bothValSet, bothValSet, valSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, valSet, bothSigners),
- ClientId: clientID,
- },
- func() error {
- suite.consensusState.NextValidatorsHash = valsHash
- 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)
-
- // store intermediate consensus state to check that trustedHeight does not need to be highest consensus state before header height
- intermediateConsState := &ibctmtypes.ConsensusState{
- Timestamp: suite.now.Add(time.Minute),
- NextValidatorsHash: suite.chainB.Vals.Hash(),
- }
- suite.keeper.SetClientConsensusState(suite.ctx, clientID, heightPlus3, intermediateConsState)
-
- clientState.LatestHeight = heightPlus3
- suite.keeper.SetClientState(suite.ctx, clientID, clientState)
-
- return err
- },
- true,
- },
- {
- "misbehavior at later height with different trusted heights should pass",
- &ibctmtypes.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), testClientHeight, altTime, bothValSet, bothValSet, valSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), heightPlus3, suite.ctx.BlockTime(), bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: clientID,
- },
- func() error {
- suite.consensusState.NextValidatorsHash = valsHash
- 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)
-
- // store trusted consensus state for Header2
- intermediateConsState := &ibctmtypes.ConsensusState{
- Timestamp: suite.now.Add(time.Minute),
- NextValidatorsHash: bothValsHash,
- }
- suite.keeper.SetClientConsensusState(suite.ctx, clientID, heightPlus3, intermediateConsState)
-
- clientState.LatestHeight = heightPlus3
- suite.keeper.SetClientState(suite.ctx, clientID, clientState)
-
- return err
- },
- true,
- },
- {
- "misbehavior ValidateBasic fails: misbehaviour height is at same height as trusted height",
- &ibctmtypes.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight), testClientHeight, altTime, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight), testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: clientID,
- },
- func() error {
- suite.consensusState.NextValidatorsHash = bothValsHash
- 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)
-
- return err
- },
- false,
- },
- {
- "trusted ConsensusState1 not found",
- &ibctmtypes.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), heightPlus3, altTime, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, valSet, bothSigners),
- ClientId: clientID,
- },
- func() error {
- suite.consensusState.NextValidatorsHash = valsHash
- 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)
- // intermediate consensus state at height + 3 is not created
- return err
- },
- false,
- },
- {
- "trusted ConsensusState2 not found",
- &ibctmtypes.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), testClientHeight, altTime, bothValSet, bothValSet, valSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), heightPlus3, suite.ctx.BlockTime(), bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: clientID,
- },
- func() error {
- suite.consensusState.NextValidatorsHash = valsHash
- 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)
- // intermediate consensus state at height + 3 is not created
- return err
- },
- false,
- },
- {
- "client state not found",
- &ibctmtypes.Misbehaviour{},
- func() error { return nil },
- false,
- },
- {
- "client already is not active - client is frozen",
- &ibctmtypes.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+1), testClientHeight, altTime, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+1), testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: clientID,
- },
- func() error {
- suite.consensusState.NextValidatorsHash = bothValsHash
- 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)
-
- clientState.FrozenHeight = types.NewHeight(0, 1)
- suite.keeper.SetClientState(suite.ctx, clientID, clientState)
-
- return err
- },
- false,
- },
- {
- "misbehaviour check failed",
- &ibctmtypes.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+1), testClientHeight, altTime, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+1), testClientHeight, suite.ctx.BlockTime(), altValSet, altValSet, bothValSet, altSigners),
- ClientId: clientID,
- },
- func() error {
- clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
- if err != nil {
- return err
- }
- clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState)
-
- return err
- },
- false,
- },
- }
-
- for i, tc := range testCases {
- tc := tc
- i := i
-
- suite.Run(tc.name, func() {
- suite.SetupTest() // reset
- clientID = testClientID // must be explicitly changed
-
- err := tc.malleate()
- suite.Require().NoError(err)
-
- tc.misbehaviour.ClientId = clientID
-
- err = suite.keeper.CheckMisbehaviourAndUpdateState(suite.ctx, tc.misbehaviour)
-
- if tc.expPass {
- suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
-
- 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.(*ibctmtypes.ClientState).FrozenHeight.IsZero(), "valid test case %d failed: %s", i, tc.name)
- } else {
- suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
- }
- })
- }
-}
-
func (suite *KeeperTestSuite) TestUpdateClientEventEmission() {
path := ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupClients(path)
+
header, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, path.EndpointA.ClientID)
suite.Require().NoError(err)
@@ -703,7 +446,7 @@ func (suite *KeeperTestSuite) TestUpdateClientEventEmission() {
bz, err := hex.DecodeString(string(attr.Value))
suite.Require().NoError(err)
- emittedHeader, err := types.UnmarshalHeader(suite.chainA.App.AppCodec(), bz)
+ emittedHeader, err := types.UnmarshalClientMessage(suite.chainA.App.AppCodec(), bz)
suite.Require().NoError(err)
suite.Require().Equal(header, emittedHeader)
}
diff --git a/modules/core/02-client/keeper/events.go b/modules/core/02-client/keeper/events.go
index 2411ad307c4..98a212eefe3 100644
--- a/modules/core/02-client/keeper/events.go
+++ b/modules/core/02-client/keeper/events.go
@@ -1,9 +1,14 @@
package keeper
import (
+ "encoding/hex"
"fmt"
+ "strconv"
+ "strings"
+ "github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
+ upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
@@ -26,14 +31,32 @@ func EmitCreateClientEvent(ctx sdk.Context, clientID string, clientState exporte
}
// EmitUpdateClientEvent emits an update client event
-func EmitUpdateClientEvent(ctx sdk.Context, clientID string, clientState exported.ClientState, consensusHeight exported.Height, headerStr string) {
+func EmitUpdateClientEvent(ctx sdk.Context, clientID string, clientType string, consensusHeights []exported.Height, cdc codec.BinaryCodec, clientMsg exported.ClientMessage) {
+ // Marshal the ClientMessage as an Any and encode the resulting bytes to hex.
+ // This prevents the event value from containing invalid UTF-8 characters
+ // which may cause data to be lost when JSON encoding/decoding.
+ clientMsgStr := hex.EncodeToString(types.MustMarshalClientMessage(cdc, clientMsg))
+
+ var consensusHeightAttr string
+ if len(consensusHeights) != 0 {
+ consensusHeightAttr = consensusHeights[0].String()
+ }
+
+ consensusHeightsAttr := make([]string, len(consensusHeights))
+ for i, height := range consensusHeights {
+ consensusHeightsAttr[i] = height.String()
+ }
+
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeUpdateClient,
sdk.NewAttribute(types.AttributeKeyClientID, clientID),
- sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()),
- sdk.NewAttribute(types.AttributeKeyConsensusHeight, consensusHeight.String()),
- sdk.NewAttribute(types.AttributeKeyHeader, headerStr),
+ sdk.NewAttribute(types.AttributeKeyClientType, clientType),
+ // Deprecated: AttributeKeyConsensusHeight is deprecated and will be removed in a future release.
+ // Please use AttributeKeyConsensusHeights instead.
+ sdk.NewAttribute(types.AttributeKeyConsensusHeight, consensusHeightAttr),
+ sdk.NewAttribute(types.AttributeKeyConsensusHeights, strings.Join(consensusHeightsAttr, ",")),
+ sdk.NewAttribute(types.AttributeKeyHeader, clientMsgStr),
),
sdk.NewEvent(
sdk.EventTypeMessage,
@@ -59,13 +82,12 @@ func EmitUpgradeClientEvent(ctx sdk.Context, clientID string, clientState export
}
// EmitUpdateClientProposalEvent emits an update client proposal event
-func EmitUpdateClientProposalEvent(ctx sdk.Context, clientID string, clientState exported.ClientState) {
+func EmitUpdateClientProposalEvent(ctx sdk.Context, clientID, clientType string) {
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeUpdateClientProposal,
sdk.NewAttribute(types.AttributeKeySubjectClientID, clientID),
- sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()),
- sdk.NewAttribute(types.AttributeKeyConsensusHeight, clientState.GetLatestHeight().String()),
+ sdk.NewAttribute(types.AttributeKeyClientType, clientType),
),
)
}
@@ -92,15 +114,13 @@ func EmitSubmitMisbehaviourEvent(ctx sdk.Context, clientID string, clientState e
)
}
-// EmitSubmitMisbehaviourEventOnUpdate emits a client misbehaviour event on a client update event
-func EmitSubmitMisbehaviourEventOnUpdate(ctx sdk.Context, clientID string, clientState exported.ClientState, consensusHeight exported.Height, headerStr string) {
- ctx.EventManager().EmitEvent(
+// EmitUpgradeChainEvent emits an upgrade chain event.
+func EmitUpgradeChainEvent(ctx sdk.Context, height int64) {
+ ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
- types.EventTypeSubmitMisbehaviour,
- sdk.NewAttribute(types.AttributeKeyClientID, clientID),
- sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()),
- sdk.NewAttribute(types.AttributeKeyConsensusHeight, consensusHeight.String()),
- sdk.NewAttribute(types.AttributeKeyHeader, headerStr),
+ types.EventTypeUpgradeChain,
+ sdk.NewAttribute(types.AttributeKeyUpgradePlanHeight, strconv.FormatInt(height, 10)),
+ sdk.NewAttribute(types.AttributeKeyUpgradeStore, upgradetypes.StoreKey), // which store to query proof of consensus state from
),
- )
+ })
}
diff --git a/modules/core/02-client/keeper/grpc_query_test.go b/modules/core/02-client/keeper/grpc_query_test.go
index 0e8277aa971..e66badac616 100644
--- a/modules/core/02-client/keeper/grpc_query_test.go
+++ b/modules/core/02-client/keeper/grpc_query_test.go
@@ -11,7 +11,7 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -142,7 +142,7 @@ func (suite *KeeperTestSuite) TestQueryClientStates() {
idcs := types.NewIdentifiedClientState(path1.EndpointA.ClientID, clientStateA1)
idcs2 := types.NewIdentifiedClientState(path2.EndpointA.ClientID, clientStateA2)
- // order is sorted by client id, localhost is last
+ // order is sorted by client id
expClientStates = types.IdentifiedClientStates{idcs, idcs2}.Sort()
req = &types.QueryClientStatesRequest{
Pagination: &query.PageRequest{
@@ -158,13 +158,7 @@ func (suite *KeeperTestSuite) TestQueryClientStates() {
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
- expClientStates = nil
-
tc.malleate()
- // always add localhost which is created by default in init genesis
- localhostClientState := suite.chainA.GetClientState(exported.Localhost)
- identifiedLocalhost := types.NewIdentifiedClientState(exported.Localhost, localhostClientState)
- expClientStates = append(expClientStates, identifiedLocalhost)
ctx := sdk.WrapSDKContext(suite.chainA.GetContext())
@@ -534,7 +528,7 @@ func (suite *KeeperTestSuite) TestQueryClientStatus() {
func() {
path := ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupClients(path)
- clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+ clientState := path.EndpointA.GetClientState().(*ibctm.ClientState)
// increment latest height so no consensus state is stored
clientState.LatestHeight = clientState.LatestHeight.Increment().(types.Height)
@@ -551,7 +545,7 @@ func (suite *KeeperTestSuite) TestQueryClientStatus() {
func() {
path := ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupClients(path)
- clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+ clientState := path.EndpointA.GetClientState().(*ibctm.ClientState)
clientState.FrozenHeight = types.NewHeight(0, 1)
path.EndpointA.SetClientState(clientState)
diff --git a/modules/core/02-client/keeper/keeper.go b/modules/core/02-client/keeper/keeper.go
index 81ca1488ba7..33b6a39ac14 100644
--- a/modules/core/02-client/keeper/keeper.go
+++ b/modules/core/02-client/keeper/keeper.go
@@ -19,7 +19,7 @@ import (
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
)
// Keeper represents a type that grants read and write permissions to any client
@@ -257,7 +257,7 @@ func (k Keeper) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (
return nil, sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no historical info found at height %d", selfHeight.RevisionHeight)
}
- consensusState := &ibctmtypes.ConsensusState{
+ consensusState := &ibctm.ConsensusState{
Timestamp: histInfo.Header.Time,
Root: commitmenttypes.NewMerkleRoot(histInfo.Header.GetAppHash()),
NextValidatorsHash: histInfo.Header.NextValidatorsHash,
@@ -269,10 +269,10 @@ func (k Keeper) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (
// This function is only used to validate the client state the counterparty stores for this chain
// Client must be in same revision as the executing chain
func (k Keeper) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error {
- tmClient, ok := clientState.(*ibctmtypes.ClientState)
+ tmClient, ok := clientState.(*ibctm.ClientState)
if !ok {
return sdkerrors.Wrapf(types.ErrInvalidClient, "client must be a Tendermint client, expected: %T, got: %T",
- &ibctmtypes.ClientState{}, tmClient)
+ &ibctm.ClientState{}, tmClient)
}
if !tmClient.FrozenHeight.IsZero() {
diff --git a/modules/core/02-client/keeper/keeper_test.go b/modules/core/02-client/keeper/keeper_test.go
index 19694c9fa91..e38f7a0d430 100644
--- a/modules/core/02-client/keeper/keeper_test.go
+++ b/modules/core/02-client/keeper/keeper_test.go
@@ -19,8 +19,8 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
- localhosttypes "github.com/cosmos/ibc-go/v5/modules/light-clients/09-localhost/types"
+ solomachinetypes "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
ibctestingmock "github.com/cosmos/ibc-go/v5/testing/mock"
"github.com/cosmos/ibc-go/v5/testing/simapp"
@@ -44,7 +44,6 @@ const (
var (
testClientHeight = types.NewHeight(0, 5)
testClientHeightRevision1 = types.NewHeight(1, 5)
- newClientHeight = types.NewHeight(1, 1)
)
type KeeperTestSuite struct {
@@ -58,13 +57,14 @@ type KeeperTestSuite struct {
cdc codec.Codec
ctx sdk.Context
keeper *keeper.Keeper
- consensusState *ibctmtypes.ConsensusState
- header *ibctmtypes.Header
+ consensusState *ibctm.ConsensusState
+ header *ibctm.Header
valSet *tmtypes.ValidatorSet
valSetHash tmbytes.HexBytes
privVal tmtypes.PrivValidator
now time.Time
past time.Time
+ solomachine *ibctesting.Solomachine
signers map[string]tmtypes.PrivValidator
@@ -102,7 +102,7 @@ func (suite *KeeperTestSuite) SetupTest() {
suite.signers[validator.Address.String()] = suite.privVal
suite.header = suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight), testClientHeightMinus1, now2, suite.valSet, suite.valSet, suite.valSet, suite.signers)
- suite.consensusState = ibctmtypes.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot([]byte("hash")), suite.valSetHash)
+ suite.consensusState = ibctm.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot([]byte("hash")), suite.valSetHash)
var validators stakingtypes.Validators
for i := 1; i < 11; i++ {
@@ -122,12 +122,7 @@ func (suite *KeeperTestSuite) SetupTest() {
app.StakingKeeper.SetHistoricalInfo(suite.ctx, int64(i), &hi)
}
- // add localhost client
- revision := types.ParseChainID(suite.chainA.ChainID)
- localHostClient := localhosttypes.NewClientState(
- suite.chainA.ChainID, types.NewHeight(revision, uint64(suite.chainA.GetContext().BlockHeight())),
- )
- suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), exported.Localhost, localHostClient)
+ suite.solomachine = ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachinesingle", "testing", 1)
// TODO: deprecate
queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, app.InterfaceRegistry())
@@ -140,7 +135,7 @@ func TestKeeperTestSuite(t *testing.T) {
}
func (suite *KeeperTestSuite) TestSetClientState() {
- clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
+ clientState := ibctm.NewClientState(testChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
retrievedState, found := suite.keeper.GetClientState(suite.ctx, testClientID)
@@ -154,13 +149,14 @@ func (suite *KeeperTestSuite) TestSetClientConsensusState() {
retrievedConsState, found := suite.keeper.GetClientConsensusState(suite.ctx, testClientID, testClientHeight)
suite.Require().True(found, "GetConsensusState failed")
- tmConsState, ok := retrievedConsState.(*ibctmtypes.ConsensusState)
+ tmConsState, ok := retrievedConsState.(*ibctm.ConsensusState)
suite.Require().True(ok)
suite.Require().Equal(suite.consensusState, tmConsState, "ConsensusState not stored correctly")
}
func (suite *KeeperTestSuite) TestValidateSelfClient() {
- testClientHeight := types.NewHeight(0, uint64(suite.chainA.GetContext().BlockHeight()-1))
+ testClientHeight := types.GetSelfHeight(suite.chainA.GetContext())
+ testClientHeight.RevisionHeight--
testCases := []struct {
name string
@@ -169,62 +165,62 @@ func (suite *KeeperTestSuite) TestValidateSelfClient() {
}{
{
"success",
- ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
+ ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
true,
},
{
"success with nil UpgradePath",
- ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), nil, false, false),
+ ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), nil, false, false),
true,
},
- {
- "invalid client type",
- localhosttypes.NewClientState(suite.chainA.ChainID, testClientHeight),
- false,
- },
{
"frozen client",
- &ibctmtypes.ClientState{ChainId: suite.chainA.ChainID, TrustLevel: ibctmtypes.DefaultTrustLevel, TrustingPeriod: trustingPeriod, UnbondingPeriod: ubdPeriod, MaxClockDrift: maxClockDrift, FrozenHeight: testClientHeight, LatestHeight: testClientHeight, ProofSpecs: commitmenttypes.GetSDKSpecs(), UpgradePath: ibctesting.UpgradePath, AllowUpdateAfterExpiry: false, AllowUpdateAfterMisbehaviour: false},
+ &ibctm.ClientState{ChainId: suite.chainA.ChainID, TrustLevel: ibctm.DefaultTrustLevel, TrustingPeriod: trustingPeriod, UnbondingPeriod: ubdPeriod, MaxClockDrift: maxClockDrift, FrozenHeight: testClientHeight, LatestHeight: testClientHeight, ProofSpecs: commitmenttypes.GetSDKSpecs(), UpgradePath: ibctesting.UpgradePath, AllowUpdateAfterExpiry: false, AllowUpdateAfterMisbehaviour: false},
false,
},
{
"incorrect chainID",
- ibctmtypes.NewClientState("gaiatestnet", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
+ ibctm.NewClientState("gaiatestnet", ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
false,
},
{
"invalid client height",
- ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.NewHeight(0, uint64(suite.chainA.GetContext().BlockHeight())), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
+ ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.GetSelfHeight(suite.chainA.GetContext()).Increment().(types.Height), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
+ false,
+ },
+ {
+ "invalid client type",
+ solomachinetypes.NewClientState(0, &solomachinetypes.ConsensusState{suite.solomachine.ConsensusState().PublicKey, suite.solomachine.Diversifier, suite.solomachine.Time}, false),
false,
},
{
"invalid client revision",
- ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeightRevision1, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
+ ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeightRevision1, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
false,
},
{
"invalid proof specs",
- ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, nil, ibctesting.UpgradePath, false, false),
+ ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, nil, ibctesting.UpgradePath, false, false),
false,
},
{
"invalid trust level",
- ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
+ ibctm.NewClientState(suite.chainA.ChainID, ibctm.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
false,
},
{
"invalid unbonding period",
- ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+10, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
+ ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod+10, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
false,
},
{
"invalid trusting period",
- ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, ubdPeriod+10, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
+ ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, ubdPeriod+10, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
false,
},
{
"invalid upgrade path",
- ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), []string{"bad", "upgrade", "path"}, false, false),
+ ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), []string{"bad", "upgrade", "path"}, false, false),
false,
},
}
@@ -244,9 +240,9 @@ func (suite KeeperTestSuite) TestGetAllGenesisClients() {
testClientID2, testClientID3, testClientID,
}
expClients := []exported.ClientState{
- ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
+ ibctm.NewClientState(testChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
+ ibctm.NewClientState(testChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
+ ibctm.NewClientState(testChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
}
expGenClients := make(types.IdentifiedClientStates, len(expClients))
@@ -256,11 +252,6 @@ func (suite KeeperTestSuite) TestGetAllGenesisClients() {
expGenClients[i] = types.NewIdentifiedClientState(clientIDs[i], expClients[i])
}
- // add localhost client
- localHostClient, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), exported.Localhost)
- suite.Require().True(found)
- expGenClients = append(expGenClients, types.NewIdentifiedClientState(exported.Localhost, localHostClient))
-
genClients := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetAllGenesisClients(suite.chainA.GetContext())
suite.Require().Equal(expGenClients.Sort(), genClients)
@@ -271,23 +262,22 @@ func (suite KeeperTestSuite) TestGetAllGenesisMetadata() {
types.NewIdentifiedGenesisMetadata(
"07-tendermint-1",
[]types.GenesisMetadata{
- types.NewGenesisMetadata(ibctmtypes.ProcessedTimeKey(types.NewHeight(0, 1)), []byte("foo")),
- types.NewGenesisMetadata(ibctmtypes.ProcessedTimeKey(types.NewHeight(0, 2)), []byte("bar")),
- types.NewGenesisMetadata(ibctmtypes.ProcessedTimeKey(types.NewHeight(0, 3)), []byte("baz")),
+ types.NewGenesisMetadata(ibctm.ProcessedTimeKey(types.NewHeight(0, 1)), []byte("foo")),
+ types.NewGenesisMetadata(ibctm.ProcessedTimeKey(types.NewHeight(0, 2)), []byte("bar")),
+ types.NewGenesisMetadata(ibctm.ProcessedTimeKey(types.NewHeight(0, 3)), []byte("baz")),
},
),
types.NewIdentifiedGenesisMetadata(
"clientB",
[]types.GenesisMetadata{
- types.NewGenesisMetadata(ibctmtypes.ProcessedTimeKey(types.NewHeight(1, 100)), []byte("val1")),
- types.NewGenesisMetadata(ibctmtypes.ProcessedTimeKey(types.NewHeight(2, 300)), []byte("val2")),
+ types.NewGenesisMetadata(ibctm.ProcessedTimeKey(types.NewHeight(1, 100)), []byte("val1")),
+ types.NewGenesisMetadata(ibctm.ProcessedTimeKey(types.NewHeight(2, 300)), []byte("val2")),
},
),
}
genClients := []types.IdentifiedClientState{
- types.NewIdentifiedClientState("07-tendermint-1", &ibctmtypes.ClientState{}), types.NewIdentifiedClientState("clientB", &ibctmtypes.ClientState{}),
- types.NewIdentifiedClientState("clientC", &ibctmtypes.ClientState{}), types.NewIdentifiedClientState("clientD", &localhosttypes.ClientState{}),
+ types.NewIdentifiedClientState("07-tendermint-1", &ibctm.ClientState{}), types.NewIdentifiedClientState("clientB", &ibctm.ClientState{}),
}
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetAllClientMetadata(suite.chainA.GetContext(), expectedGenMetadata)
@@ -325,12 +315,12 @@ func (suite KeeperTestSuite) TestGetConsensusState() {
func (suite KeeperTestSuite) TestConsensusStateHelpers() {
// initial setup
- clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
+ clientState := ibctm.NewClientState(testChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight, suite.consensusState)
- nextState := ibctmtypes.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot([]byte("next")), suite.valSetHash)
+ nextState := ibctm.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot([]byte("next")), suite.valSetHash)
testClientHeightPlus5 := types.NewHeight(0, height+5)
diff --git a/modules/core/02-client/keeper/proposal.go b/modules/core/02-client/keeper/proposal.go
index 95e3544a277..aa0846021cc 100644
--- a/modules/core/02-client/keeper/proposal.go
+++ b/modules/core/02-client/keeper/proposal.go
@@ -13,16 +13,11 @@ import (
// ClientUpdateProposal will retrieve the subject and substitute client.
// A callback will occur to the subject client state with the client
// prefixed store being provided for both the subject and the substitute client.
-// The localhost client is not allowed to be modified with a proposal. The IBC
-// client implementations are responsible for validating the parameters of the
+// The IBC client implementations are responsible for validating the parameters of the
// subtitute (enusring they match the subject's parameters) as well as copying
// the necessary consensus states from the subtitute to the subject client
// store. The substitute must be Active and the subject must not be Active.
func (k Keeper) ClientUpdateProposal(ctx sdk.Context, p *types.ClientUpdateProposal) error {
- if p.SubjectClientId == exported.Localhost || p.SubstituteClientId == exported.Localhost {
- return sdkerrors.Wrap(types.ErrInvalidUpdateClientProposal, "cannot update localhost client with proposal")
- }
-
subjectClientState, found := k.GetClientState(ctx, p.SubjectClientId)
if !found {
return sdkerrors.Wrapf(types.ErrClientNotFound, "subject client with ID %s", p.SubjectClientId)
@@ -49,20 +44,18 @@ func (k Keeper) ClientUpdateProposal(ctx sdk.Context, p *types.ClientUpdatePropo
return sdkerrors.Wrapf(types.ErrClientNotActive, "substitute client is not Active, status is %s", status)
}
- clientState, err := subjectClientState.CheckSubstituteAndUpdateState(ctx, k.cdc, subjectClientStore, substituteClientStore, substituteClientState)
- if err != nil {
+ if err := subjectClientState.CheckSubstituteAndUpdateState(ctx, k.cdc, subjectClientStore, substituteClientStore, substituteClientState); err != nil {
return err
}
- k.SetClientState(ctx, p.SubjectClientId, clientState)
- k.Logger(ctx).Info("client updated after governance proposal passed", "client-id", p.SubjectClientId, "height", clientState.GetLatestHeight().String())
+ k.Logger(ctx).Info("client updated after governance proposal passed", "client-id", p.SubjectClientId)
defer func() {
telemetry.IncrCounterWithLabels(
[]string{"ibc", "client", "update"},
1,
[]metrics.Label{
- telemetry.NewLabel(types.LabelClientType, clientState.ClientType()),
+ telemetry.NewLabel(types.LabelClientType, substituteClientState.ClientType()),
telemetry.NewLabel(types.LabelClientID, p.SubjectClientId),
telemetry.NewLabel(types.LabelUpdateType, "proposal"),
},
@@ -70,7 +63,7 @@ func (k Keeper) ClientUpdateProposal(ctx sdk.Context, p *types.ClientUpdatePropo
}()
// emitting events in the keeper for proposal updates to clients
- EmitUpdateClientProposalEvent(ctx, p.SubjectClientId, clientState)
+ EmitUpdateClientProposalEvent(ctx, p.SubjectClientId, substituteClientState.ClientType())
return nil
}
diff --git a/modules/core/02-client/keeper/proposal_test.go b/modules/core/02-client/keeper/proposal_test.go
index 6123666a7ab..762d41a41ec 100644
--- a/modules/core/02-client/keeper/proposal_test.go
+++ b/modules/core/02-client/keeper/proposal_test.go
@@ -6,7 +6,7 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -30,7 +30,7 @@ func (suite *KeeperTestSuite) TestClientUpdateProposal() {
},
{
"subject and substitute use different revision numbers", func() {
- tmClientState, ok := substituteClientState.(*ibctmtypes.ClientState)
+ tmClientState, ok := substituteClientState.(*ibctm.ClientState)
suite.Require().True(ok)
consState, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientConsensusState(suite.chainA.GetContext(), substitute, tmClientState.LatestHeight)
suite.Require().True(found)
@@ -40,23 +40,13 @@ func (suite *KeeperTestSuite) TestClientUpdateProposal() {
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), substitute, tmClientState.LatestHeight, consState)
clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), substitute)
- ibctmtypes.SetProcessedTime(clientStore, tmClientState.LatestHeight, 100)
- ibctmtypes.SetProcessedHeight(clientStore, tmClientState.LatestHeight, types.NewHeight(0, 1))
+ ibctm.SetProcessedTime(clientStore, tmClientState.LatestHeight, 100)
+ ibctm.SetProcessedHeight(clientStore, tmClientState.LatestHeight, types.NewHeight(0, 1))
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), substitute, tmClientState)
content = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute)
}, true,
},
- {
- "cannot use localhost as subject", func() {
- content = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, exported.Localhost, substitute)
- }, false,
- },
- {
- "cannot use localhost as substitute", func() {
- content = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, exported.Localhost)
- }, false,
- },
{
"cannot use solomachine as substitute for tendermint client", func() {
solomachine := ibctesting.NewSolomachine(suite.T(), suite.cdc, "solo machine", "", 1)
@@ -78,7 +68,7 @@ func (suite *KeeperTestSuite) TestClientUpdateProposal() {
},
{
"subject and substitute have equal latest height", func() {
- tmClientState, ok := subjectClientState.(*ibctmtypes.ClientState)
+ tmClientState, ok := subjectClientState.(*ibctm.ClientState)
suite.Require().True(ok)
tmClientState.LatestHeight = substituteClientState.GetLatestHeight().(types.Height)
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), subject, tmClientState)
@@ -88,7 +78,7 @@ func (suite *KeeperTestSuite) TestClientUpdateProposal() {
},
{
"update fails, client is not frozen or expired", func() {
- tmClientState, ok := subjectClientState.(*ibctmtypes.ClientState)
+ tmClientState, ok := subjectClientState.(*ibctm.ClientState)
suite.Require().True(ok)
tmClientState.FrozenHeight = types.ZeroHeight()
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), subject, tmClientState)
@@ -98,7 +88,7 @@ func (suite *KeeperTestSuite) TestClientUpdateProposal() {
},
{
"substitute is frozen", func() {
- tmClientState, ok := substituteClientState.(*ibctmtypes.ClientState)
+ tmClientState, ok := substituteClientState.(*ibctm.ClientState)
suite.Require().True(ok)
tmClientState.FrozenHeight = types.NewHeight(0, 1)
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), substitute, tmClientState)
@@ -128,14 +118,14 @@ func (suite *KeeperTestSuite) TestClientUpdateProposal() {
substitutePath.EndpointA.UpdateClient()
substituteClientState = suite.chainA.GetClientState(substitute)
- tmClientState, ok := subjectClientState.(*ibctmtypes.ClientState)
+ 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.(*ibctmtypes.ClientState)
+ tmClientState, ok = substituteClientState.(*ibctm.ClientState)
suite.Require().True(ok)
tmClientState.AllowUpdateAfterMisbehaviour = true
tmClientState.AllowUpdateAfterExpiry = true
@@ -158,7 +148,7 @@ func (suite *KeeperTestSuite) TestClientUpdateProposal() {
func (suite *KeeperTestSuite) TestHandleUpgradeProposal() {
var (
- upgradedClientState *ibctmtypes.ClientState
+ upgradedClientState *ibctm.ClientState
oldPlan, plan upgradetypes.Plan
content govtypes.Content
err error
@@ -188,7 +178,7 @@ func (suite *KeeperTestSuite) TestHandleUpgradeProposal() {
},
{
"cannot unpack client state", func() {
- any, err := types.PackConsensusState(&ibctmtypes.ConsensusState{})
+ any, err := types.PackConsensusState(&ibctm.ConsensusState{})
suite.Require().NoError(err)
content = &types.UpgradeProposal{
Title: ibctesting.Title,
@@ -209,7 +199,7 @@ func (suite *KeeperTestSuite) TestHandleUpgradeProposal() {
path := ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupClients(path)
- upgradedClientState = suite.chainA.GetClientState(path.EndpointA.ClientID).ZeroCustomFields().(*ibctmtypes.ClientState)
+ upgradedClientState = suite.chainA.GetClientState(path.EndpointA.ClientID).ZeroCustomFields().(*ibctm.ClientState)
// use height 1000 to distinguish from old plan
plan = upgradetypes.Plan{
diff --git a/modules/core/02-client/legacy/v100/genesis.go b/modules/core/02-client/legacy/v100/genesis.go
index 9442b59b2a4..3a4018ff621 100644
--- a/modules/core/02-client/legacy/v100/genesis.go
+++ b/modules/core/02-client/legacy/v100/genesis.go
@@ -10,7 +10,7 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
)
// MigrateGenesis accepts exported v1.0.0 IBC client genesis file and migrates it to:
@@ -67,7 +67,7 @@ func MigrateGenesis(cdc codec.BinaryCodec, clientGenState *types.GenesisState, g
case exported.Tendermint:
// only add non expired consensus states to new clientsConsensus
- tmClientState, ok := client.ClientState.GetCachedValue().(*ibctmtypes.ClientState)
+ tmClientState, ok := client.ClientState.GetCachedValue().(*ibctm.ClientState)
if !ok {
return nil, types.ErrInvalidClient
}
@@ -75,7 +75,7 @@ func MigrateGenesis(cdc codec.BinaryCodec, clientGenState *types.GenesisState, g
// collect unexpired consensus states
var unexpiredConsensusStates []types.ConsensusStateWithHeight
for _, consState := range clientConsensusStates.ConsensusStates {
- tmConsState := consState.ConsensusState.GetCachedValue().(*ibctmtypes.ConsensusState)
+ tmConsState := consState.ConsensusState.GetCachedValue().(*ibctm.ConsensusState)
if !tmClientState.IsExpired(tmConsState.Timestamp, genesisBlockTime) {
unexpiredConsensusStates = append(unexpiredConsensusStates, consState)
}
@@ -109,18 +109,18 @@ func MigrateGenesis(cdc codec.BinaryCodec, clientGenState *types.GenesisState, g
// the previous version of IBC only contained the processed time metadata
// if we find the processed time metadata for an unexpired height, add the
// iteration key and processed height keys.
- if bytes.Equal(metadata.Key, ibctmtypes.ProcessedTimeKey(height)) {
+ if bytes.Equal(metadata.Key, ibctm.ProcessedTimeKey(height)) {
clientMetadata = append(clientMetadata,
// set the processed height using the current self height
// this is safe, it may cause delays in packet processing if there
// is a non zero connection delay time
types.GenesisMetadata{
- Key: ibctmtypes.ProcessedHeightKey(height),
+ Key: ibctm.ProcessedHeightKey(height),
Value: []byte(selfHeight.String()),
},
metadata, // processed time
types.GenesisMetadata{
- Key: ibctmtypes.IterationKey(height),
+ Key: ibctm.IterationKey(height),
Value: host.ConsensusStateKey(height),
})
}
diff --git a/modules/core/02-client/legacy/v100/genesis_test.go b/modules/core/02-client/legacy/v100/genesis_test.go
index 7235b984261..953643e4ecc 100644
--- a/modules/core/02-client/legacy/v100/genesis_test.go
+++ b/modules/core/02-client/legacy/v100/genesis_test.go
@@ -14,7 +14,7 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
"github.com/cosmos/ibc-go/v5/testing/simapp"
)
@@ -134,7 +134,7 @@ func (suite *LegacyTestSuite) TestMigrateGenesisSolomachine() {
var updatedMetadata []types.GenesisMetadata
var iterationKeys []types.GenesisMetadata
for _, metadata := range clientMetadata.ClientMetadata {
- if bytes.HasPrefix(metadata.Key, []byte(ibctmtypes.KeyIterateConsensusStatePrefix)) {
+ if bytes.HasPrefix(metadata.Key, []byte(ibctm.KeyIterateConsensusStatePrefix)) {
iterationKeys = append(iterationKeys, metadata)
} else {
updatedMetadata = append(updatedMetadata, metadata)
@@ -233,7 +233,7 @@ func (suite *LegacyTestSuite) TestMigrateGenesisTendermint() {
var updatedMetadata []types.GenesisMetadata
var iterationKeys []types.GenesisMetadata
for _, metadata := range clientMetadata.ClientMetadata {
- if bytes.HasPrefix(metadata.Key, []byte(ibctmtypes.KeyIterateConsensusStatePrefix)) {
+ if bytes.HasPrefix(metadata.Key, []byte(ibctm.KeyIterateConsensusStatePrefix)) {
iterationKeys = append(iterationKeys, metadata)
} else {
updatedMetadata = append(updatedMetadata, metadata)
@@ -258,9 +258,9 @@ func (suite *LegacyTestSuite) TestMigrateGenesisTendermint() {
for _, client := range migrated.ClientsMetadata {
if client.ClientId == path1.EndpointA.ClientID {
for _, metadata := range client.ClientMetadata {
- suite.Require().NotEqual(ibctmtypes.ProcessedTimeKey(height), metadata.Key)
- suite.Require().NotEqual(ibctmtypes.ProcessedHeightKey(height), metadata.Key)
- suite.Require().NotEqual(ibctmtypes.IterationKey(height), metadata.Key)
+ suite.Require().NotEqual(ibctm.ProcessedTimeKey(height), metadata.Key)
+ suite.Require().NotEqual(ibctm.ProcessedHeightKey(height), metadata.Key)
+ suite.Require().NotEqual(ibctm.IterationKey(height), metadata.Key)
}
}
}
@@ -278,9 +278,9 @@ func (suite *LegacyTestSuite) TestMigrateGenesisTendermint() {
for _, client := range migrated.ClientsMetadata {
if client.ClientId == path2.EndpointA.ClientID {
for _, metadata := range client.ClientMetadata {
- suite.Require().NotEqual(ibctmtypes.ProcessedTimeKey(height), metadata.Key)
- suite.Require().NotEqual(ibctmtypes.ProcessedHeightKey(height), metadata.Key)
- suite.Require().NotEqual(ibctmtypes.IterationKey(height), metadata.Key)
+ suite.Require().NotEqual(ibctm.ProcessedTimeKey(height), metadata.Key)
+ suite.Require().NotEqual(ibctm.ProcessedHeightKey(height), metadata.Key)
+ suite.Require().NotEqual(ibctm.IterationKey(height), metadata.Key)
}
}
}
diff --git a/modules/core/02-client/legacy/v100/solomachine.go b/modules/core/02-client/legacy/v100/solomachine.go
index e9121760e5b..d16dad0bfbb 100644
--- a/modules/core/02-client/legacy/v100/solomachine.go
+++ b/modules/core/02-client/legacy/v100/solomachine.go
@@ -88,16 +88,40 @@ func (cs ClientState) ExportMetadata(_ sdk.KVStore) []exported.GenesisMetadata {
panic("legacy solo machine is deprecated!")
}
+// CheckForMisbehaviour panics!
+func (cs ClientState) CheckForMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, msg exported.ClientMessage) bool {
+ panic("legacy solo machine is deprecated!")
+}
+
+// UpdateStateOnMisbehaviour panics!
+func (cs *ClientState) UpdateStateOnMisbehaviour(
+ _ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore, _ exported.ClientMessage,
+) {
+ panic("legacy solo machine is deprecated!")
+}
+
+// VerifyClientMessage panics!
+func (cs *ClientState) VerifyClientMessage(
+ _ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore, _ exported.ClientMessage,
+) error {
+ panic("legacy solo machine is deprecated!")
+}
+
+// UpdateState panis!
+func (cs *ClientState) UpdateState(_ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore, _ exported.ClientMessage) []exported.Height {
+ panic("legacy solo machine is deprecated!")
+}
+
// CheckHeaderAndUpdateState panics!
func (cs *ClientState) CheckHeaderAndUpdateState(
- _ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore, _ exported.Header,
+ _ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore, _ exported.ClientMessage,
) (exported.ClientState, exported.ConsensusState, error) {
panic("legacy solo machine is deprecated!")
}
// CheckMisbehaviourAndUpdateState panics!
func (cs ClientState) CheckMisbehaviourAndUpdateState(
- _ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore, _ exported.Misbehaviour,
+ _ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore, _ exported.ClientMessage,
) (exported.ClientState, error) {
panic("legacy solo machine is deprecated!")
}
@@ -106,7 +130,7 @@ func (cs ClientState) CheckMisbehaviourAndUpdateState(
func (cs ClientState) CheckSubstituteAndUpdateState(
ctx sdk.Context, _ codec.BinaryCodec, _, _ sdk.KVStore,
_ exported.ClientState,
-) (exported.ClientState, error) {
+) error {
panic("legacy solo machine is deprecated!")
}
@@ -114,7 +138,7 @@ func (cs ClientState) CheckSubstituteAndUpdateState(
func (cs ClientState) VerifyUpgradeAndUpdateState(
_ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore,
_ exported.ClientState, _ exported.ConsensusState, _, _ []byte,
-) (exported.ClientState, exported.ConsensusState, error) {
+) error {
panic("legacy solo machine is deprecated!")
}
@@ -187,6 +211,42 @@ func (cs ClientState) VerifyNextSequenceRecv(
panic("legacy solo machine is deprecated!")
}
+// GetTimestampAtHeight panics!
+func (cs ClientState) GetTimestampAtHeight(
+ sdk.Context, sdk.KVStore, codec.BinaryCodec, exported.Height,
+) (uint64, error) {
+ panic("legacy solo machine is deprecated!")
+}
+
+// VerifyMembership panics!
+func (cs *ClientState) VerifyMembership(
+ ctx sdk.Context,
+ clientStore sdk.KVStore,
+ cdc codec.BinaryCodec,
+ height exported.Height,
+ delayTimePeriod uint64,
+ delayBlockPeriod uint64,
+ proof []byte,
+ path []byte,
+ value []byte,
+) error {
+ panic("legacy solo machine is deprecated!")
+}
+
+// VerifyNonMembership panics!
+func (cs *ClientState) VerifyNonMembership(
+ ctx sdk.Context,
+ clientStore sdk.KVStore,
+ cdc codec.BinaryCodec,
+ height exported.Height,
+ delayTimePeriod uint64,
+ delayBlockPeriod uint64,
+ proof []byte,
+ path []byte,
+) error {
+ panic("legacy solo machine is deprecated")
+}
+
// ClientType panics!
func (ConsensusState) ClientType() string {
panic("legacy solo machine is deprecated!")
@@ -197,11 +257,6 @@ func (cs ConsensusState) GetTimestamp() uint64 {
panic("legacy solo machine is deprecated!")
}
-// GetRoot panics!
-func (cs ConsensusState) GetRoot() exported.Root {
- panic("legacy solo machine is deprecated!")
-}
-
// ValidateBasic panics!
func (cs ConsensusState) ValidateBasic() error {
panic("legacy solo machine is deprecated!")
diff --git a/modules/core/02-client/legacy/v100/store.go b/modules/core/02-client/legacy/v100/store.go
index f20b24ba2a1..e83b116c956 100644
--- a/modules/core/02-client/legacy/v100/store.go
+++ b/modules/core/02-client/legacy/v100/store.go
@@ -14,8 +14,8 @@ import (
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- smtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ smtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
)
// MigrateStore performs in-place store migrations from SDK v0.40 of the IBC module to v1.0.0 of ibc-go.
@@ -88,7 +88,7 @@ func MigrateStore(ctx sdk.Context, storeKey storetypes.StoreKey, cdc codec.Binar
return sdkerrors.Wrap(err, "failed to unmarshal client state bytes into tendermint client state")
}
- tmClientState, ok := clientState.(*ibctmtypes.ClientState)
+ tmClientState, ok := clientState.(*ibctm.ClientState)
if !ok {
return sdkerrors.Wrap(clienttypes.ErrInvalidClient, "client state is not tendermint even though client id contains 07-tendermint")
}
@@ -96,10 +96,7 @@ func MigrateStore(ctx sdk.Context, storeKey storetypes.StoreKey, cdc codec.Binar
// add iteration keys so pruning will be successful
addConsensusMetadata(ctx, clientStore)
- if err = ibctmtypes.PruneAllExpiredConsensusStates(ctx, clientStore, cdc, tmClientState); err != nil {
- return err
- }
-
+ ibctm.PruneAllExpiredConsensusStates(ctx, clientStore, cdc, tmClientState)
default:
continue
}
@@ -170,7 +167,7 @@ func addConsensusMetadata(ctx sdk.Context, clientStore sdk.KVStore) {
for _, height := range heights {
// set the iteration key and processed height
// these keys were not included in the SDK v0.42.0 release
- ibctmtypes.SetProcessedHeight(clientStore, height, clienttypes.GetSelfHeight(ctx))
- ibctmtypes.SetIterationKey(clientStore, height)
+ ibctm.SetProcessedHeight(clientStore, height, clienttypes.GetSelfHeight(ctx))
+ ibctm.SetIterationKey(clientStore, height)
}
}
diff --git a/modules/core/02-client/legacy/v100/store_test.go b/modules/core/02-client/legacy/v100/store_test.go
index 4cebf0a53cb..69c431fe15f 100644
--- a/modules/core/02-client/legacy/v100/store_test.go
+++ b/modules/core/02-client/legacy/v100/store_test.go
@@ -10,7 +10,7 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -146,15 +146,15 @@ func (suite *LegacyTestSuite) TestMigrateStoreTendermint() {
ctx := path.EndpointA.Chain.GetContext()
clientStore := path.EndpointA.Chain.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, path.EndpointA.ClientID)
- processedTime, ok := ibctmtypes.GetProcessedTime(clientStore, pruneHeight)
+ processedTime, ok := ibctm.GetProcessedTime(clientStore, pruneHeight)
suite.Require().True(ok)
suite.Require().NotNil(processedTime)
- processedHeight, ok := ibctmtypes.GetProcessedHeight(clientStore, pruneHeight)
+ processedHeight, ok := ibctm.GetProcessedHeight(clientStore, pruneHeight)
suite.Require().True(ok)
suite.Require().NotNil(processedHeight)
- expectedConsKey := ibctmtypes.GetIterationKey(clientStore, pruneHeight)
+ expectedConsKey := ibctm.GetIterationKey(clientStore, pruneHeight)
suite.Require().NotNil(expectedConsKey)
}
pruneHeightMap[path] = pruneHeights
@@ -174,8 +174,8 @@ func (suite *LegacyTestSuite) TestMigrateStoreTendermint() {
// remove processed height and iteration keys since these were missing from previous version of ibc module
clientStore := path.EndpointA.Chain.App.GetIBCKeeper().ClientKeeper.ClientStore(path.EndpointA.Chain.GetContext(), path.EndpointA.ClientID)
for _, height := range unexpiredHeights {
- clientStore.Delete(ibctmtypes.ProcessedHeightKey(height))
- clientStore.Delete(ibctmtypes.IterationKey(height))
+ clientStore.Delete(ibctm.ProcessedHeightKey(height))
+ clientStore.Delete(ibctm.IterationKey(height))
}
unexpiredHeightMap[path] = unexpiredHeights
@@ -198,15 +198,15 @@ func (suite *LegacyTestSuite) TestMigrateStoreTendermint() {
suite.Require().False(ok, i)
suite.Require().Nil(consState, i)
- processedTime, ok := ibctmtypes.GetProcessedTime(clientStore, pruneHeight)
+ processedTime, ok := ibctm.GetProcessedTime(clientStore, pruneHeight)
suite.Require().False(ok, i)
suite.Require().Equal(uint64(0), processedTime, i)
- processedHeight, ok := ibctmtypes.GetProcessedHeight(clientStore, pruneHeight)
+ processedHeight, ok := ibctm.GetProcessedHeight(clientStore, pruneHeight)
suite.Require().False(ok, i)
suite.Require().Nil(processedHeight, i)
- expectedConsKey := ibctmtypes.GetIterationKey(clientStore, pruneHeight)
+ expectedConsKey := ibctm.GetIterationKey(clientStore, pruneHeight)
suite.Require().Nil(expectedConsKey, i)
}
@@ -216,15 +216,15 @@ func (suite *LegacyTestSuite) TestMigrateStoreTendermint() {
suite.Require().True(ok)
suite.Require().NotNil(consState)
- processedTime, ok := ibctmtypes.GetProcessedTime(clientStore, height)
+ processedTime, ok := ibctm.GetProcessedTime(clientStore, height)
suite.Require().True(ok)
suite.Require().NotEqual(uint64(0), processedTime)
- processedHeight, ok := ibctmtypes.GetProcessedHeight(clientStore, height)
+ processedHeight, ok := ibctm.GetProcessedHeight(clientStore, height)
suite.Require().True(ok)
suite.Require().Equal(types.GetSelfHeight(path.EndpointA.Chain.GetContext()), processedHeight)
- consKey := ibctmtypes.GetIterationKey(clientStore, height)
+ consKey := ibctm.GetIterationKey(clientStore, height)
suite.Require().Equal(host.ConsensusStateKey(height), consKey)
}
}
diff --git a/modules/light-clients/06-solomachine/types/solomachine.pb.go b/modules/core/02-client/migrations/v6/solomachine.pb.go
similarity index 92%
rename from modules/light-clients/06-solomachine/types/solomachine.pb.go
rename to modules/core/02-client/migrations/v6/solomachine.pb.go
index 2a287b9ced7..bbcb1b6a355 100644
--- a/modules/light-clients/06-solomachine/types/solomachine.pb.go
+++ b/modules/core/02-client/migrations/v6/solomachine.pb.go
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: ibc/lightclients/solomachine/v2/solomachine.proto
-package types
+package v6
import (
fmt "fmt"
@@ -823,93 +823,93 @@ func init() {
}
var fileDescriptor_141333b361aae010 = []byte{
- // 1370 bytes of a gzipped FileDescriptorProto
+ // 1373 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x57, 0x5f, 0x8f, 0xdb, 0x44,
- 0x10, 0x3f, 0xa7, 0xe9, 0xf5, 0x32, 0xb9, 0xde, 0x05, 0x37, 0x6d, 0x73, 0x6e, 0x95, 0x18, 0x23,
- 0xca, 0x81, 0x68, 0xc2, 0x1d, 0x6a, 0x85, 0x2a, 0x04, 0x38, 0x8e, 0x4b, 0xd3, 0xde, 0xf9, 0x82,
- 0xe3, 0x03, 0x5a, 0x21, 0x19, 0xc7, 0xd9, 0x4b, 0xac, 0x26, 0xde, 0x34, 0x76, 0x92, 0x06, 0x09,
- 0x09, 0xf1, 0x54, 0x22, 0x1e, 0xf8, 0x02, 0x91, 0x10, 0x88, 0xcf, 0xc1, 0x1b, 0xf0, 0xd8, 0x47,
- 0x9e, 0x02, 0x6a, 0xbf, 0x41, 0x3e, 0x01, 0xb2, 0x77, 0x13, 0xdb, 0xb9, 0x5e, 0x4e, 0xfc, 0x7b,
- 0xdb, 0x9d, 0xdf, 0xcc, 0x6f, 0x66, 0x67, 0xc6, 0xb3, 0x6b, 0xd8, 0xb1, 0x6a, 0x66, 0xa1, 0x65,
- 0x35, 0x9a, 0xae, 0xd9, 0xb2, 0x90, 0xed, 0x3a, 0x05, 0x07, 0xb7, 0x70, 0xdb, 0x30, 0x9b, 0x96,
- 0x8d, 0x0a, 0xfd, 0xdd, 0xf0, 0x36, 0xdf, 0xe9, 0x62, 0x17, 0xb3, 0x39, 0xab, 0x66, 0xe6, 0xc3,
- 0x26, 0xf9, 0xb0, 0x4e, 0x7f, 0x97, 0x7b, 0xcd, 0xe3, 0x34, 0x71, 0x17, 0x15, 0x4c, 0x6c, 0xdb,
- 0xc8, 0x74, 0x2d, 0x6c, 0x17, 0xfa, 0x3b, 0xa1, 0x1d, 0x61, 0xe2, 0x5e, 0x0e, 0x14, 0x9b, 0x86,
- 0x6d, 0xa3, 0x96, 0xaf, 0x45, 0x96, 0x54, 0x25, 0xdd, 0xc0, 0x0d, 0xec, 0x2f, 0x0b, 0xde, 0x8a,
- 0x4a, 0xb7, 0x1a, 0x18, 0x37, 0x5a, 0xa8, 0xe0, 0xef, 0x6a, 0xbd, 0xa3, 0x82, 0x61, 0x0f, 0x09,
- 0x24, 0xfc, 0x1c, 0x83, 0xa4, 0xe4, 0xc7, 0x55, 0x75, 0x0d, 0x17, 0xb1, 0x1c, 0xac, 0x39, 0xe8,
- 0x51, 0x0f, 0xd9, 0x26, 0xca, 0x30, 0x3c, 0xb3, 0x1d, 0x57, 0xe7, 0x7b, 0x76, 0x07, 0x12, 0x96,
- 0xa3, 0x1f, 0x75, 0xf1, 0x17, 0xc8, 0xce, 0xc4, 0x78, 0x66, 0x7b, 0xad, 0x98, 0x9e, 0x4e, 0x72,
- 0xa9, 0xa1, 0xd1, 0x6e, 0xdd, 0x12, 0xe6, 0x90, 0xa0, 0xae, 0x59, 0xce, 0x6d, 0x7f, 0xc9, 0xba,
- 0xb0, 0x69, 0x62, 0xdb, 0x41, 0xb6, 0xd3, 0x73, 0x74, 0xc7, 0xf3, 0x90, 0x39, 0xc3, 0x33, 0xdb,
- 0xc9, 0xdd, 0x42, 0xfe, 0x94, 0xb4, 0xe4, 0xa5, 0x99, 0x9d, 0x1f, 0x58, 0x91, 0x9b, 0x4e, 0x72,
- 0x97, 0x88, 0xa7, 0x05, 0x46, 0x41, 0xdd, 0x30, 0x23, 0xba, 0x2c, 0x82, 0x2b, 0x46, 0xab, 0x85,
- 0x07, 0x7a, 0xaf, 0x53, 0x37, 0x5c, 0xa4, 0x1b, 0x47, 0x2e, 0xea, 0xea, 0x9d, 0x2e, 0xee, 0x60,
- 0xc7, 0x68, 0x65, 0xe2, 0x7e, 0xe8, 0xd7, 0xa6, 0x93, 0x9c, 0x40, 0x08, 0x97, 0x28, 0x0b, 0x6a,
- 0xc6, 0x47, 0x0f, 0x7d, 0x50, 0xf4, 0xb0, 0x0a, 0x85, 0x6e, 0xc5, 0x9f, 0x7c, 0x9f, 0x5b, 0x11,
- 0x7e, 0x60, 0x60, 0x23, 0x1a, 0x2b, 0x7b, 0x17, 0xa0, 0xd3, 0xab, 0xb5, 0x2c, 0x53, 0x7f, 0x88,
- 0x86, 0x7e, 0x1a, 0x93, 0xbb, 0xe9, 0x3c, 0x29, 0x42, 0x7e, 0x56, 0x84, 0xbc, 0x68, 0x0f, 0x8b,
- 0x17, 0xa7, 0x93, 0xdc, 0x4b, 0x24, 0x88, 0xc0, 0x42, 0x50, 0x13, 0x64, 0x73, 0x0f, 0x0d, 0x59,
- 0x1e, 0x92, 0x75, 0xab, 0x8f, 0xba, 0x8e, 0x75, 0x64, 0xa1, 0xae, 0x9f, 0xf6, 0x84, 0x1a, 0x16,
- 0xb1, 0x57, 0x21, 0xe1, 0x5a, 0x6d, 0xe4, 0xb8, 0x46, 0xbb, 0xe3, 0x67, 0x37, 0xae, 0x06, 0x02,
- 0x1a, 0xe4, 0xd7, 0x31, 0x58, 0xbd, 0x83, 0x8c, 0x3a, 0xea, 0x2e, 0xad, 0x70, 0x84, 0x2a, 0xb6,
- 0x40, 0xe5, 0xa1, 0x8e, 0xd5, 0xb0, 0x0d, 0xb7, 0xd7, 0x25, 0x65, 0x5c, 0x57, 0x03, 0x01, 0x7b,
- 0x08, 0x1b, 0x36, 0x1a, 0xe8, 0xa1, 0x83, 0xc7, 0x97, 0x1c, 0x7c, 0x6b, 0x3a, 0xc9, 0x5d, 0x24,
- 0x07, 0x8f, 0x5a, 0x09, 0xea, 0xba, 0x8d, 0x06, 0x95, 0xf9, 0xf9, 0x25, 0xd8, 0xf4, 0x14, 0xc2,
- 0x39, 0x38, 0xeb, 0xe5, 0x20, 0xdc, 0x10, 0x0b, 0x0a, 0x82, 0xea, 0x45, 0x52, 0x0a, 0x04, 0x34,
- 0x09, 0xbf, 0xc6, 0x60, 0x7d, 0xdf, 0x72, 0x6a, 0xa8, 0x69, 0xf4, 0x2d, 0xdc, 0xeb, 0x7a, 0x0d,
- 0x4d, 0x9a, 0x4f, 0xb7, 0xea, 0x7e, 0x2e, 0x12, 0xe1, 0x86, 0x9e, 0x43, 0x82, 0xba, 0x46, 0xd6,
- 0xe5, 0x7a, 0x24, 0x7b, 0xb1, 0x85, 0xec, 0x75, 0xe0, 0xfc, 0x3c, 0x1d, 0x3a, 0xb6, 0x67, 0xad,
- 0xbe, 0x73, 0x6a, 0xab, 0x57, 0x67, 0x56, 0xa2, 0x5d, 0x2f, 0x19, 0xae, 0x51, 0xcc, 0x4c, 0x27,
- 0xb9, 0x34, 0x89, 0x22, 0xc2, 0x28, 0xa8, 0xeb, 0xf3, 0xfd, 0x81, 0xbd, 0xe0, 0xd1, 0x1d, 0x60,
- 0x9a, 0xf2, 0xff, 0xca, 0xa3, 0x3b, 0xc0, 0x61, 0x8f, 0xda, 0x00, 0xd3, 0x4c, 0xfe, 0xc2, 0x40,
- 0x6a, 0x91, 0x22, 0xda, 0x1e, 0xcc, 0x62, 0x7b, 0x7c, 0x06, 0x89, 0xba, 0xe1, 0x1a, 0xba, 0x3b,
- 0xec, 0x90, 0xcc, 0x6d, 0xec, 0xbe, 0x7e, 0x6a, 0x98, 0x1e, 0xaf, 0x36, 0xec, 0xa0, 0x70, 0x59,
- 0xe6, 0x2c, 0x82, 0xba, 0x56, 0xa7, 0x38, 0xcb, 0x42, 0xdc, 0x5b, 0xd3, 0xae, 0xf4, 0xd7, 0xd1,
- 0x66, 0x8e, 0xbf, 0xf8, 0xbb, 0xf8, 0x8a, 0x81, 0x8c, 0x36, 0x93, 0xa1, 0xfa, 0xfc, 0x4c, 0xfe,
- 0x81, 0x3e, 0x80, 0x8d, 0x20, 0x17, 0x3e, 0xbd, 0x7f, 0xaa, 0x70, 0xef, 0x46, 0x71, 0x41, 0x0d,
- 0xca, 0x51, 0x3a, 0x16, 0x42, 0xec, 0xc5, 0x21, 0xfc, 0xc1, 0x40, 0xc2, 0xf3, 0x5b, 0x1c, 0xba,
- 0xc8, 0xf9, 0x17, 0x5f, 0xe7, 0xc2, 0xa0, 0x38, 0x73, 0x7c, 0x50, 0x44, 0x4a, 0x10, 0xff, 0xbf,
- 0x4a, 0x70, 0x36, 0x28, 0x01, 0x3d, 0xe1, 0x4f, 0x0c, 0x00, 0x19, 0x3e, 0x7e, 0x52, 0xf6, 0x20,
- 0x49, 0x3f, 0xf9, 0x53, 0xc7, 0xe3, 0xa5, 0xe9, 0x24, 0xc7, 0x46, 0xa6, 0x04, 0x9d, 0x8f, 0x64,
- 0x44, 0x9c, 0x30, 0x1f, 0x62, 0xff, 0x70, 0x3e, 0x7c, 0x09, 0x9b, 0xa1, 0xab, 0xd0, 0x8f, 0x95,
- 0x85, 0x78, 0xc7, 0x70, 0x9b, 0xb4, 0x9d, 0xfd, 0x35, 0x5b, 0x81, 0x75, 0x3a, 0x1a, 0xc8, 0x85,
- 0x16, 0x5b, 0x72, 0x80, 0xcb, 0xd3, 0x49, 0xee, 0x42, 0x64, 0x9c, 0xd0, 0x2b, 0x2b, 0x69, 0x06,
- 0x9e, 0xa8, 0xfb, 0x6f, 0x18, 0x60, 0xa3, 0x17, 0xc9, 0x89, 0x21, 0xdc, 0x3f, 0x7e, 0xad, 0x2e,
- 0x8b, 0xe2, 0x6f, 0xdc, 0x9d, 0x34, 0x96, 0x3e, 0x5c, 0x90, 0xe6, 0xcf, 0x8f, 0xe5, 0xb1, 0xc8,
- 0x00, 0xc1, 0x4b, 0x85, 0x86, 0xf1, 0xaa, 0xdf, 0x56, 0xde, 0x53, 0x25, 0x1f, 0x7a, 0xc5, 0xf4,
- 0x77, 0xf2, 0x01, 0xa9, 0x6c, 0xd7, 0xd5, 0x90, 0x21, 0xf5, 0x5b, 0x87, 0x94, 0x44, 0x1e, 0x34,
- 0xcb, 0x9d, 0xde, 0x84, 0x73, 0xf4, 0xe1, 0x43, 0x3d, 0x5e, 0x0d, 0x79, 0xa4, 0x2f, 0x22, 0xcf,
- 0x1d, 0x59, 0xaa, 0x33, 0x65, 0xea, 0xe5, 0x2e, 0xa4, 0x2b, 0x86, 0xf9, 0x10, 0xb9, 0x12, 0x6e,
- 0xb7, 0x2d, 0xb7, 0x8d, 0x6c, 0xf7, 0x44, 0x4f, 0x59, 0xef, 0x78, 0x33, 0x2d, 0xdf, 0xd9, 0xba,
- 0x1a, 0x92, 0x08, 0xf7, 0x61, 0x8b, 0x70, 0x89, 0xe6, 0x43, 0x1b, 0x0f, 0x5a, 0xa8, 0xde, 0x40,
- 0x4b, 0x09, 0xb7, 0x61, 0xd3, 0x88, 0xaa, 0x52, 0xd6, 0x45, 0xb1, 0x90, 0x87, 0x0c, 0xa1, 0x56,
- 0x91, 0x89, 0xac, 0x8e, 0x2b, 0xd6, 0x1c, 0x6f, 0x0e, 0x9c, 0xc4, 0x2c, 0x34, 0x21, 0xad, 0xa0,
- 0xc7, 0x6e, 0x95, 0xce, 0x0b, 0x15, 0x99, 0xfd, 0x13, 0xa3, 0x78, 0x17, 0xce, 0xdb, 0xe8, 0xb1,
- 0xab, 0x3b, 0xe8, 0x91, 0xde, 0x45, 0x66, 0x9f, 0xcc, 0x93, 0xf0, 0x35, 0x10, 0x81, 0x05, 0x35,
- 0x69, 0x13, 0x6a, 0x8f, 0xf5, 0x8d, 0x6f, 0xe3, 0xb0, 0x36, 0x1b, 0x0c, 0xec, 0x3b, 0xf0, 0x4a,
- 0x49, 0xd4, 0x44, 0x5d, 0xbb, 0x5f, 0x91, 0xf5, 0x43, 0xa5, 0xac, 0x94, 0xb5, 0xb2, 0xb8, 0x57,
- 0x7e, 0x20, 0x97, 0xf4, 0x43, 0xa5, 0x5a, 0x91, 0xa5, 0xf2, 0xed, 0xb2, 0x5c, 0x4a, 0xad, 0x70,
- 0x9b, 0xa3, 0x31, 0x9f, 0x0c, 0x89, 0xd8, 0x6b, 0x70, 0x29, 0xb0, 0x94, 0xf6, 0xca, 0xb2, 0xa2,
- 0xe9, 0x55, 0x4d, 0xd4, 0xe4, 0x14, 0xc3, 0xc1, 0x68, 0xcc, 0xaf, 0x12, 0x19, 0xfb, 0x26, 0x6c,
- 0x85, 0xf4, 0x0e, 0x94, 0xaa, 0xac, 0x54, 0x0f, 0xab, 0x54, 0x35, 0xc6, 0x9d, 0x1f, 0x8d, 0xf9,
- 0xc4, 0x5c, 0xcc, 0xe6, 0x81, 0x8b, 0x68, 0x2b, 0xb2, 0xa4, 0x95, 0x0f, 0x14, 0xaa, 0x7e, 0x86,
- 0xdb, 0x18, 0x8d, 0x79, 0x08, 0xe4, 0xec, 0x36, 0x5c, 0x0e, 0xe9, 0xdf, 0x11, 0x15, 0x45, 0xde,
- 0xa3, 0xca, 0x71, 0x2e, 0x39, 0x1a, 0xf3, 0xe7, 0xa8, 0x90, 0xbd, 0x01, 0x57, 0x02, 0xcd, 0x8a,
- 0x28, 0xdd, 0x93, 0x35, 0x5d, 0x3a, 0xd8, 0xdf, 0x2f, 0x6b, 0xfb, 0xb2, 0xa2, 0xa5, 0xce, 0x72,
- 0xe9, 0xd1, 0x98, 0x4f, 0x11, 0x20, 0x90, 0xb3, 0xef, 0x03, 0x7f, 0xcc, 0x4c, 0x94, 0xee, 0x29,
- 0x07, 0x9f, 0xec, 0xc9, 0xa5, 0x0f, 0x65, 0xdf, 0x76, 0x95, 0xdb, 0x1a, 0x8d, 0xf9, 0x8b, 0x04,
- 0x5d, 0x00, 0xd9, 0xf7, 0x5e, 0x40, 0xa0, 0xca, 0x92, 0x5c, 0xae, 0x68, 0xba, 0x58, 0xac, 0xca,
- 0x8a, 0x24, 0xa7, 0xce, 0x71, 0x99, 0xd1, 0x98, 0x4f, 0x13, 0x94, 0x82, 0x14, 0x63, 0x6f, 0xc2,
- 0xd5, 0xc0, 0x5e, 0x91, 0x3f, 0xd5, 0xf4, 0xaa, 0xfc, 0xd1, 0xa1, 0x07, 0x79, 0x34, 0x1f, 0xa7,
- 0xd6, 0x48, 0xe0, 0x1e, 0x32, 0x03, 0x3c, 0x39, 0xcb, 0x43, 0x2a, 0xb0, 0xbb, 0x23, 0x8b, 0x25,
- 0x59, 0x4d, 0x25, 0x48, 0x65, 0xc8, 0x8e, 0x8b, 0x3f, 0xf9, 0x31, 0xbb, 0x52, 0xfc, 0xfc, 0xb7,
- 0x67, 0x59, 0xe6, 0xe9, 0xb3, 0x2c, 0xf3, 0xe7, 0xb3, 0x2c, 0xf3, 0xdd, 0xf3, 0xec, 0xca, 0xd3,
- 0xe7, 0xd9, 0x95, 0xdf, 0x9f, 0x67, 0x57, 0x1e, 0xdc, 0x6e, 0x58, 0x6e, 0xb3, 0x57, 0xcb, 0x9b,
- 0xb8, 0x5d, 0x30, 0xb1, 0xd3, 0xc6, 0x4e, 0xc1, 0xaa, 0x99, 0xd7, 0x1b, 0xb8, 0xd0, 0xbf, 0x51,
- 0x68, 0xe3, 0x7a, 0xaf, 0x85, 0x1c, 0xf2, 0x3f, 0x75, 0x7d, 0xf6, 0x43, 0xf5, 0xd6, 0xcd, 0xeb,
- 0xe1, 0x7f, 0x2a, 0xef, 0x9a, 0x71, 0x6a, 0xab, 0xfe, 0x3c, 0x7b, 0xfb, 0xaf, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0x32, 0xda, 0xb7, 0x54, 0x80, 0x0d, 0x00, 0x00,
+ 0x10, 0x3f, 0xa7, 0xe9, 0xf5, 0xb2, 0xb9, 0xde, 0x05, 0x37, 0x6d, 0x73, 0x6e, 0x95, 0x18, 0x23,
+ 0xca, 0x81, 0x68, 0xcc, 0x1d, 0x6a, 0x85, 0x2a, 0x04, 0x75, 0x1c, 0x97, 0xa6, 0xbd, 0xf3, 0x05,
+ 0xc7, 0x07, 0xb4, 0x42, 0xb2, 0x1c, 0x7b, 0x2f, 0xb1, 0x9a, 0x78, 0xd3, 0x78, 0x93, 0x34, 0x48,
+ 0x48, 0x88, 0xa7, 0x12, 0xf1, 0xc0, 0x17, 0x88, 0x84, 0x40, 0x7c, 0x0e, 0xde, 0x80, 0xc7, 0x3e,
+ 0xf2, 0x14, 0x50, 0xfb, 0x0d, 0xf2, 0x09, 0x90, 0xbd, 0x9b, 0xd8, 0xce, 0xf5, 0x72, 0xe2, 0xdf,
+ 0xdb, 0xee, 0xfc, 0x66, 0x7e, 0x33, 0x3b, 0x33, 0x9e, 0x5d, 0x83, 0x1d, 0xa7, 0x6e, 0x89, 0x2d,
+ 0xa7, 0xd1, 0xc4, 0x56, 0xcb, 0x81, 0x2e, 0xf6, 0x44, 0x0f, 0xb5, 0x50, 0xdb, 0xb4, 0x9a, 0x8e,
+ 0x0b, 0xc5, 0xfe, 0x6e, 0x74, 0x5b, 0xec, 0x74, 0x11, 0x46, 0x6c, 0xc1, 0xa9, 0x5b, 0xc5, 0xa8,
+ 0x49, 0x31, 0xaa, 0xd3, 0xdf, 0xe5, 0xde, 0xf0, 0x39, 0x2d, 0xd4, 0x85, 0xa2, 0x85, 0x5c, 0x17,
+ 0x5a, 0xd8, 0x41, 0xae, 0xd8, 0xdf, 0x89, 0xec, 0x08, 0x13, 0xf7, 0x6a, 0xa8, 0xd8, 0x34, 0x5d,
+ 0x17, 0xb6, 0x02, 0x2d, 0xb2, 0xa4, 0x2a, 0xd9, 0x06, 0x6a, 0xa0, 0x60, 0x29, 0xfa, 0x2b, 0x2a,
+ 0xdd, 0x6a, 0x20, 0xd4, 0x68, 0x41, 0x31, 0xd8, 0xd5, 0x7b, 0x47, 0xa2, 0xe9, 0x0e, 0x09, 0x24,
+ 0xfc, 0x9c, 0x00, 0x69, 0x39, 0x88, 0xab, 0x86, 0x4d, 0x0c, 0x59, 0x0e, 0xac, 0x79, 0xf0, 0x71,
+ 0x0f, 0xba, 0x16, 0xcc, 0x31, 0x3c, 0xb3, 0x9d, 0xd4, 0xe6, 0x7b, 0x76, 0x07, 0xa4, 0x1c, 0xcf,
+ 0x38, 0xea, 0xa2, 0x2f, 0xa0, 0x9b, 0x4b, 0xf0, 0xcc, 0xf6, 0x5a, 0x29, 0x3b, 0x9d, 0x14, 0x32,
+ 0x43, 0xb3, 0xdd, 0xba, 0x25, 0xcc, 0x21, 0x41, 0x5b, 0x73, 0xbc, 0x3b, 0xc1, 0x92, 0xc5, 0x60,
+ 0xd3, 0x42, 0xae, 0x07, 0x5d, 0xaf, 0xe7, 0x19, 0x9e, 0xef, 0x21, 0x77, 0x86, 0x67, 0xb6, 0xd3,
+ 0xbb, 0x62, 0xf1, 0x94, 0xb4, 0x14, 0xe5, 0x99, 0x5d, 0x10, 0x58, 0x89, 0x9b, 0x4e, 0x0a, 0x97,
+ 0x88, 0xa7, 0x05, 0x46, 0x41, 0xdb, 0xb0, 0x62, 0xba, 0x2c, 0x04, 0x57, 0xcc, 0x56, 0x0b, 0x0d,
+ 0x8c, 0x5e, 0xc7, 0x36, 0x31, 0x34, 0xcc, 0x23, 0x0c, 0xbb, 0x46, 0xa7, 0x8b, 0x3a, 0xc8, 0x33,
+ 0x5b, 0xb9, 0x64, 0x10, 0xfa, 0xb5, 0xe9, 0xa4, 0x20, 0x10, 0xc2, 0x25, 0xca, 0x82, 0x96, 0x0b,
+ 0xd0, 0xc3, 0x00, 0x94, 0x7c, 0xac, 0x4a, 0xa1, 0x5b, 0xc9, 0xa7, 0xdf, 0x17, 0x56, 0x84, 0x1f,
+ 0x18, 0xb0, 0x11, 0x8f, 0x95, 0xbd, 0x07, 0x40, 0xa7, 0x57, 0x6f, 0x39, 0x96, 0xf1, 0x08, 0x0e,
+ 0x83, 0x34, 0xa6, 0x77, 0xb3, 0x45, 0x52, 0x84, 0xe2, 0xac, 0x08, 0x45, 0xc9, 0x1d, 0x96, 0x2e,
+ 0x4e, 0x27, 0x85, 0x57, 0x48, 0x10, 0xa1, 0x85, 0xa0, 0xa5, 0xc8, 0xe6, 0x3e, 0x1c, 0xb2, 0x3c,
+ 0x48, 0xdb, 0x4e, 0x1f, 0x76, 0x3d, 0xe7, 0xc8, 0x81, 0xdd, 0x20, 0xed, 0x29, 0x2d, 0x2a, 0x62,
+ 0xaf, 0x82, 0x14, 0x76, 0xda, 0xd0, 0xc3, 0x66, 0xbb, 0x13, 0x64, 0x37, 0xa9, 0x85, 0x02, 0x1a,
+ 0xe4, 0xd7, 0x09, 0xb0, 0x7a, 0x17, 0x9a, 0x36, 0xec, 0x2e, 0xad, 0x70, 0x8c, 0x2a, 0xb1, 0x40,
+ 0xe5, 0xa3, 0x9e, 0xd3, 0x70, 0x4d, 0xdc, 0xeb, 0x92, 0x32, 0xae, 0x6b, 0xa1, 0x80, 0x3d, 0x04,
+ 0x1b, 0x2e, 0x1c, 0x18, 0x91, 0x83, 0x27, 0x97, 0x1c, 0x7c, 0x6b, 0x3a, 0x29, 0x5c, 0x24, 0x07,
+ 0x8f, 0x5b, 0x09, 0xda, 0xba, 0x0b, 0x07, 0xd5, 0xf9, 0xf9, 0x65, 0xb0, 0xe9, 0x2b, 0x44, 0x73,
+ 0x70, 0xd6, 0xcf, 0x41, 0xb4, 0x21, 0x16, 0x14, 0x04, 0xcd, 0x8f, 0xa4, 0x1c, 0x0a, 0x68, 0x12,
+ 0x7e, 0x4d, 0x80, 0xf5, 0x7d, 0xc7, 0xab, 0xc3, 0xa6, 0xd9, 0x77, 0x50, 0xaf, 0xeb, 0x37, 0x34,
+ 0x69, 0x3e, 0xc3, 0xb1, 0x83, 0x5c, 0xa4, 0xa2, 0x0d, 0x3d, 0x87, 0x04, 0x6d, 0x8d, 0xac, 0x2b,
+ 0x76, 0x2c, 0x7b, 0x89, 0x85, 0xec, 0x75, 0xc0, 0xf9, 0x79, 0x3a, 0x0c, 0xe4, 0xce, 0x5a, 0x7d,
+ 0xe7, 0xd4, 0x56, 0xaf, 0xcd, 0xac, 0x24, 0xd7, 0x2e, 0x9b, 0xd8, 0x2c, 0xe5, 0xa6, 0x93, 0x42,
+ 0x96, 0x44, 0x11, 0x63, 0x14, 0xb4, 0xf5, 0xf9, 0xfe, 0xc0, 0x5d, 0xf0, 0x88, 0x07, 0x88, 0xa6,
+ 0xfc, 0xbf, 0xf2, 0x88, 0x07, 0x28, 0xea, 0x51, 0x1f, 0x20, 0x9a, 0xc9, 0x5f, 0x18, 0x90, 0x59,
+ 0xa4, 0x88, 0xb7, 0x07, 0xb3, 0xd8, 0x1e, 0x9f, 0x83, 0x94, 0x6d, 0x62, 0xd3, 0xc0, 0xc3, 0x0e,
+ 0xc9, 0xdc, 0xc6, 0xee, 0x9b, 0xa7, 0x86, 0xe9, 0xf3, 0xea, 0xc3, 0x0e, 0x8c, 0x96, 0x65, 0xce,
+ 0x22, 0x68, 0x6b, 0x36, 0xc5, 0x59, 0x16, 0x24, 0xfd, 0x35, 0xed, 0xca, 0x60, 0x1d, 0x6f, 0xe6,
+ 0xe4, 0xcb, 0xbf, 0x8b, 0xaf, 0x18, 0x90, 0xd3, 0x67, 0x32, 0x68, 0xcf, 0xcf, 0x14, 0x1c, 0xe8,
+ 0x36, 0xd8, 0x08, 0x73, 0x11, 0xd0, 0x07, 0xa7, 0x8a, 0xf6, 0x6e, 0x1c, 0x17, 0xb4, 0xb0, 0x1c,
+ 0xe5, 0x63, 0x21, 0x24, 0x5e, 0x1e, 0xc2, 0x1f, 0x0c, 0x48, 0xf9, 0x7e, 0x4b, 0x43, 0x0c, 0xbd,
+ 0x7f, 0xf1, 0x75, 0x2e, 0x0c, 0x8a, 0x33, 0xc7, 0x07, 0x45, 0xac, 0x04, 0xc9, 0xff, 0xab, 0x04,
+ 0x67, 0xc3, 0x12, 0xd0, 0x13, 0xfe, 0xc4, 0x00, 0x40, 0x86, 0x4f, 0x90, 0x94, 0x3d, 0x90, 0xa6,
+ 0x9f, 0xfc, 0xa9, 0xe3, 0xf1, 0xd2, 0x74, 0x52, 0x60, 0x63, 0x53, 0x82, 0xce, 0x47, 0x32, 0x22,
+ 0x4e, 0x98, 0x0f, 0x89, 0x7f, 0x38, 0x1f, 0xbe, 0x04, 0x9b, 0x91, 0xab, 0x30, 0x88, 0x95, 0x05,
+ 0xc9, 0x8e, 0x89, 0x9b, 0xb4, 0x9d, 0x83, 0x35, 0x5b, 0x05, 0xeb, 0x74, 0x34, 0x90, 0x0b, 0x2d,
+ 0xb1, 0xe4, 0x00, 0x97, 0xa7, 0x93, 0xc2, 0x85, 0xd8, 0x38, 0xa1, 0x57, 0x56, 0xda, 0x0a, 0x3d,
+ 0x51, 0xf7, 0xdf, 0x30, 0x80, 0x8d, 0x5f, 0x24, 0x27, 0x86, 0xf0, 0xe0, 0xf8, 0xb5, 0xba, 0x2c,
+ 0x8a, 0xbf, 0x71, 0x77, 0xd2, 0x58, 0xfa, 0xe0, 0x82, 0x3c, 0x7f, 0x7e, 0x2c, 0x8f, 0x45, 0x01,
+ 0x20, 0x7c, 0xa9, 0xd0, 0x30, 0x5e, 0x0f, 0xda, 0xca, 0x7f, 0xaa, 0x14, 0x23, 0xaf, 0x98, 0xfe,
+ 0x4e, 0x31, 0x24, 0x55, 0x5c, 0x5b, 0x8b, 0x18, 0x52, 0xbf, 0x36, 0xc8, 0xc8, 0xe4, 0x41, 0xb3,
+ 0xdc, 0xe9, 0x4d, 0x70, 0x8e, 0x3e, 0x7c, 0xa8, 0xc7, 0xab, 0x11, 0x8f, 0xf4, 0x45, 0xe4, 0xbb,
+ 0x23, 0x4b, 0x6d, 0xa6, 0x4c, 0xbd, 0xdc, 0x03, 0xd9, 0xaa, 0x69, 0x3d, 0x82, 0x58, 0x46, 0xed,
+ 0xb6, 0x83, 0xdb, 0xd0, 0xc5, 0x27, 0x7a, 0xca, 0xfb, 0xc7, 0x9b, 0x69, 0x05, 0xce, 0xd6, 0xb5,
+ 0x88, 0x44, 0x78, 0x00, 0xb6, 0x08, 0x97, 0x64, 0x3d, 0x72, 0xd1, 0xa0, 0x05, 0xed, 0x06, 0x5c,
+ 0x4a, 0xb8, 0x0d, 0x36, 0xcd, 0xb8, 0x2a, 0x65, 0x5d, 0x14, 0x0b, 0x45, 0x90, 0x23, 0xd4, 0x1a,
+ 0xb4, 0xa0, 0xd3, 0xc1, 0x52, 0xdd, 0xf3, 0xe7, 0xc0, 0x49, 0xcc, 0x42, 0x13, 0x64, 0x55, 0xf8,
+ 0x04, 0xd7, 0xe8, 0xbc, 0xd0, 0xa0, 0xd5, 0x3f, 0x31, 0x8a, 0xf7, 0xc1, 0x79, 0x17, 0x3e, 0xc1,
+ 0x86, 0x07, 0x1f, 0x1b, 0x5d, 0x68, 0xf5, 0xc9, 0x3c, 0x89, 0x5e, 0x03, 0x31, 0x58, 0xd0, 0xd2,
+ 0x2e, 0xa1, 0xf6, 0x59, 0xdf, 0xfa, 0x36, 0x09, 0xd6, 0x66, 0x83, 0x81, 0x7d, 0x0f, 0xbc, 0x56,
+ 0x96, 0x74, 0xc9, 0xd0, 0x1f, 0x54, 0x15, 0xe3, 0x50, 0xad, 0xa8, 0x15, 0xbd, 0x22, 0xed, 0x55,
+ 0x1e, 0x2a, 0x65, 0xe3, 0x50, 0xad, 0x55, 0x15, 0xb9, 0x72, 0xa7, 0xa2, 0x94, 0x33, 0x2b, 0xdc,
+ 0xe6, 0x68, 0xcc, 0xa7, 0x23, 0x22, 0xf6, 0x1a, 0xb8, 0x14, 0x5a, 0xca, 0x7b, 0x15, 0x45, 0xd5,
+ 0x8d, 0x9a, 0x2e, 0xe9, 0x4a, 0x86, 0xe1, 0xc0, 0x68, 0xcc, 0xaf, 0x12, 0x19, 0xfb, 0x36, 0xd8,
+ 0x8a, 0xe8, 0x1d, 0xa8, 0x35, 0x45, 0xad, 0x1d, 0xd6, 0xa8, 0x6a, 0x82, 0x3b, 0x3f, 0x1a, 0xf3,
+ 0xa9, 0xb9, 0x98, 0x2d, 0x02, 0x2e, 0xa6, 0xad, 0x2a, 0xb2, 0x5e, 0x39, 0x50, 0xa9, 0xfa, 0x19,
+ 0x6e, 0x63, 0x34, 0xe6, 0x41, 0x28, 0x67, 0xb7, 0xc1, 0xe5, 0x88, 0xfe, 0x5d, 0x49, 0x55, 0x95,
+ 0x3d, 0xaa, 0x9c, 0xe4, 0xd2, 0xa3, 0x31, 0x7f, 0x8e, 0x0a, 0xd9, 0x1b, 0xe0, 0x4a, 0xa8, 0x59,
+ 0x95, 0xe4, 0xfb, 0x8a, 0x6e, 0xc8, 0x07, 0xfb, 0xfb, 0x15, 0x7d, 0x5f, 0x51, 0xf5, 0xcc, 0x59,
+ 0x2e, 0x3b, 0x1a, 0xf3, 0x19, 0x02, 0x84, 0x72, 0xf6, 0x43, 0xc0, 0x1f, 0x33, 0x93, 0xe4, 0xfb,
+ 0xea, 0xc1, 0xa7, 0x7b, 0x4a, 0xf9, 0x23, 0x25, 0xb0, 0x5d, 0xe5, 0xb6, 0x46, 0x63, 0xfe, 0x22,
+ 0x41, 0x17, 0x40, 0xf6, 0x83, 0x97, 0x10, 0x68, 0x8a, 0xac, 0x54, 0xaa, 0xba, 0x21, 0x95, 0x6a,
+ 0x8a, 0x2a, 0x2b, 0x99, 0x73, 0x5c, 0x6e, 0x34, 0xe6, 0xb3, 0x04, 0xa5, 0x20, 0xc5, 0xd8, 0x9b,
+ 0xe0, 0x6a, 0x68, 0xaf, 0x2a, 0x9f, 0xe9, 0x46, 0x4d, 0xf9, 0xf8, 0xd0, 0x87, 0x7c, 0x9a, 0x4f,
+ 0x32, 0x6b, 0x24, 0x70, 0x1f, 0x99, 0x01, 0xbe, 0x9c, 0xe5, 0x41, 0x26, 0xb4, 0xbb, 0xab, 0x48,
+ 0x65, 0x45, 0xcb, 0xa4, 0x48, 0x65, 0xc8, 0x8e, 0x4b, 0x3e, 0xfd, 0x31, 0xbf, 0x52, 0x7a, 0xf8,
+ 0xdb, 0xf3, 0x3c, 0xf3, 0xec, 0x79, 0x9e, 0xf9, 0xf3, 0x79, 0x9e, 0xf9, 0xee, 0x45, 0x7e, 0xe5,
+ 0xd9, 0x8b, 0xfc, 0xca, 0xef, 0x2f, 0xf2, 0x2b, 0x0f, 0x6f, 0x37, 0x1c, 0xdc, 0xec, 0xd5, 0x8b,
+ 0x16, 0x6a, 0x8b, 0x16, 0xf2, 0xda, 0xc8, 0x13, 0x9d, 0xba, 0x75, 0xbd, 0x81, 0xc4, 0xfe, 0x0d,
+ 0xb1, 0x8d, 0xec, 0x5e, 0x0b, 0x7a, 0xe4, 0x97, 0xe6, 0x9d, 0xdd, 0xeb, 0x64, 0x24, 0x8a, 0x6d,
+ 0xa7, 0xd1, 0x35, 0xfd, 0x99, 0xe0, 0x89, 0xfd, 0x9b, 0xf5, 0xd5, 0x60, 0x92, 0xbd, 0xfb, 0x57,
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0x9c, 0xae, 0x69, 0xbe, 0x7a, 0x0d, 0x00, 0x00,
}
func (m *ClientState) Marshal() (dAtA []byte, err error) {
diff --git a/modules/core/02-client/proposal_handler_test.go b/modules/core/02-client/proposal_handler_test.go
index 7cbe4de91a5..9c13a1c56f6 100644
--- a/modules/core/02-client/proposal_handler_test.go
+++ b/modules/core/02-client/proposal_handler_test.go
@@ -7,7 +7,7 @@ import (
client "github.com/cosmos/ibc-go/v5/modules/core/02-client"
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -38,14 +38,14 @@ func (suite *ClientTestSuite) TestNewClientUpdateProposalHandler() {
suite.Require().NoError(err)
substituteClientState := suite.chainA.GetClientState(substitutePath.EndpointA.ClientID)
- tmClientState, ok := subjectClientState.(*ibctmtypes.ClientState)
+ tmClientState, ok := subjectClientState.(*ibctm.ClientState)
suite.Require().True(ok)
tmClientState.AllowUpdateAfterMisbehaviour = true
tmClientState.FrozenHeight = tmClientState.LatestHeight
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), subjectPath.EndpointA.ClientID, tmClientState)
// replicate changes to substitute (they must match)
- tmClientState, ok = substituteClientState.(*ibctmtypes.ClientState)
+ tmClientState, ok = substituteClientState.(*ibctm.ClientState)
suite.Require().True(ok)
tmClientState.AllowUpdateAfterMisbehaviour = true
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), substitutePath.EndpointA.ClientID, tmClientState)
diff --git a/modules/core/02-client/simulation/decoder_test.go b/modules/core/02-client/simulation/decoder_test.go
index 6cb7f24811b..40a7c8eea5e 100644
--- a/modules/core/02-client/simulation/decoder_test.go
+++ b/modules/core/02-client/simulation/decoder_test.go
@@ -11,7 +11,7 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/02-client/simulation"
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
"github.com/cosmos/ibc-go/v5/testing/simapp"
)
@@ -21,11 +21,11 @@ func TestDecodeStore(t *testing.T) {
height := types.NewHeight(0, 10)
- clientState := &ibctmtypes.ClientState{
+ clientState := &ibctm.ClientState{
FrozenHeight: height,
}
- consState := &ibctmtypes.ConsensusState{
+ consState := &ibctm.ConsensusState{
Timestamp: time.Now().UTC(),
}
diff --git a/modules/core/02-client/types/codec.go b/modules/core/02-client/types/codec.go
index 293b466fd10..247507e8c32 100644
--- a/modules/core/02-client/types/codec.go
+++ b/modules/core/02-client/types/codec.go
@@ -23,7 +23,7 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
)
registry.RegisterInterface(
"ibc.core.client.v1.Header",
- (*exported.Header)(nil),
+ (*exported.ClientMessage)(nil),
)
registry.RegisterInterface(
"ibc.core.client.v1.Height",
@@ -32,7 +32,7 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
)
registry.RegisterInterface(
"ibc.core.client.v1.Misbehaviour",
- (*exported.Misbehaviour)(nil),
+ (*exported.ClientMessage)(nil),
)
registry.RegisterImplementations(
(*govtypes.Content)(nil),
@@ -124,66 +124,34 @@ func UnpackConsensusState(any *codectypes.Any) (exported.ConsensusState, error)
return consensusState, nil
}
-// PackHeader constructs a new Any packed with the given header value. It returns
-// an error if the header can't be casted to a protobuf message or if the concrete
+// PackClientMessage constructs a new Any packed with the given value. It returns
+// an error if the value can't be casted to a protobuf message or if the concrete
// implemention is not registered to the protobuf codec.
-func PackHeader(header exported.Header) (*codectypes.Any, error) {
- msg, ok := header.(proto.Message)
+func PackClientMessage(clientMessage exported.ClientMessage) (*codectypes.Any, error) {
+ msg, ok := clientMessage.(proto.Message)
if !ok {
- return nil, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", header)
+ return nil, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", clientMessage)
}
- anyHeader, err := codectypes.NewAnyWithValue(msg)
+ any, err := codectypes.NewAnyWithValue(msg)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrPackAny, err.Error())
}
- return anyHeader, nil
+ return any, nil
}
-// UnpackHeader unpacks an Any into a Header. It returns an error if the
-// consensus state can't be unpacked into a Header.
-func UnpackHeader(any *codectypes.Any) (exported.Header, error) {
+// UnpackClientMessage unpacks an Any into a ClientMessage. It returns an error if the
+// consensus state can't be unpacked into a ClientMessage.
+func UnpackClientMessage(any *codectypes.Any) (exported.ClientMessage, error) {
if any == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnpackAny, "protobuf Any message cannot be nil")
}
- header, ok := any.GetCachedValue().(exported.Header)
+ clientMessage, ok := any.GetCachedValue().(exported.ClientMessage)
if !ok {
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnpackAny, "cannot unpack Any into Header %T", any)
}
- return header, nil
-}
-
-// PackMisbehaviour constructs a new Any packed with the given misbehaviour value. It returns
-// an error if the misbehaviour can't be casted to a protobuf message or if the concrete
-// implemention is not registered to the protobuf codec.
-func PackMisbehaviour(misbehaviour exported.Misbehaviour) (*codectypes.Any, error) {
- msg, ok := misbehaviour.(proto.Message)
- if !ok {
- return nil, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", misbehaviour)
- }
-
- anyMisbhaviour, err := codectypes.NewAnyWithValue(msg)
- if err != nil {
- return nil, sdkerrors.Wrap(sdkerrors.ErrPackAny, err.Error())
- }
-
- return anyMisbhaviour, nil
-}
-
-// UnpackMisbehaviour unpacks an Any into a Misbehaviour. It returns an error if the
-// Any can't be unpacked into a Misbehaviour.
-func UnpackMisbehaviour(any *codectypes.Any) (exported.Misbehaviour, error) {
- if any == nil {
- return nil, sdkerrors.Wrap(sdkerrors.ErrUnpackAny, "protobuf Any message cannot be nil")
- }
-
- misbehaviour, ok := any.GetCachedValue().(exported.Misbehaviour)
- if !ok {
- return nil, sdkerrors.Wrapf(sdkerrors.ErrUnpackAny, "cannot unpack Any into Misbehaviour %T", any)
- }
-
- return misbehaviour, nil
+ return clientMessage, nil
}
diff --git a/modules/core/02-client/types/codec_test.go b/modules/core/02-client/types/codec_test.go
index e8bfb0b1beb..cfcd395b0c9 100644
--- a/modules/core/02-client/types/codec_test.go
+++ b/modules/core/02-client/types/codec_test.go
@@ -6,8 +6,7 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
- localhosttypes "github.com/cosmos/ibc-go/v5/modules/light-clients/09-localhost/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -30,12 +29,7 @@ func (suite *TypesTestSuite) TestPackClientState() {
},
{
"tendermint client",
- ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- true,
- },
- {
- "localhost client",
- localhosttypes.NewClientState(chainID, clientHeight),
+ ibctm.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
true,
},
{
@@ -115,15 +109,15 @@ func (suite *TypesTestSuite) TestPackConsensusState() {
}
}
-func (suite *TypesTestSuite) TestPackHeader() {
+func (suite *TypesTestSuite) TestPackClientMessage() {
testCases := []struct {
- name string
- header exported.Header
- expPass bool
+ name string
+ clientMessage exported.ClientMessage
+ expPass bool
}{
{
"solo machine header",
- ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2).CreateHeader(),
+ ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2).CreateHeader("solomachine"),
true,
},
{
@@ -141,54 +135,7 @@ func (suite *TypesTestSuite) TestPackHeader() {
testCasesAny := []caseAny{}
for _, tc := range testCases {
- clientAny, err := types.PackHeader(tc.header)
- if tc.expPass {
- suite.Require().NoError(err, tc.name)
- } else {
- suite.Require().Error(err, tc.name)
- }
-
- testCasesAny = append(testCasesAny, caseAny{tc.name, clientAny, tc.expPass})
- }
-
- for i, tc := range testCasesAny {
- cs, err := types.UnpackHeader(tc.any)
- if tc.expPass {
- suite.Require().NoError(err, tc.name)
- suite.Require().Equal(testCases[i].header, cs, tc.name)
- } else {
- suite.Require().Error(err, tc.name)
- }
- }
-}
-
-func (suite *TypesTestSuite) TestPackMisbehaviour() {
- testCases := []struct {
- name string
- misbehaviour exported.Misbehaviour
- expPass bool
- }{
- {
- "solo machine misbehaviour",
- ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2).CreateMisbehaviour(),
- true,
- },
- {
- "tendermint misbehaviour",
- ibctmtypes.NewMisbehaviour("tendermint", suite.chainA.LastHeader, suite.chainA.LastHeader),
- true,
- },
- {
- "nil",
- nil,
- false,
- },
- }
-
- testCasesAny := []caseAny{}
-
- for _, tc := range testCases {
- clientAny, err := types.PackMisbehaviour(tc.misbehaviour)
+ clientAny, err := types.PackClientMessage(tc.clientMessage)
if tc.expPass {
suite.Require().NoError(err, tc.name)
} else {
@@ -199,10 +146,10 @@ func (suite *TypesTestSuite) TestPackMisbehaviour() {
}
for i, tc := range testCasesAny {
- cs, err := types.UnpackMisbehaviour(tc.any)
+ cs, err := types.UnpackClientMessage(tc.any)
if tc.expPass {
suite.Require().NoError(err, tc.name)
- suite.Require().Equal(testCases[i].misbehaviour, cs, tc.name)
+ suite.Require().Equal(testCases[i].clientMessage, cs, tc.name)
} else {
suite.Require().Error(err, tc.name)
}
diff --git a/modules/core/02-client/types/encoding.go b/modules/core/02-client/types/encoding.go
index 90bbbd16965..b974eb8b942 100644
--- a/modules/core/02-client/types/encoding.go
+++ b/modules/core/02-client/types/encoding.go
@@ -86,29 +86,29 @@ func UnmarshalConsensusState(cdc codec.BinaryCodec, bz []byte) (exported.Consens
return consensusState, nil
}
-// MarshalHeader protobuf serializes a Header interface
-func MarshalHeader(cdc codec.BinaryCodec, h exported.Header) ([]byte, error) {
- return cdc.MarshalInterface(h)
+// MarshalClientMessage protobuf serializes a ClientMessage interface
+func MarshalClientMessage(cdc codec.BinaryCodec, clientMessage exported.ClientMessage) ([]byte, error) {
+ return cdc.MarshalInterface(clientMessage)
}
-// MustMarshalHeader attempts to encode a Header object and returns the
+// MustMarshalClientMessage attempts to encode a ClientMessage object and returns the
// raw encoded bytes. It panics on error.
-func MustMarshalHeader(cdc codec.BinaryCodec, header exported.Header) []byte {
- bz, err := MarshalHeader(cdc, header)
+func MustMarshalClientMessage(cdc codec.BinaryCodec, clientMessage exported.ClientMessage) []byte {
+ bz, err := MarshalClientMessage(cdc, clientMessage)
if err != nil {
- panic(fmt.Errorf("failed to encode header: %w", err))
+ panic(fmt.Errorf("failed to encode ClientMessage: %w", err))
}
return bz
}
-// UnmarshalHeader returns a Header interface from raw proto encoded header bytes.
+// UnmarshalClientMessage returns a ClientMessage interface from raw proto encoded header bytes.
// An error is returned upon decoding failure.
-func UnmarshalHeader(cdc codec.BinaryCodec, bz []byte) (exported.Header, error) {
- var header exported.Header
- if err := cdc.UnmarshalInterface(bz, &header); err != nil {
+func UnmarshalClientMessage(cdc codec.BinaryCodec, bz []byte) (exported.ClientMessage, error) {
+ var clientMessage exported.ClientMessage
+ if err := cdc.UnmarshalInterface(bz, &clientMessage); err != nil {
return nil, err
}
- return header, nil
+ return clientMessage, nil
}
diff --git a/modules/core/02-client/types/encoding_test.go b/modules/core/02-client/types/encoding_test.go
index 3aa01c09708..7142153ff7e 100644
--- a/modules/core/02-client/types/encoding_test.go
+++ b/modules/core/02-client/types/encoding_test.go
@@ -2,27 +2,27 @@ package types_test
import (
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
)
func (suite *TypesTestSuite) TestMarshalHeader() {
cdc := suite.chainA.App.AppCodec()
- h := &ibctmtypes.Header{
+ h := &ibctm.Header{
TrustedHeight: types.NewHeight(4, 100),
}
// marshal header
- bz, err := types.MarshalHeader(cdc, h)
+ bz, err := types.MarshalClientMessage(cdc, h)
suite.Require().NoError(err)
// unmarshal header
- newHeader, err := types.UnmarshalHeader(cdc, bz)
+ newHeader, err := types.UnmarshalClientMessage(cdc, bz)
suite.Require().NoError(err)
suite.Require().Equal(h, newHeader)
// use invalid bytes
- invalidHeader, err := types.UnmarshalHeader(cdc, []byte("invalid bytes"))
+ invalidHeader, err := types.UnmarshalClientMessage(cdc, []byte("invalid bytes"))
suite.Require().Error(err)
suite.Require().Nil(invalidHeader)
}
diff --git a/modules/core/02-client/types/errors.go b/modules/core/02-client/types/errors.go
index c40bae878cc..0c2bd65f339 100644
--- a/modules/core/02-client/types/errors.go
+++ b/modules/core/02-client/types/errors.go
@@ -33,5 +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")
+ ErrClientNotActive = sdkerrors.Register(SubModuleName, 29, "client state is not active")
)
diff --git a/modules/core/02-client/types/events.go b/modules/core/02-client/types/events.go
index 78ed0028e65..4e0bd1ba96f 100644
--- a/modules/core/02-client/types/events.go
+++ b/modules/core/02-client/types/events.go
@@ -12,9 +12,11 @@ const (
AttributeKeySubjectClientID = "subject_client_id"
AttributeKeyClientType = "client_type"
AttributeKeyConsensusHeight = "consensus_height"
+ AttributeKeyConsensusHeights = "consensus_heights"
AttributeKeyHeader = "header"
+ AttributeKeyUpgradeStore = "upgrade_store"
+ AttributeKeyUpgradePlanHeight = "upgrade_plan_height"
AttributeKeyUpgradePlanTitle = "title"
- AttributeKeyUpgradePlanHeight = "height"
)
// IBC client events vars
@@ -24,6 +26,7 @@ var (
EventTypeUpgradeClient = "upgrade_client"
EventTypeSubmitMisbehaviour = "client_misbehaviour"
EventTypeUpdateClientProposal = "update_client_proposal"
+ EventTypeUpgradeChain = "upgrade_chain"
EventTypeUpgradeClientProposal = "upgrade_client_proposal"
AttributeValueCategory = fmt.Sprintf("%s_%s", host.ModuleName, SubModuleName)
diff --git a/modules/core/02-client/types/genesis.go b/modules/core/02-client/types/genesis.go
index 9d12b224765..784bae42f79 100644
--- a/modules/core/02-client/types/genesis.go
+++ b/modules/core/02-client/types/genesis.go
@@ -200,10 +200,6 @@ func (gs GenesisState) Validate() error {
}
- if gs.CreateLocalhost && !gs.Params.IsAllowedClient(exported.Localhost) {
- return fmt.Errorf("localhost client is not registered on the allowlist")
- }
-
if maxSequence != 0 && maxSequence >= gs.NextClientSequence {
return fmt.Errorf("next client identifier sequence %d must be greater than the maximum sequence used in the provided client identifiers %d", gs.NextClientSequence, maxSequence)
}
diff --git a/modules/core/02-client/types/genesis_test.go b/modules/core/02-client/types/genesis_test.go
index 2fba3a19647..08d55606c61 100644
--- a/modules/core/02-client/types/genesis_test.go
+++ b/modules/core/02-client/types/genesis_test.go
@@ -9,23 +9,23 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
- localhosttypes "github.com/cosmos/ibc-go/v5/modules/light-clients/09-localhost/types"
+ solomachinetypes "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
ibctestingmock "github.com/cosmos/ibc-go/v5/testing/mock"
)
const (
- chainID = "chainID"
- tmClientID0 = "07-tendermint-0"
- tmClientID1 = "07-tendermint-1"
- invalidClientID = "myclient-0"
- clientID = tmClientID0
+ tmClientID0 = "07-tendermint-0"
+ tmClientID1 = "07-tendermint-1"
+ invalidClientID = "myclient-0"
+ soloMachineClientID = "06-solomachine-0"
+ clientID = tmClientID0
height = 10
)
-var clientHeight = types.NewHeight(0, 10)
+var clientHeight = types.NewHeight(1, 10)
func (suite *TypesTestSuite) TestMarshalGenesisState() {
cdc := suite.chainA.App.AppCodec()
@@ -58,8 +58,8 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
signers := make(map[string]tmtypes.PrivValidator)
signers[val.Address.String()] = privVal
- heightMinus1 := types.NewHeight(0, height-1)
- header := suite.chainA.CreateTMClientHeader(chainID, int64(clientHeight.RevisionHeight), heightMinus1, now, valSet, valSet, valSet, signers)
+ heightMinus1 := types.NewHeight(1, height-1)
+ header := suite.chainA.CreateTMClientHeader(suite.chainA.ChainID, int64(clientHeight.RevisionHeight), heightMinus1, now, valSet, valSet, valSet, signers)
testCases := []struct {
name string
@@ -76,10 +76,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
- tmClientID0, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ),
- types.NewIdentifiedClientState(
- exported.Localhost+"-1", localhosttypes.NewClientState("chainID", clientHeight),
+ tmClientID0, ibctm.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
},
[]types.ClientConsensusStates{
@@ -88,7 +85,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
[]types.ConsensusStateWithHeight{
types.NewConsensusStateWithHeight(
header.GetHeight().(types.Height),
- ibctmtypes.NewConsensusState(
+ ibctm.NewConsensusState(
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash,
),
),
@@ -104,21 +101,35 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
},
),
},
- types.NewParams(exported.Tendermint, exported.Localhost),
+ types.NewParams(exported.Tendermint),
false,
2,
),
expPass: true,
},
{
- name: "invalid clientid",
+ name: "invalid client type",
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
- invalidClientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
+ soloMachineClientID, ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
+ types.NewIdentifiedClientState(tmClientID0, solomachinetypes.NewClientState(0, &solomachinetypes.ConsensusState{suite.solomachine.ConsensusState().PublicKey, suite.solomachine.Diversifier, suite.solomachine.Time}, false)),
+ },
+ nil,
+ nil,
+ types.NewParams(exported.Tendermint),
+ false,
+ 0,
+ ),
+ expPass: false,
+ },
+ {
+ name: "invalid clientid",
+ genState: types.NewGenesisState(
+ []types.IdentifiedClientState{
types.NewIdentifiedClientState(
- exported.Localhost, localhosttypes.NewClientState("chainID", clientHeight),
+ invalidClientID, ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
},
[]types.ClientConsensusStates{
@@ -127,7 +138,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
[]types.ConsensusStateWithHeight{
types.NewConsensusStateWithHeight(
header.GetHeight().(types.Height),
- ibctmtypes.NewConsensusState(
+ ibctm.NewConsensusState(
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash,
),
),
@@ -141,32 +152,12 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
),
expPass: false,
},
- {
- name: "invalid client",
- genState: types.NewGenesisState(
- []types.IdentifiedClientState{
- types.NewIdentifiedClientState(
- tmClientID0, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ),
- types.NewIdentifiedClientState(exported.Localhost, localhosttypes.NewClientState("chaindID", types.ZeroHeight())),
- },
- nil,
- nil,
- types.NewParams(exported.Tendermint),
- false,
- 0,
- ),
- expPass: false,
- },
{
name: "consensus state client id does not match client id in genesis clients",
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
- tmClientID0, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ),
- types.NewIdentifiedClientState(
- exported.Localhost, localhosttypes.NewClientState("chaindID", clientHeight),
+ tmClientID0, ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
},
[]types.ClientConsensusStates{
@@ -174,8 +165,8 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
tmClientID1,
[]types.ConsensusStateWithHeight{
types.NewConsensusStateWithHeight(
- types.NewHeight(0, 1),
- ibctmtypes.NewConsensusState(
+ types.NewHeight(1, 1),
+ ibctm.NewConsensusState(
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash,
),
),
@@ -194,10 +185,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
- tmClientID0, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ),
- types.NewIdentifiedClientState(
- exported.Localhost, localhosttypes.NewClientState("chaindID", clientHeight),
+ tmClientID0, ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
},
[]types.ClientConsensusStates{
@@ -206,7 +194,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
[]types.ConsensusStateWithHeight{
types.NewConsensusStateWithHeight(
types.ZeroHeight(),
- ibctmtypes.NewConsensusState(
+ ibctm.NewConsensusState(
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash,
),
),
@@ -225,10 +213,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
- tmClientID0, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ),
- types.NewIdentifiedClientState(
- exported.Localhost, localhosttypes.NewClientState("chaindID", clientHeight),
+ tmClientID0, ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
},
[]types.ClientConsensusStates{
@@ -236,8 +221,8 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
tmClientID0,
[]types.ConsensusStateWithHeight{
types.NewConsensusStateWithHeight(
- types.NewHeight(0, 1),
- ibctmtypes.NewConsensusState(
+ types.NewHeight(1, 1),
+ ibctm.NewConsensusState(
time.Time{}, commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash,
),
),
@@ -256,10 +241,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
- tmClientID0, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ),
- types.NewIdentifiedClientState(
- exported.Localhost, localhosttypes.NewClientState("chainID", clientHeight),
+ tmClientID0, ibctm.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
},
[]types.ClientConsensusStates{
@@ -268,7 +250,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
[]types.ConsensusStateWithHeight{
types.NewConsensusStateWithHeight(
header.GetHeight().(types.Height),
- ibctmtypes.NewConsensusState(
+ ibctm.NewConsensusState(
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash,
),
),
@@ -287,10 +269,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
- clientID, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ),
- types.NewIdentifiedClientState(
- exported.Localhost, localhosttypes.NewClientState("chainID", clientHeight),
+ clientID, ibctm.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
},
[]types.ClientConsensusStates{
@@ -299,7 +278,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
[]types.ConsensusStateWithHeight{
types.NewConsensusStateWithHeight(
header.GetHeight().(types.Height),
- ibctmtypes.NewConsensusState(
+ ibctm.NewConsensusState(
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash,
),
),
@@ -315,7 +294,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
},
),
},
- types.NewParams(exported.Tendermint, exported.Localhost),
+ types.NewParams(exported.Tendermint),
false,
0,
),
@@ -326,7 +305,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
- clientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
+ clientID, ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
},
[]types.ClientConsensusStates{
@@ -335,7 +314,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
[]types.ConsensusStateWithHeight{
types.NewConsensusStateWithHeight(
header.GetHeight().(types.Height),
- ibctmtypes.NewConsensusState(
+ ibctm.NewConsensusState(
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash,
),
),
@@ -361,10 +340,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
- tmClientID0, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ),
- types.NewIdentifiedClientState(
- exported.Localhost, localhosttypes.NewClientState("chainID", clientHeight),
+ tmClientID0, ibctm.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
},
[]types.ClientConsensusStates{
@@ -373,7 +349,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
[]types.ConsensusStateWithHeight{
types.NewConsensusStateWithHeight(
header.GetHeight().(types.Height),
- ibctmtypes.NewConsensusState(
+ ibctm.NewConsensusState(
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash,
),
),
@@ -392,10 +368,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
- tmClientID0, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ),
- types.NewIdentifiedClientState(
- exported.Localhost, localhosttypes.NewClientState("chainID", clientHeight),
+ tmClientID0, ibctm.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
},
[]types.ClientConsensusStates{
@@ -404,7 +377,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
[]types.ConsensusStateWithHeight{
types.NewConsensusStateWithHeight(
header.GetHeight().(types.Height),
- ibctmtypes.NewConsensusState(
+ ibctm.NewConsensusState(
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash,
),
),
@@ -413,51 +386,20 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
},
nil,
types.NewParams(" "),
- true,
+ false,
0,
),
expPass: false,
},
- {
- name: "localhost client not registered on allowlist",
- genState: types.NewGenesisState(
- []types.IdentifiedClientState{
- types.NewIdentifiedClientState(
- tmClientID1, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ),
- types.NewIdentifiedClientState(
- exported.Localhost+"-0", localhosttypes.NewClientState("chainID", clientHeight),
- ),
- },
- []types.ClientConsensusStates{
- types.NewClientConsensusStates(
- tmClientID1,
- []types.ConsensusStateWithHeight{
- types.NewConsensusStateWithHeight(
- header.GetHeight().(types.Height),
- ibctmtypes.NewConsensusState(
- header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash,
- ),
- ),
- },
- ),
- },
- nil,
- types.NewParams(exported.Tendermint),
- true,
- 2,
- ),
- expPass: false,
- },
{
name: "next sequence too small",
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
- tmClientID0, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
+ tmClientID0, ibctm.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
types.NewIdentifiedClientState(
- exported.Localhost+"-1", localhosttypes.NewClientState("chainID", clientHeight),
+ tmClientID1, ibctm.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
},
[]types.ClientConsensusStates{
@@ -466,7 +408,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
[]types.ConsensusStateWithHeight{
types.NewConsensusStateWithHeight(
header.GetHeight().(types.Height),
- ibctmtypes.NewConsensusState(
+ ibctm.NewConsensusState(
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash,
),
),
@@ -474,7 +416,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
),
},
nil,
- types.NewParams(exported.Tendermint, exported.Localhost),
+ types.NewParams(exported.Tendermint),
false,
0,
),
@@ -485,10 +427,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
- "my-client", ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ),
- types.NewIdentifiedClientState(
- exported.Localhost+"-1", localhosttypes.NewClientState("chainID", clientHeight),
+ "my-client", ibctm.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
},
[]types.ClientConsensusStates{
@@ -497,7 +436,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
[]types.ConsensusStateWithHeight{
types.NewConsensusStateWithHeight(
header.GetHeight().(types.Height),
- ibctmtypes.NewConsensusState(
+ ibctm.NewConsensusState(
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash,
),
),
@@ -505,7 +444,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
),
},
nil,
- types.NewParams(exported.Tendermint, exported.Localhost),
+ types.NewParams(exported.Tendermint),
false,
5,
),
@@ -514,18 +453,14 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
{
name: "consensus state different than client state type",
genState: types.NewGenesisState(
- []types.IdentifiedClientState{
- types.NewIdentifiedClientState(
- exported.Localhost+"-1", localhosttypes.NewClientState("chainID", clientHeight),
- ),
- },
+ []types.IdentifiedClientState{},
[]types.ClientConsensusStates{
types.NewClientConsensusStates(
- exported.Localhost+"-1",
+ tmClientID0,
[]types.ConsensusStateWithHeight{
types.NewConsensusStateWithHeight(
header.GetHeight().(types.Height),
- ibctmtypes.NewConsensusState(
+ ibctm.NewConsensusState(
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash,
),
),
@@ -533,7 +468,7 @@ func (suite *TypesTestSuite) TestValidateGenesis() {
),
},
nil,
- types.NewParams(exported.Tendermint, exported.Localhost),
+ types.NewParams(exported.Tendermint),
false,
5,
),
diff --git a/modules/core/02-client/types/msgs.go b/modules/core/02-client/types/msgs.go
index da1ef19275c..8e339199923 100644
--- a/modules/core/02-client/types/msgs.go
+++ b/modules/core/02-client/types/msgs.go
@@ -65,9 +65,6 @@ func (msg MsgCreateClient) ValidateBasic() error {
if err := clientState.Validate(); err != nil {
return err
}
- if clientState.ClientType() == exported.Localhost {
- return sdkerrors.Wrap(ErrInvalidClient, "localhost client can only be created on chain initialization")
- }
consensusState, err := UnpackConsensusState(msg.ConsensusState)
if err != nil {
return err
@@ -105,16 +102,16 @@ func (msg MsgCreateClient) UnpackInterfaces(unpacker codectypes.AnyUnpacker) err
// NewMsgUpdateClient creates a new MsgUpdateClient instance
//
//nolint:interfacer
-func NewMsgUpdateClient(id string, header exported.Header, signer string) (*MsgUpdateClient, error) {
- anyHeader, err := PackHeader(header)
+func NewMsgUpdateClient(id string, clientMsg exported.ClientMessage, signer string) (*MsgUpdateClient, error) {
+ anyClientMsg, err := PackClientMessage(clientMsg)
if err != nil {
return nil, err
}
return &MsgUpdateClient{
- ClientId: id,
- Header: anyHeader,
- Signer: signer,
+ ClientId: id,
+ ClientMessage: anyClientMsg,
+ Signer: signer,
}, nil
}
@@ -124,16 +121,13 @@ func (msg MsgUpdateClient) ValidateBasic() error {
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err)
}
- header, err := UnpackHeader(msg.Header)
+ clientMsg, err := UnpackClientMessage(msg.ClientMessage)
if err != nil {
return err
}
- if err := header.ValidateBasic(); err != nil {
+ if err := clientMsg.ValidateBasic(); err != nil {
return err
}
- if msg.ClientId == exported.Localhost {
- return sdkerrors.Wrap(ErrInvalidClient, "localhost client is only updated on ABCI BeginBlock")
- }
return host.ClientIdentifierValidator(msg.ClientId)
}
@@ -148,8 +142,8 @@ func (msg MsgUpdateClient) GetSigners() []sdk.AccAddress {
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (msg MsgUpdateClient) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
- var header exported.Header
- return unpacker.UnpackAny(msg.Header, &header)
+ var clientMsg exported.ClientMessage
+ return unpacker.UnpackAny(msg.ClientMessage, &clientMsg)
}
// NewMsgUpgradeClient creates a new MsgUpgradeClient instance
@@ -233,8 +227,8 @@ func (msg MsgUpgradeClient) UnpackInterfaces(unpacker codectypes.AnyUnpacker) er
// NewMsgSubmitMisbehaviour creates a new MsgSubmitMisbehaviour instance.
//
//nolint:interfacer
-func NewMsgSubmitMisbehaviour(clientID string, misbehaviour exported.Misbehaviour, signer string) (*MsgSubmitMisbehaviour, error) {
- anyMisbehaviour, err := PackMisbehaviour(misbehaviour)
+func NewMsgSubmitMisbehaviour(clientID string, misbehaviour exported.ClientMessage, signer string) (*MsgSubmitMisbehaviour, error) {
+ anyMisbehaviour, err := PackClientMessage(misbehaviour)
if err != nil {
return nil, err
}
@@ -252,20 +246,13 @@ func (msg MsgSubmitMisbehaviour) ValidateBasic() error {
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err)
}
- misbehaviour, err := UnpackMisbehaviour(msg.Misbehaviour)
+ misbehaviour, err := UnpackClientMessage(msg.Misbehaviour)
if err != nil {
return err
}
if err := misbehaviour.ValidateBasic(); err != nil {
return err
}
- if misbehaviour.GetClientID() != msg.ClientId {
- return sdkerrors.Wrapf(
- ErrInvalidMisbehaviour,
- "misbehaviour client-id doesn't match client-id from message (%s ≠ %s)",
- misbehaviour.GetClientID(), msg.ClientId,
- )
- }
return host.ClientIdentifierValidator(msg.ClientId)
}
@@ -281,6 +268,6 @@ func (msg MsgSubmitMisbehaviour) GetSigners() []sdk.AccAddress {
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (msg MsgSubmitMisbehaviour) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
- var misbehaviour exported.Misbehaviour
+ var misbehaviour exported.ClientMessage
return unpacker.UnpackAny(msg.Misbehaviour, &misbehaviour)
}
diff --git a/modules/core/02-client/types/msgs_test.go b/modules/core/02-client/types/msgs_test.go
index 3ea81a9d0a7..b42445c030c 100644
--- a/modules/core/02-client/types/msgs_test.go
+++ b/modules/core/02-client/types/msgs_test.go
@@ -9,9 +9,8 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
- solomachinetypes "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ solomachinetypes "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -20,14 +19,16 @@ type TypesTestSuite struct {
coordinator *ibctesting.Coordinator
- chainA *ibctesting.TestChain
- chainB *ibctesting.TestChain
+ chainA *ibctesting.TestChain
+ chainB *ibctesting.TestChain
+ solomachine *ibctesting.Solomachine
}
func (suite *TypesTestSuite) SetupTest() {
suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2)
suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(1))
suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(2))
+ suite.solomachine = ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachinesingle", "testing", 1)
}
func TestTypesTestSuite(t *testing.T) {
@@ -55,7 +56,7 @@ func (suite *TypesTestSuite) TestMarshalMsgCreateClient() {
},
{
"tendermint client", func() {
- tendermintClient := ibctmtypes.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
+ tendermintClient := ibctm.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
msg, err = types.NewMsgCreateClient(tendermintClient, suite.chainA.CurrentTMClientHeader().ConsensusState(), suite.chainA.SenderAccount.GetAddress().String())
suite.Require().NoError(err)
},
@@ -100,7 +101,7 @@ func (suite *TypesTestSuite) TestMsgCreateClient_ValidateBasic() {
{
"valid - tendermint client",
func() {
- tendermintClient := ibctmtypes.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
+ tendermintClient := ibctm.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
msg, err = types.NewMsgCreateClient(tendermintClient, suite.chainA.CurrentTMClientHeader().ConsensusState(), suite.chainA.SenderAccount.GetAddress().String())
suite.Require().NoError(err)
},
@@ -109,7 +110,7 @@ func (suite *TypesTestSuite) TestMsgCreateClient_ValidateBasic() {
{
"invalid tendermint client",
func() {
- msg, err = types.NewMsgCreateClient(&ibctmtypes.ClientState{}, suite.chainA.CurrentTMClientHeader().ConsensusState(), suite.chainA.SenderAccount.GetAddress().String())
+ msg, err = types.NewMsgCreateClient(&ibctm.ClientState{}, suite.chainA.CurrentTMClientHeader().ConsensusState(), suite.chainA.SenderAccount.GetAddress().String())
suite.Require().NoError(err)
},
false,
@@ -124,7 +125,7 @@ func (suite *TypesTestSuite) TestMsgCreateClient_ValidateBasic() {
{
"failed to unpack consensus state",
func() {
- tendermintClient := ibctmtypes.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
+ tendermintClient := ibctm.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
msg, err = types.NewMsgCreateClient(tendermintClient, suite.chainA.CurrentTMClientHeader().ConsensusState(), suite.chainA.SenderAccount.GetAddress().String())
suite.Require().NoError(err)
msg.ConsensusState = nil
@@ -168,7 +169,7 @@ func (suite *TypesTestSuite) TestMsgCreateClient_ValidateBasic() {
{
"invalid - client state and consensus state client types do not match",
func() {
- tendermintClient := ibctmtypes.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
+ tendermintClient := ibctm.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2)
msg, err = types.NewMsgCreateClient(tendermintClient, soloMachine.ConsensusState(), suite.chainA.SenderAccount.GetAddress().String())
suite.Require().NoError(err)
@@ -203,7 +204,7 @@ func (suite *TypesTestSuite) TestMarshalMsgUpdateClient() {
{
"solo machine client", func() {
soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2)
- msg, err = types.NewMsgUpdateClient(soloMachine.ClientID, soloMachine.CreateHeader(), suite.chainA.SenderAccount.GetAddress().String())
+ msg, err = types.NewMsgUpdateClient(soloMachine.ClientID, soloMachine.CreateHeader(soloMachine.Diversifier), suite.chainA.SenderAccount.GetAddress().String())
suite.Require().NoError(err)
},
},
@@ -268,7 +269,7 @@ func (suite *TypesTestSuite) TestMsgUpdateClient_ValidateBasic() {
{
"invalid tendermint header",
func() {
- msg, err = types.NewMsgUpdateClient("tendermint", &ibctmtypes.Header{}, suite.chainA.SenderAccount.GetAddress().String())
+ msg, err = types.NewMsgUpdateClient("tendermint", &ibctm.Header{}, suite.chainA.SenderAccount.GetAddress().String())
suite.Require().NoError(err)
},
false,
@@ -276,7 +277,7 @@ func (suite *TypesTestSuite) TestMsgUpdateClient_ValidateBasic() {
{
"failed to unpack header",
func() {
- msg.Header = nil
+ msg.ClientMessage = nil
},
false,
},
@@ -291,7 +292,8 @@ func (suite *TypesTestSuite) TestMsgUpdateClient_ValidateBasic() {
"valid - solomachine header",
func() {
soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2)
- msg, err = types.NewMsgUpdateClient(soloMachine.ClientID, soloMachine.CreateHeader(), suite.chainA.SenderAccount.GetAddress().String())
+ msg, err = types.NewMsgUpdateClient(soloMachine.ClientID, soloMachine.CreateHeader(soloMachine.Diversifier), suite.chainA.SenderAccount.GetAddress().String())
+
suite.Require().NoError(err)
},
true,
@@ -304,14 +306,6 @@ func (suite *TypesTestSuite) TestMsgUpdateClient_ValidateBasic() {
},
false,
},
- {
- "unsupported - localhost",
- func() {
- msg, err = types.NewMsgUpdateClient(exported.Localhost, suite.chainA.CurrentTMClientHeader(), suite.chainA.SenderAccount.GetAddress().String())
- suite.Require().NoError(err)
- },
- false,
- },
}
for _, tc := range cases {
@@ -338,8 +332,8 @@ func (suite *TypesTestSuite) TestMarshalMsgUpgradeClient() {
{
"client upgrades to new tendermint client",
func() {
- tendermintClient := ibctmtypes.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
- tendermintConsState := &ibctmtypes.ConsensusState{NextValidatorsHash: []byte("nextValsHash")}
+ tendermintClient := ibctm.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
+ tendermintConsState := &ibctm.ConsensusState{NextValidatorsHash: []byte("nextValsHash")}
msg, err = types.NewMsgUpgradeClient("clientid", tendermintClient, tendermintConsState, []byte("proofUpgradeClient"), []byte("proofUpgradeConsState"), suite.chainA.SenderAccount.GetAddress().String())
suite.Require().NoError(err)
},
@@ -451,8 +445,8 @@ func (suite *TypesTestSuite) TestMsgUpgradeClient_ValidateBasic() {
for _, tc := range cases {
tc := tc
- clientState := ibctmtypes.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
- consState := &ibctmtypes.ConsensusState{NextValidatorsHash: []byte("nextValsHash")}
+ clientState := ibctm.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
+ consState := &ibctm.ConsensusState{NextValidatorsHash: []byte("nextValsHash")}
msg, err := types.NewMsgUpgradeClient("testclientid", clientState, consState, []byte("proofUpgradeClient"), []byte("proofUpgradeConsState"), suite.chainA.SenderAccount.GetAddress().String())
suite.Require().NoError(err)
@@ -492,7 +486,7 @@ func (suite *TypesTestSuite) TestMarshalMsgSubmitMisbehaviour() {
header1 := suite.chainA.CreateTMClientHeader(suite.chainA.ChainID, int64(height.RevisionHeight), heightMinus1, suite.chainA.CurrentHeader.Time, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers)
header2 := suite.chainA.CreateTMClientHeader(suite.chainA.ChainID, int64(height.RevisionHeight), heightMinus1, suite.chainA.CurrentHeader.Time.Add(time.Minute), suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers)
- misbehaviour := ibctmtypes.NewMisbehaviour("tendermint", header1, header2)
+ misbehaviour := ibctm.NewMisbehaviour("tendermint", header1, header2)
msg, err = types.NewMsgSubmitMisbehaviour("tendermint", misbehaviour, suite.chainA.SenderAccount.GetAddress().String())
suite.Require().NoError(err)
},
@@ -549,7 +543,7 @@ func (suite *TypesTestSuite) TestMsgSubmitMisbehaviour_ValidateBasic() {
header1 := suite.chainA.CreateTMClientHeader(suite.chainA.ChainID, int64(height.RevisionHeight), heightMinus1, suite.chainA.CurrentHeader.Time, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers)
header2 := suite.chainA.CreateTMClientHeader(suite.chainA.ChainID, int64(height.RevisionHeight), heightMinus1, suite.chainA.CurrentHeader.Time.Add(time.Minute), suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers)
- misbehaviour := ibctmtypes.NewMisbehaviour("tendermint", header1, header2)
+ misbehaviour := ibctm.NewMisbehaviour("tendermint", header1, header2)
msg, err = types.NewMsgSubmitMisbehaviour("tendermint", misbehaviour, suite.chainA.SenderAccount.GetAddress().String())
suite.Require().NoError(err)
},
@@ -558,7 +552,7 @@ func (suite *TypesTestSuite) TestMsgSubmitMisbehaviour_ValidateBasic() {
{
"invalid tendermint misbehaviour",
func() {
- msg, err = types.NewMsgSubmitMisbehaviour("tendermint", &ibctmtypes.Misbehaviour{}, suite.chainA.SenderAccount.GetAddress().String())
+ msg, err = types.NewMsgSubmitMisbehaviour("tendermint", &ibctm.Misbehaviour{}, suite.chainA.SenderAccount.GetAddress().String())
suite.Require().NoError(err)
},
false,
diff --git a/modules/core/02-client/types/proposal.go b/modules/core/02-client/types/proposal.go
index 37b4cee74e2..4bc7a84a810 100644
--- a/modules/core/02-client/types/proposal.go
+++ b/modules/core/02-client/types/proposal.go
@@ -2,6 +2,7 @@ package types
import (
"fmt"
+ "reflect"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
@@ -111,11 +112,15 @@ func (up *UpgradeProposal) ValidateBasic() error {
return sdkerrors.Wrap(ErrInvalidUpgradeProposal, "upgraded client state cannot be nil")
}
- _, err := UnpackClientState(up.UpgradedClientState)
+ clientState, err := UnpackClientState(up.UpgradedClientState)
if err != nil {
return sdkerrors.Wrap(err, "failed to unpack upgraded client state")
}
+ if !reflect.DeepEqual(clientState, clientState.ZeroCustomFields()) {
+ return sdkerrors.Wrap(ErrInvalidUpgradeProposal, "upgraded client state is not zeroed out")
+ }
+
return nil
}
diff --git a/modules/core/02-client/types/proposal_test.go b/modules/core/02-client/types/proposal_test.go
index 6b856211901..2b1725248e0 100644
--- a/modules/core/02-client/types/proposal_test.go
+++ b/modules/core/02-client/types/proposal_test.go
@@ -9,7 +9,7 @@ import (
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -109,20 +109,31 @@ func (suite *TypesTestSuite) TestUpgradeProposalValidateBasic() {
}{
{
"success", func() {
- proposal, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, plan, cs)
+ proposal, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, plan, cs.ZeroCustomFields())
suite.Require().NoError(err)
}, true,
},
{
"fails validate abstract - empty title", func() {
- proposal, err = types.NewUpgradeProposal("", ibctesting.Description, plan, cs)
+ proposal, err = types.NewUpgradeProposal("", ibctesting.Description, plan, cs.ZeroCustomFields())
+ suite.Require().NoError(err)
+
+ }, false,
+ },
+ {
+ "non zeroed fields", func() {
+ proposal, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, plan, &ibctm.ClientState{
+ FrozenHeight: types.Height{
+ RevisionHeight: 10,
+ },
+ })
suite.Require().NoError(err)
}, false,
},
{
"plan height is zero", func() {
invalidPlan := upgradetypes.Plan{Name: "ibc upgrade", Height: 0}
- proposal, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, invalidPlan, cs)
+ proposal, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, invalidPlan, cs.ZeroCustomFields())
suite.Require().NoError(err)
}, false,
},
@@ -138,7 +149,7 @@ func (suite *TypesTestSuite) TestUpgradeProposalValidateBasic() {
},
{
"failed to unpack client state", func() {
- any, err := types.PackConsensusState(&ibctmtypes.ConsensusState{})
+ any, err := types.PackConsensusState(&ibctm.ConsensusState{})
suite.Require().NoError(err)
proposal = &types.UpgradeProposal{
@@ -173,7 +184,7 @@ func (suite *TypesTestSuite) TestMarshalUpgradeProposal() {
Name: "upgrade ibc",
Height: 1000,
}
- content, err := types.NewUpgradeProposal("title", "description", plan, &ibctmtypes.ClientState{})
+ content, err := types.NewUpgradeProposal("title", "description", plan, &ibctm.ClientState{})
suite.Require().NoError(err)
up, ok := content.(*types.UpgradeProposal)
@@ -183,7 +194,7 @@ func (suite *TypesTestSuite) TestMarshalUpgradeProposal() {
ir := codectypes.NewInterfaceRegistry()
types.RegisterInterfaces(ir)
govtypes.RegisterInterfaces(ir)
- ibctmtypes.RegisterInterfaces(ir)
+ ibctm.RegisterInterfaces(ir)
cdc := codec.NewProtoCodec(ir)
// marshal message
@@ -207,10 +218,10 @@ func (suite *TypesTestSuite) TestUpgradeString() {
Height: 1000,
}
- proposal, err := types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, plan, &ibctmtypes.ClientState{})
+ proposal, err := types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, plan, &ibctm.ClientState{})
suite.Require().NoError(err)
- expect := fmt.Sprintf("IBC Upgrade Proposal\n Title: title\n Description: description\n Upgrade Plan\n Name: ibc upgrade\n height: 1000\n Info: https://foo.bar/baz.\n Upgraded IBC Client: %s", &ibctmtypes.ClientState{})
+ expect := fmt.Sprintf("IBC Upgrade Proposal\n Title: title\n Description: description\n Upgrade Plan\n Name: ibc upgrade\n height: 1000\n Info: https://foo.bar/baz.\n Upgraded IBC Client: %s", &ibctm.ClientState{})
suite.Require().Equal(expect, proposal.String())
}
diff --git a/modules/core/02-client/types/tx.pb.go b/modules/core/02-client/types/tx.pb.go
index b2d823567cb..a9cf9917069 100644
--- a/modules/core/02-client/types/tx.pb.go
+++ b/modules/core/02-client/types/tx.pb.go
@@ -111,12 +111,12 @@ func (m *MsgCreateClientResponse) XXX_DiscardUnknown() {
var xxx_messageInfo_MsgCreateClientResponse proto.InternalMessageInfo
// MsgUpdateClient defines an sdk.Msg to update a IBC client state using
-// the given header.
+// the given client message.
type MsgUpdateClient struct {
// client unique identifier
ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"`
- // header to update the light client
- Header *types.Any `protobuf:"bytes,2,opt,name=header,proto3" json:"header,omitempty"`
+ // client message to update the light client
+ ClientMessage *types.Any `protobuf:"bytes,2,opt,name=client_message,json=clientMessage,proto3" json:"client_message,omitempty"`
// signer address
Signer string `protobuf:"bytes,3,opt,name=signer,proto3" json:"signer,omitempty"`
}
@@ -281,13 +281,14 @@ var xxx_messageInfo_MsgUpgradeClientResponse proto.InternalMessageInfo
// MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for
// light client misbehaviour.
+// Warning: DEPRECATED
type MsgSubmitMisbehaviour struct {
// client unique identifier
- ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"`
+ ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` // Deprecated: Do not use.
// misbehaviour used for freezing the light client
- Misbehaviour *types.Any `protobuf:"bytes,2,opt,name=misbehaviour,proto3" json:"misbehaviour,omitempty"`
+ Misbehaviour *types.Any `protobuf:"bytes,2,opt,name=misbehaviour,proto3" json:"misbehaviour,omitempty"` // Deprecated: Do not use.
// signer address
- Signer string `protobuf:"bytes,3,opt,name=signer,proto3" json:"signer,omitempty"`
+ Signer string `protobuf:"bytes,3,opt,name=signer,proto3" json:"signer,omitempty"` // Deprecated: Do not use.
}
func (m *MsgSubmitMisbehaviour) Reset() { *m = MsgSubmitMisbehaviour{} }
@@ -375,45 +376,46 @@ func init() {
func init() { proto.RegisterFile("ibc/core/client/v1/tx.proto", fileDescriptor_cb5dc4651eb49a04) }
var fileDescriptor_cb5dc4651eb49a04 = []byte{
- // 602 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0x3f, 0x6f, 0xd3, 0x4e,
- 0x18, 0x8e, 0x9b, 0xdf, 0x2f, 0x6a, 0xae, 0x81, 0x56, 0x26, 0xb4, 0xa9, 0xab, 0xda, 0x91, 0xe9,
- 0x10, 0x44, 0x7b, 0x47, 0x82, 0x90, 0xaa, 0x6e, 0xa4, 0x13, 0x43, 0x24, 0x70, 0xc5, 0x00, 0x4b,
- 0xf0, 0x9f, 0xeb, 0xe5, 0x44, 0xec, 0x8b, 0x7c, 0x76, 0x44, 0xbe, 0x01, 0x23, 0x03, 0x1f, 0xa0,
- 0x62, 0xe0, 0xb3, 0x30, 0x76, 0x60, 0x60, 0x8a, 0xaa, 0x64, 0x61, 0xce, 0x27, 0x40, 0xf1, 0x39,
- 0x21, 0x76, 0xe3, 0x28, 0xe2, 0xcf, 0xe6, 0xf3, 0xfb, 0xdc, 0xf3, 0xbc, 0x8f, 0x9f, 0xf7, 0x7c,
- 0xe0, 0x80, 0x5a, 0x36, 0xb2, 0x99, 0x8f, 0x91, 0xdd, 0xa5, 0xd8, 0x0b, 0x50, 0xbf, 0x8e, 0x82,
- 0xf7, 0xb0, 0xe7, 0xb3, 0x80, 0xc9, 0x32, 0xb5, 0x6c, 0x38, 0x2d, 0x42, 0x51, 0x84, 0xfd, 0xba,
- 0x52, 0x26, 0x8c, 0xb0, 0xa8, 0x8c, 0xa6, 0x4f, 0x02, 0xa9, 0xec, 0x13, 0xc6, 0x48, 0x17, 0xa3,
- 0x68, 0x65, 0x85, 0x97, 0xc8, 0xf4, 0x06, 0xa2, 0xa4, 0xdf, 0x48, 0x60, 0xbb, 0xc5, 0xc9, 0xb9,
- 0x8f, 0xcd, 0x00, 0x9f, 0x47, 0x3c, 0xf2, 0x0b, 0x50, 0x12, 0x8c, 0x6d, 0x1e, 0x98, 0x01, 0xae,
- 0x48, 0x55, 0xa9, 0xb6, 0xd5, 0x28, 0x43, 0xc1, 0x02, 0x67, 0x2c, 0xf0, 0x99, 0x37, 0x68, 0xee,
- 0x4d, 0x86, 0xda, 0xbd, 0x81, 0xe9, 0x76, 0xcf, 0xf4, 0xc5, 0x3d, 0xba, 0xb1, 0x25, 0x96, 0x17,
- 0xd3, 0x95, 0xfc, 0x1a, 0x6c, 0xdb, 0xcc, 0xe3, 0xd8, 0xe3, 0x21, 0x8f, 0x49, 0x37, 0x56, 0x90,
- 0x2a, 0x93, 0xa1, 0xb6, 0x1b, 0x93, 0x26, 0xb7, 0xe9, 0xc6, 0xdd, 0xf9, 0x1b, 0x41, 0xbd, 0x0b,
- 0x0a, 0x9c, 0x12, 0x0f, 0xfb, 0x95, 0x7c, 0x55, 0xaa, 0x15, 0x8d, 0x78, 0x75, 0xb6, 0xf9, 0xe1,
- 0x4a, 0xcb, 0xfd, 0xb8, 0xd2, 0x72, 0xfa, 0x3e, 0xd8, 0x4b, 0x39, 0x34, 0x30, 0xef, 0x4d, 0x59,
- 0xf4, 0x4f, 0xc2, 0xfd, 0xab, 0x9e, 0xf3, 0xcb, 0x7d, 0x1d, 0x14, 0x63, 0x27, 0xd4, 0x89, 0xac,
- 0x17, 0x9b, 0xe5, 0xc9, 0x50, 0xdb, 0x49, 0x98, 0xa4, 0x8e, 0x6e, 0x6c, 0x8a, 0xe7, 0xe7, 0x8e,
- 0x7c, 0x0c, 0x0a, 0x1d, 0x6c, 0x3a, 0xd8, 0x5f, 0xe5, 0xca, 0x88, 0x31, 0x6b, 0x77, 0xbc, 0xd8,
- 0xd5, 0xbc, 0xe3, 0x6f, 0x79, 0xb0, 0x13, 0xd5, 0x88, 0x6f, 0x3a, 0x7f, 0xd0, 0x72, 0x3a, 0xe3,
- 0x8d, 0x7f, 0x91, 0x71, 0xfe, 0x2f, 0x65, 0xfc, 0x12, 0x94, 0x7b, 0x3e, 0x63, 0x97, 0xed, 0x50,
- 0xd8, 0x6e, 0x0b, 0xdd, 0xca, 0x7f, 0x55, 0xa9, 0x56, 0x6a, 0x6a, 0x93, 0xa1, 0x76, 0x20, 0x98,
- 0x96, 0xa1, 0x74, 0x43, 0x8e, 0x5e, 0x27, 0x3f, 0xd9, 0x3b, 0x70, 0x98, 0x02, 0xa7, 0x7a, 0xff,
- 0x3f, 0xe2, 0xae, 0x4d, 0x86, 0xda, 0xd1, 0x52, 0xee, 0x74, 0xcf, 0x4a, 0x42, 0x24, 0x6b, 0x46,
- 0x0b, 0x19, 0x89, 0x2b, 0xa0, 0x92, 0x4e, 0x75, 0x1e, 0xf9, 0x17, 0x09, 0xdc, 0x6f, 0x71, 0x72,
- 0x11, 0x5a, 0x2e, 0x0d, 0x5a, 0x94, 0x5b, 0xb8, 0x63, 0xf6, 0x29, 0x0b, 0xfd, 0xdf, 0xc9, 0xfd,
- 0x14, 0x94, 0xdc, 0x05, 0x8a, 0x95, 0x03, 0x9b, 0x40, 0xae, 0x31, 0xb6, 0x1a, 0x38, 0x5c, 0xda,
- 0xe7, 0xcc, 0x49, 0xe3, 0x73, 0x1e, 0xe4, 0x5b, 0x9c, 0xc8, 0x6f, 0x41, 0x29, 0xf1, 0xc3, 0x79,
- 0x00, 0x6f, 0xff, 0xca, 0x60, 0xea, 0xcc, 0x2a, 0x8f, 0xd6, 0x00, 0xcd, 0x94, 0xa6, 0x0a, 0x89,
- 0x43, 0x9d, 0xa5, 0xb0, 0x08, 0xca, 0x54, 0x58, 0x76, 0x10, 0x65, 0x1b, 0xdc, 0x49, 0x4e, 0xd4,
- 0x51, 0xe6, 0xee, 0x05, 0x94, 0x72, 0xbc, 0x0e, 0x6a, 0x2e, 0xe2, 0x03, 0x79, 0x49, 0xec, 0x0f,
- 0x33, 0x38, 0x6e, 0x43, 0x95, 0xfa, 0xda, 0xd0, 0x99, 0x66, 0xd3, 0xf8, 0x3a, 0x52, 0xa5, 0xeb,
- 0x91, 0x2a, 0xdd, 0x8c, 0x54, 0xe9, 0xe3, 0x58, 0xcd, 0x5d, 0x8f, 0xd5, 0xdc, 0xf7, 0xb1, 0x9a,
- 0x7b, 0x73, 0x4a, 0x68, 0xd0, 0x09, 0x2d, 0x68, 0x33, 0x17, 0xd9, 0x8c, 0xbb, 0x8c, 0x23, 0x6a,
- 0xd9, 0x27, 0x84, 0xa1, 0xfe, 0x53, 0xe4, 0x32, 0x27, 0xec, 0x62, 0x2e, 0x6e, 0xab, 0xc7, 0x8d,
- 0x93, 0xf8, 0xc2, 0x0a, 0x06, 0x3d, 0xcc, 0xad, 0x42, 0x34, 0x57, 0x4f, 0x7e, 0x06, 0x00, 0x00,
- 0xff, 0xff, 0xaa, 0xe7, 0x1e, 0x7d, 0xd0, 0x06, 0x00, 0x00,
+ // 623 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xcd, 0x6e, 0xd3, 0x4c,
+ 0x14, 0x8d, 0x9b, 0xef, 0x8b, 0x9a, 0x69, 0xfa, 0x23, 0x13, 0x52, 0xd7, 0x55, 0xed, 0xc8, 0x74,
+ 0x11, 0x04, 0xb5, 0x49, 0x2a, 0x24, 0x54, 0xd8, 0x90, 0xae, 0x58, 0x44, 0x02, 0x57, 0x2c, 0x60,
+ 0x13, 0xfc, 0x33, 0x9d, 0x8e, 0x88, 0x3d, 0x91, 0xc7, 0x8e, 0xc8, 0x1b, 0xb0, 0xe4, 0x11, 0x2a,
+ 0x78, 0x01, 0x1e, 0x83, 0x65, 0x17, 0x2c, 0x58, 0x45, 0x55, 0xb2, 0x61, 0x9d, 0x27, 0x40, 0xf1,
+ 0x38, 0xc1, 0x76, 0xec, 0x28, 0x12, 0xb0, 0xf3, 0xcc, 0x3d, 0x73, 0xce, 0x3d, 0x3e, 0x77, 0x6c,
+ 0x70, 0x88, 0x4d, 0x4b, 0xb3, 0x88, 0x07, 0x35, 0xab, 0x87, 0xa1, 0xeb, 0x6b, 0x83, 0xa6, 0xe6,
+ 0x7f, 0x50, 0xfb, 0x1e, 0xf1, 0x09, 0xcf, 0x63, 0xd3, 0x52, 0x67, 0x45, 0x95, 0x15, 0xd5, 0x41,
+ 0x53, 0xac, 0x22, 0x82, 0x48, 0x58, 0xd6, 0x66, 0x4f, 0x0c, 0x29, 0x1e, 0x20, 0x42, 0x50, 0x0f,
+ 0x6a, 0xe1, 0xca, 0x0c, 0x2e, 0x35, 0xc3, 0x1d, 0xb2, 0x92, 0x72, 0xcb, 0x81, 0xdd, 0x0e, 0x45,
+ 0xe7, 0x1e, 0x34, 0x7c, 0x78, 0x1e, 0xf2, 0xf0, 0x2f, 0x41, 0x85, 0x31, 0x76, 0xa9, 0x6f, 0xf8,
+ 0x50, 0xe0, 0xea, 0x5c, 0x63, 0xab, 0x55, 0x55, 0x19, 0x8b, 0x3a, 0x67, 0x51, 0x9f, 0xbb, 0xc3,
+ 0xf6, 0xfe, 0x74, 0x24, 0xdf, 0x19, 0x1a, 0x4e, 0xef, 0x4c, 0x89, 0x9f, 0x51, 0xf4, 0x2d, 0xb6,
+ 0xbc, 0x98, 0xad, 0xf8, 0x37, 0x60, 0xd7, 0x22, 0x2e, 0x85, 0x2e, 0x0d, 0x68, 0x44, 0xba, 0xb1,
+ 0x82, 0x54, 0x9c, 0x8e, 0xe4, 0x5a, 0x44, 0x9a, 0x3c, 0xa6, 0xe8, 0x3b, 0x8b, 0x1d, 0x46, 0x5d,
+ 0x03, 0x25, 0x8a, 0x91, 0x0b, 0x3d, 0xa1, 0x58, 0xe7, 0x1a, 0x65, 0x3d, 0x5a, 0x9d, 0x6d, 0x7e,
+ 0xbc, 0x96, 0x0b, 0x3f, 0xaf, 0xe5, 0x82, 0x72, 0x00, 0xf6, 0x53, 0x0e, 0x75, 0x48, 0xfb, 0x33,
+ 0x16, 0xe5, 0x0b, 0x73, 0xff, 0xba, 0x6f, 0xff, 0x76, 0xdf, 0x04, 0xe5, 0xc8, 0x09, 0xb6, 0x43,
+ 0xeb, 0xe5, 0x76, 0x75, 0x3a, 0x92, 0xf7, 0x12, 0x26, 0xb1, 0xad, 0xe8, 0x9b, 0xec, 0xf9, 0x85,
+ 0xcd, 0x3f, 0x05, 0x3b, 0xd1, 0xbe, 0x03, 0x29, 0x35, 0xd0, 0x4a, 0x77, 0xfa, 0x36, 0xc3, 0x76,
+ 0x18, 0x74, 0x6d, 0x03, 0xf1, 0x26, 0x17, 0x06, 0xbe, 0x17, 0xc1, 0x5e, 0x58, 0x43, 0x9e, 0x61,
+ 0xff, 0x81, 0x83, 0x74, 0xe4, 0x1b, 0xff, 0x22, 0xf2, 0xe2, 0x5f, 0x8a, 0xfc, 0x15, 0xa8, 0xf6,
+ 0x3d, 0x42, 0x2e, 0xbb, 0x01, 0xb3, 0xdd, 0x65, 0xba, 0xc2, 0x7f, 0x75, 0xae, 0x51, 0x69, 0xcb,
+ 0xd3, 0x91, 0x7c, 0xc8, 0x98, 0xb2, 0x50, 0x8a, 0xce, 0x87, 0xdb, 0xc9, 0x57, 0xf6, 0x1e, 0x1c,
+ 0xa5, 0xc0, 0xa9, 0xde, 0xff, 0x0f, 0xb9, 0x1b, 0xd3, 0x91, 0x7c, 0x9c, 0xc9, 0x9d, 0xee, 0x59,
+ 0x4c, 0x88, 0xe4, 0x8d, 0x6c, 0x29, 0x27, 0x71, 0x11, 0x08, 0xe9, 0x54, 0x17, 0x91, 0x7f, 0xe5,
+ 0xc0, 0xdd, 0x0e, 0x45, 0x17, 0x81, 0xe9, 0x60, 0xbf, 0x83, 0xa9, 0x09, 0xaf, 0x8c, 0x01, 0x26,
+ 0x81, 0xc7, 0x9f, 0x2e, 0xe7, 0x5e, 0xcb, 0xca, 0x5d, 0xe0, 0x62, 0xc9, 0x3f, 0x03, 0x15, 0x27,
+ 0x46, 0xb2, 0x32, 0xf9, 0x0d, 0x81, 0xd3, 0x13, 0x68, 0x5e, 0x4c, 0x0e, 0x6f, 0x88, 0x58, 0xb6,
+ 0x23, 0x83, 0xa3, 0xcc, 0x8e, 0xe7, 0x9e, 0x5a, 0x9f, 0x8b, 0xa0, 0xd8, 0xa1, 0x88, 0x7f, 0x07,
+ 0x2a, 0x89, 0x2f, 0xd1, 0x3d, 0x75, 0xf9, 0x1b, 0xa7, 0xa6, 0x2e, 0xb3, 0xf8, 0x60, 0x0d, 0xd0,
+ 0x5c, 0x69, 0xa6, 0x90, 0xb8, 0xed, 0x79, 0x0a, 0x71, 0x50, 0xae, 0x42, 0xd6, 0x95, 0xe4, 0x2d,
+ 0xb0, 0x9d, 0x9c, 0xad, 0xe3, 0xdc, 0xd3, 0x31, 0x94, 0xf8, 0x70, 0x1d, 0xd4, 0x42, 0xc4, 0x03,
+ 0x7c, 0xc6, 0x00, 0xdc, 0xcf, 0xe1, 0x58, 0x86, 0x8a, 0xcd, 0xb5, 0xa1, 0x73, 0xcd, 0xb6, 0xfe,
+ 0x6d, 0x2c, 0x71, 0x37, 0x63, 0x89, 0xbb, 0x1d, 0x4b, 0xdc, 0xa7, 0x89, 0x54, 0xb8, 0x99, 0x48,
+ 0x85, 0x1f, 0x13, 0xa9, 0xf0, 0xf6, 0x09, 0xc2, 0xfe, 0x55, 0x60, 0xaa, 0x16, 0x71, 0x34, 0x8b,
+ 0x50, 0x87, 0x50, 0x0d, 0x9b, 0xd6, 0x09, 0x22, 0xda, 0xe0, 0xb1, 0xe6, 0x10, 0x3b, 0xe8, 0x41,
+ 0xca, 0x7e, 0x63, 0x8f, 0x5a, 0x27, 0xd1, 0x9f, 0xcc, 0x1f, 0xf6, 0x21, 0x35, 0x4b, 0xe1, 0x7c,
+ 0x9d, 0xfe, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x88, 0x72, 0x43, 0x59, 0xe9, 0x06, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -716,9 +718,9 @@ func (m *MsgUpdateClient) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i--
dAtA[i] = 0x1a
}
- if m.Header != nil {
+ if m.ClientMessage != nil {
{
- size, err := m.Header.MarshalToSizedBuffer(dAtA[:i])
+ size, err := m.ClientMessage.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
@@ -982,8 +984,8 @@ func (m *MsgUpdateClient) Size() (n int) {
if l > 0 {
n += 1 + l + sovTx(uint64(l))
}
- if m.Header != nil {
- l = m.Header.Size()
+ if m.ClientMessage != nil {
+ l = m.ClientMessage.Size()
n += 1 + l + sovTx(uint64(l))
}
l = len(m.Signer)
@@ -1347,7 +1349,7 @@ func (m *MsgUpdateClient) Unmarshal(dAtA []byte) error {
iNdEx = postIndex
case 2:
if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ return fmt.Errorf("proto: wrong wireType = %d for field ClientMessage", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
@@ -1374,10 +1376,10 @@ func (m *MsgUpdateClient) Unmarshal(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
- if m.Header == nil {
- m.Header = &types.Any{}
+ if m.ClientMessage == nil {
+ m.ClientMessage = &types.Any{}
}
- if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ if err := m.ClientMessage.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
diff --git a/modules/core/03-connection/keeper/handshake_test.go b/modules/core/03-connection/keeper/handshake_test.go
index 64ef8f8b813..0dfafa5f911 100644
--- a/modules/core/03-connection/keeper/handshake_test.go
+++ b/modules/core/03-connection/keeper/handshake_test.go
@@ -7,7 +7,7 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/03-connection/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -125,7 +125,7 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID)
// Set an invalid client of chainA on chainB
- tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState)
+ tmClient, ok := counterpartyClient.(*ibctm.ClientState)
suite.Require().True(ok)
tmClient.ChainId = "wrongchainid"
@@ -182,7 +182,7 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID)
// modify counterparty client without setting in store so it still passes validate but fails proof verification
- tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState)
+ tmClient, ok := counterpartyClient.(*ibctm.ClientState)
suite.Require().True(ok)
tmClient.LatestHeight = tmClient.LatestHeight.Increment().(clienttypes.Height)
}, false},
@@ -194,7 +194,7 @@ func (suite *KeeperTestSuite) TestConnOpenTry() {
consState, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetLatestClientConsensusState(suite.chainA.GetContext(), path.EndpointA.ClientID)
suite.Require().True(found)
- tmConsState, ok := consState.(*ibctmtypes.ConsensusState)
+ tmConsState, ok := consState.(*ibctm.ConsensusState)
suite.Require().True(ok)
tmConsState.Timestamp = time.Now()
@@ -291,7 +291,7 @@ func (suite *KeeperTestSuite) TestConnOpenAck() {
counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
// Set an invalid client of chainA on chainB
- tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState)
+ tmClient, ok := counterpartyClient.(*ibctm.ClientState)
suite.Require().True(ok)
tmClient.ChainId = "wrongchainid"
@@ -431,7 +431,7 @@ func (suite *KeeperTestSuite) TestConnOpenAck() {
counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
// modify counterparty client without setting in store so it still passes validate but fails proof verification
- tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState)
+ tmClient, ok := counterpartyClient.(*ibctm.ClientState)
suite.Require().True(ok)
tmClient.LatestHeight = tmClient.LatestHeight.Increment().(clienttypes.Height)
@@ -449,7 +449,7 @@ func (suite *KeeperTestSuite) TestConnOpenAck() {
consState, found := suite.chainB.App.GetIBCKeeper().ClientKeeper.GetLatestClientConsensusState(suite.chainB.GetContext(), path.EndpointB.ClientID)
suite.Require().True(found)
- tmConsState, ok := consState.(*ibctmtypes.ConsensusState)
+ tmConsState, ok := consState.(*ibctm.ConsensusState)
suite.Require().True(ok)
tmConsState.Timestamp = tmConsState.Timestamp.Add(time.Second)
diff --git a/modules/core/03-connection/keeper/keeper.go b/modules/core/03-connection/keeper/keeper.go
index 9e23503ad50..7995a52c4b3 100644
--- a/modules/core/03-connection/keeper/keeper.go
+++ b/modules/core/03-connection/keeper/keeper.go
@@ -86,18 +86,19 @@ func (k Keeper) SetConnection(ctx sdk.Context, connectionID string, connection t
// GetTimestampAtHeight returns the timestamp in nanoseconds of the consensus state at the
// given height.
func (k Keeper) GetTimestampAtHeight(ctx sdk.Context, connection types.ConnectionEnd, height exported.Height) (uint64, error) {
- consensusState, found := k.clientKeeper.GetClientConsensusState(
- ctx, connection.GetClientID(), height,
- )
-
+ clientState, found := k.clientKeeper.GetClientState(ctx, connection.GetClientID())
if !found {
return 0, sdkerrors.Wrapf(
- clienttypes.ErrConsensusStateNotFound,
- "clientID (%s), height (%s)", connection.GetClientID(), height,
+ clienttypes.ErrClientNotFound, "clientID (%s)", connection.GetClientID(),
)
}
- return consensusState.GetTimestamp(), nil
+ timestamp, err := clientState.GetTimestampAtHeight(ctx, k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height)
+ if err != nil {
+ return 0, err
+ }
+
+ return timestamp, nil
}
// GetClientConnectionPaths returns all the connection paths stored under a
diff --git a/modules/core/03-connection/keeper/keeper_test.go b/modules/core/03-connection/keeper/keeper_test.go
index df1a6131d3e..2062105dac9 100644
--- a/modules/core/03-connection/keeper/keeper_test.go
+++ b/modules/core/03-connection/keeper/keeper_test.go
@@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/suite"
"github.com/cosmos/ibc-go/v5/modules/core/03-connection/types"
+ "github.com/cosmos/ibc-go/v5/modules/core/exported"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -111,7 +112,10 @@ func (suite KeeperTestSuite) TestGetAllClientConnectionPaths() {
// TestGetTimestampAtHeight verifies if the clients on each chain return the
// correct timestamp for the other chain.
func (suite *KeeperTestSuite) TestGetTimestampAtHeight() {
- var connection types.ConnectionEnd
+ var (
+ connection types.ConnectionEnd
+ height exported.Height
+ )
cases := []struct {
msg string
@@ -122,10 +126,14 @@ func (suite *KeeperTestSuite) TestGetTimestampAtHeight() {
path := ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupConnections(path)
connection = path.EndpointA.GetConnection()
+ height = suite.chainB.LastHeader.GetHeight()
}, true},
+ {"client state not found", func() {}, false},
{"consensus state not found", func() {
- // any non-nil value of connection is valid
- suite.Require().NotNil(connection)
+ path := ibctesting.NewPath(suite.chainA, suite.chainB)
+ suite.coordinator.SetupConnections(path)
+ connection = path.EndpointA.GetConnection()
+ height = suite.chainB.LastHeader.GetHeight().Increment()
}, false},
}
@@ -136,7 +144,7 @@ func (suite *KeeperTestSuite) TestGetTimestampAtHeight() {
tc.malleate()
actualTimestamp, err := suite.chainA.App.GetIBCKeeper().ConnectionKeeper.GetTimestampAtHeight(
- suite.chainA.GetContext(), connection, suite.chainB.LastHeader.GetHeight(),
+ suite.chainA.GetContext(), connection, height,
)
if tc.expPass {
diff --git a/modules/core/03-connection/keeper/verify.go b/modules/core/03-connection/keeper/verify.go
index 3471cdcb7ac..bafea2bd190 100644
--- a/modules/core/03-connection/keeper/verify.go
+++ b/modules/core/03-connection/keeper/verify.go
@@ -7,6 +7,10 @@ import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
+ connectiontypes "github.com/cosmos/ibc-go/v5/modules/core/03-connection/types"
+ channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
+ commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
+ host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
)
@@ -31,9 +35,27 @@ func (k Keeper) VerifyClientState(
return sdkerrors.Wrapf(clienttypes.ErrClientNotActive, "client (%s) status is %s", clientID, status)
}
- if err := targetClient.VerifyClientState(
- clientStore, k.cdc, height,
- connection.GetCounterparty().GetPrefix(), connection.GetCounterparty().GetClientID(), proof, clientState); err != nil {
+ merklePath := commitmenttypes.NewMerklePath(host.FullClientStatePath(connection.GetCounterparty().GetClientID()))
+ merklePath, err := commitmenttypes.ApplyPrefix(connection.GetCounterparty().GetPrefix(), merklePath)
+ if err != nil {
+ return err
+ }
+
+ path, err := k.cdc.Marshal(&merklePath)
+ if err != nil {
+ return err
+ }
+
+ bz, err := k.cdc.MarshalInterface(clientState)
+ if err != nil {
+ return err
+ }
+
+ if err := targetClient.VerifyMembership(
+ ctx, clientStore, k.cdc, height,
+ 0, 0, // skip delay period checks for non-packet processing verification
+ proof, path, bz,
+ ); err != nil {
return sdkerrors.Wrapf(err, "failed client state verification for target client: %s", clientID)
}
@@ -62,9 +84,26 @@ func (k Keeper) VerifyClientConsensusState(
return sdkerrors.Wrapf(clienttypes.ErrClientNotActive, "client (%s) status is %s", clientID, status)
}
- if err := clientState.VerifyClientConsensusState(
- clientStore, k.cdc, height,
- connection.GetCounterparty().GetClientID(), consensusHeight, connection.GetCounterparty().GetPrefix(), proof, consensusState,
+ merklePath := commitmenttypes.NewMerklePath(host.FullConsensusStatePath(connection.GetCounterparty().GetClientID(), consensusHeight))
+ merklePath, err := commitmenttypes.ApplyPrefix(connection.GetCounterparty().GetPrefix(), merklePath)
+ if err != nil {
+ return err
+ }
+
+ path, err := k.cdc.Marshal(&merklePath)
+ if err != nil {
+ return err
+ }
+
+ bz, err := k.cdc.MarshalInterface(consensusState)
+ if err != nil {
+ return err
+ }
+
+ if err := clientState.VerifyMembership(
+ ctx, clientStore, k.cdc, height,
+ 0, 0, // skip delay period checks for non-packet processing verification
+ proof, path, bz,
); err != nil {
return sdkerrors.Wrapf(err, "failed consensus state verification for client (%s)", clientID)
}
@@ -80,7 +119,7 @@ func (k Keeper) VerifyConnectionState(
height exported.Height,
proof []byte,
connectionID string,
- connectionEnd exported.ConnectionI, // opposite connection
+ counterpartyConnection exported.ConnectionI, // opposite connection
) error {
clientID := connection.GetClientID()
clientStore := k.clientKeeper.ClientStore(ctx, clientID)
@@ -94,9 +133,31 @@ func (k Keeper) VerifyConnectionState(
return sdkerrors.Wrapf(clienttypes.ErrClientNotActive, "client (%s) status is %s", clientID, status)
}
- if err := clientState.VerifyConnectionState(
- clientStore, k.cdc, height,
- connection.GetCounterparty().GetPrefix(), proof, connectionID, connectionEnd,
+ merklePath := commitmenttypes.NewMerklePath(host.ConnectionPath(connectionID))
+ merklePath, err := commitmenttypes.ApplyPrefix(connection.GetCounterparty().GetPrefix(), merklePath)
+ if err != nil {
+ return err
+ }
+
+ path, err := k.cdc.Marshal(&merklePath)
+ if err != nil {
+ return err
+ }
+
+ connectionEnd, ok := counterpartyConnection.(connectiontypes.ConnectionEnd)
+ if !ok {
+ return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "invalid connection type %T", counterpartyConnection)
+ }
+
+ bz, err := k.cdc.Marshal(&connectionEnd)
+ if err != nil {
+ return err
+ }
+
+ if err := clientState.VerifyMembership(
+ ctx, clientStore, k.cdc, height,
+ 0, 0, // skip delay period checks for non-packet processing verification
+ proof, path, bz,
); err != nil {
return sdkerrors.Wrapf(err, "failed connection state verification for client (%s)", clientID)
}
@@ -127,10 +188,31 @@ func (k Keeper) VerifyChannelState(
return sdkerrors.Wrapf(clienttypes.ErrClientNotActive, "client (%s) status is %s", clientID, status)
}
- if err := clientState.VerifyChannelState(
- clientStore, k.cdc, height,
- connection.GetCounterparty().GetPrefix(), proof,
- portID, channelID, channel,
+ merklePath := commitmenttypes.NewMerklePath(host.ChannelPath(portID, channelID))
+ merklePath, err := commitmenttypes.ApplyPrefix(connection.GetCounterparty().GetPrefix(), merklePath)
+ if err != nil {
+ return err
+ }
+
+ path, err := k.cdc.Marshal(&merklePath)
+ if err != nil {
+ return err
+ }
+
+ channelEnd, ok := channel.(channeltypes.Channel)
+ if !ok {
+ return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "invalid channel type %T", channel)
+ }
+
+ bz, err := k.cdc.Marshal(&channelEnd)
+ if err != nil {
+ return err
+ }
+
+ if err := clientState.VerifyMembership(
+ ctx, clientStore, k.cdc, height,
+ 0, 0, // skip delay period checks for non-packet processing verification
+ proof, path, bz,
); err != nil {
return sdkerrors.Wrapf(err, "failed channel state verification for client (%s)", clientID)
}
@@ -166,11 +248,21 @@ func (k Keeper) VerifyPacketCommitment(
timeDelay := connection.GetDelayPeriod()
blockDelay := k.getBlockDelay(ctx, connection)
- if err := clientState.VerifyPacketCommitment(
+ merklePath := commitmenttypes.NewMerklePath(host.PacketCommitmentPath(portID, channelID, sequence))
+ merklePath, err := commitmenttypes.ApplyPrefix(connection.GetCounterparty().GetPrefix(), merklePath)
+ if err != nil {
+ return err
+ }
+
+ path, err := k.cdc.Marshal(&merklePath)
+ if err != nil {
+ return err
+ }
+
+ if err := clientState.VerifyMembership(
ctx, clientStore, k.cdc, height,
timeDelay, blockDelay,
- connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
- sequence, commitmentBytes,
+ proof, path, commitmentBytes,
); err != nil {
return sdkerrors.Wrapf(err, "failed packet commitment verification for client (%s)", clientID)
}
@@ -206,11 +298,21 @@ func (k Keeper) VerifyPacketAcknowledgement(
timeDelay := connection.GetDelayPeriod()
blockDelay := k.getBlockDelay(ctx, connection)
- if err := clientState.VerifyPacketAcknowledgement(
+ merklePath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementPath(portID, channelID, sequence))
+ merklePath, err := commitmenttypes.ApplyPrefix(connection.GetCounterparty().GetPrefix(), merklePath)
+ if err != nil {
+ return err
+ }
+
+ path, err := k.cdc.Marshal(&merklePath)
+ if err != nil {
+ return err
+ }
+
+ if err := clientState.VerifyMembership(
ctx, clientStore, k.cdc, height,
timeDelay, blockDelay,
- connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
- sequence, acknowledgement,
+ proof, path, channeltypes.CommitAcknowledgement(acknowledgement),
); err != nil {
return sdkerrors.Wrapf(err, "failed packet acknowledgement verification for client (%s)", clientID)
}
@@ -246,11 +348,21 @@ func (k Keeper) VerifyPacketReceiptAbsence(
timeDelay := connection.GetDelayPeriod()
blockDelay := k.getBlockDelay(ctx, connection)
- if err := clientState.VerifyPacketReceiptAbsence(
+ merklePath := commitmenttypes.NewMerklePath(host.PacketReceiptPath(portID, channelID, sequence))
+ merklePath, err := commitmenttypes.ApplyPrefix(connection.GetCounterparty().GetPrefix(), merklePath)
+ if err != nil {
+ return err
+ }
+
+ path, err := k.cdc.Marshal(&merklePath)
+ if err != nil {
+ return err
+ }
+
+ if err := clientState.VerifyNonMembership(
ctx, clientStore, k.cdc, height,
timeDelay, blockDelay,
- connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
- sequence,
+ proof, path,
); err != nil {
return sdkerrors.Wrapf(err, "failed packet receipt absence verification for client (%s)", clientID)
}
@@ -285,11 +397,21 @@ func (k Keeper) VerifyNextSequenceRecv(
timeDelay := connection.GetDelayPeriod()
blockDelay := k.getBlockDelay(ctx, connection)
- if err := clientState.VerifyNextSequenceRecv(
+ merklePath := commitmenttypes.NewMerklePath(host.NextSequenceRecvPath(portID, channelID))
+ merklePath, err := commitmenttypes.ApplyPrefix(connection.GetCounterparty().GetPrefix(), merklePath)
+ if err != nil {
+ return err
+ }
+
+ path, err := k.cdc.Marshal(&merklePath)
+ if err != nil {
+ return err
+ }
+
+ if err := clientState.VerifyMembership(
ctx, clientStore, k.cdc, height,
timeDelay, blockDelay,
- connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
- nextSequenceRecv,
+ proof, path, sdk.Uint64ToBigEndian(nextSequenceRecv),
); err != nil {
return sdkerrors.Wrapf(err, "failed next sequence receive verification for client (%s)", clientID)
}
diff --git a/modules/core/03-connection/keeper/verify_test.go b/modules/core/03-connection/keeper/verify_test.go
index b5592362936..3ad64e9b285 100644
--- a/modules/core/03-connection/keeper/verify_test.go
+++ b/modules/core/03-connection/keeper/verify_test.go
@@ -9,12 +9,12 @@ import (
channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
ibcmock "github.com/cosmos/ibc-go/v5/testing/mock"
)
-var defaultTimeoutHeight = clienttypes.NewHeight(0, 100000)
+var defaultTimeoutHeight = clienttypes.NewHeight(1, 100000)
// TestVerifyClientState verifies a client state of chainA
// stored on path.EndpointB (which is on chainB)
@@ -38,12 +38,12 @@ func (suite *KeeperTestSuite) TestVerifyClientState() {
heightDiff = 5
}, false},
{"verification failed", func() {
- counterpartyClient := path.EndpointB.GetClientState().(*ibctmtypes.ClientState)
+ counterpartyClient := path.EndpointB.GetClientState().(*ibctm.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 := path.EndpointA.GetClientState().(*ibctm.ClientState)
clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
path.EndpointA.SetClientState(clientState)
}, false},
@@ -62,7 +62,7 @@ func (suite *KeeperTestSuite) TestVerifyClientState() {
tc.malleate()
counterpartyClient, clientProof := path.EndpointB.QueryClientStateProof()
- proofHeight := clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()-1))
+ proofHeight := clienttypes.NewHeight(1, uint64(suite.chainB.GetContext().BlockHeight()-1))
connection := path.EndpointA.GetConnection()
@@ -109,7 +109,7 @@ func (suite *KeeperTestSuite) TestVerifyClientConsensusState() {
consState, found := suite.chainB.App.GetIBCKeeper().ClientKeeper.GetLatestClientConsensusState(suite.chainB.GetContext(), path.EndpointB.ClientID)
suite.Require().True(found)
- tmConsState, ok := consState.(*ibctmtypes.ConsensusState)
+ tmConsState, ok := consState.(*ibctm.ConsensusState)
suite.Require().True(ok)
tmConsState.Timestamp = time.Now()
@@ -118,7 +118,7 @@ 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 := path.EndpointA.GetClientState().(*ibctm.ClientState)
clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
path.EndpointA.SetClientState(clientState)
}, false},
@@ -138,7 +138,7 @@ func (suite *KeeperTestSuite) TestVerifyClientConsensusState() {
connection := path.EndpointA.GetConnection()
proof, consensusHeight := suite.chainB.QueryConsensusStateProof(path.EndpointB.ClientID)
- proofHeight := clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()-1))
+ proofHeight := clienttypes.NewHeight(1, uint64(suite.chainB.GetContext().BlockHeight()-1))
consensusState, err := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetSelfConsensusState(suite.chainA.GetContext(), consensusHeight)
suite.Require().NoError(err)
@@ -183,7 +183,7 @@ func (suite *KeeperTestSuite) TestVerifyConnectionState() {
path.EndpointA.SetConnection(connection)
}, false},
{"client status is not active - client is expired", func() {
- clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+ clientState := path.EndpointA.GetClientState().(*ibctm.ClientState)
clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
path.EndpointA.SetClientState(clientState)
}, false},
@@ -248,7 +248,7 @@ func (suite *KeeperTestSuite) TestVerifyChannelState() {
path.EndpointA.SetChannel(channel)
}, false},
{"client status is not active - client is expired", func() {
- clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+ clientState := path.EndpointA.GetClientState().(*ibctm.ClientState)
clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
path.EndpointA.SetClientState(clientState)
}, false},
@@ -326,7 +326,7 @@ func (suite *KeeperTestSuite) TestVerifyPacketCommitment() {
packet.Data = []byte(ibctesting.InvalidID)
}, false},
{"client status is not active - client is expired", func() {
- clientState := path.EndpointB.GetClientState().(*ibctmtypes.ClientState)
+ clientState := path.EndpointB.GetClientState().(*ibctm.ClientState)
clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
path.EndpointB.SetClientState(clientState)
}, false},
@@ -418,7 +418,7 @@ func (suite *KeeperTestSuite) TestVerifyPacketAcknowledgement() {
ack = ibcmock.MockFailAcknowledgement
}, false},
{"client status is not active - client is expired", func() {
- clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+ clientState := path.EndpointA.GetClientState().(*ibctm.ClientState)
clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
path.EndpointA.SetClientState(clientState)
}, false},
@@ -524,7 +524,7 @@ func (suite *KeeperTestSuite) TestVerifyPacketReceiptAbsence() {
suite.Require().NoError(err)
}, false},
{"client status is not active - client is expired", func() {
- clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+ clientState := path.EndpointA.GetClientState().(*ibctm.ClientState)
clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
path.EndpointA.SetClientState(clientState)
}, false},
@@ -553,7 +553,7 @@ func (suite *KeeperTestSuite) TestVerifyPacketReceiptAbsence() {
connection := path.EndpointA.GetConnection()
connection.DelayPeriod = delayTimePeriod
- clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+ clientState := path.EndpointA.GetClientState().(*ibctm.ClientState)
if clientState.FrozenHeight.IsZero() {
// need to update height to prove absence or receipt
suite.coordinator.CommitBlock(suite.chainA, suite.chainB)
@@ -624,7 +624,7 @@ func (suite *KeeperTestSuite) TestVerifyNextSequenceRecv() {
offsetSeq = 1
}, false},
{"client status is not active - client is expired", func() {
- clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
+ clientState := path.EndpointA.GetClientState().(*ibctm.ClientState)
clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
path.EndpointA.SetClientState(clientState)
}, false},
diff --git a/modules/core/03-connection/types/msgs_test.go b/modules/core/03-connection/types/msgs_test.go
index 58c02063378..5d8d4bcc99c 100644
--- a/modules/core/03-connection/types/msgs_test.go
+++ b/modules/core/03-connection/types/msgs_test.go
@@ -16,7 +16,7 @@ import (
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
"github.com/cosmos/ibc-go/v5/modules/core/03-connection/types"
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
"github.com/cosmos/ibc-go/v5/testing/simapp"
)
@@ -109,22 +109,22 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenInit() {
func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() {
prefix := commitmenttypes.NewMerklePrefix([]byte("storePrefixKey"))
- clientState := ibctmtypes.NewClientState(
- chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false,
+ clientState := ibctm.NewClientState(
+ chainID, ibctm.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false,
)
any, err := clienttypes.PackClientState(clientState)
suite.Require().NoError(err)
// Pack consensus state into any to test unpacking error
- consState := ibctmtypes.NewConsensusState(
+ consState := ibctm.NewConsensusState(
time.Now(), commitmenttypes.NewMerkleRoot([]byte("root")), []byte("nextValsHash"),
)
invalidAny := clienttypes.MustPackConsensusState(consState)
counterparty := types.NewCounterparty("connectiontotest", "clienttotest", prefix)
// invalidClientState fails validateBasic
- invalidClient := ibctmtypes.NewClientState(
- chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clienttypes.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false,
+ invalidClient := ibctm.NewClientState(
+ chainID, ibctm.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clienttypes.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false,
)
testCases := []struct {
@@ -162,19 +162,19 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() {
}
func (suite *MsgTestSuite) TestNewMsgConnectionOpenAck() {
- clientState := ibctmtypes.NewClientState(
- chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false,
+ clientState := ibctm.NewClientState(
+ chainID, ibctm.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false,
)
// Pack consensus state into any to test unpacking error
- consState := ibctmtypes.NewConsensusState(
+ consState := ibctm.NewConsensusState(
time.Now(), commitmenttypes.NewMerkleRoot([]byte("root")), []byte("nextValsHash"),
)
invalidAny := clienttypes.MustPackConsensusState(consState)
// invalidClientState fails validateBasic
- invalidClient := ibctmtypes.NewClientState(
- chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clienttypes.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false,
+ invalidClient := ibctm.NewClientState(
+ chainID, ibctm.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clienttypes.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false,
)
connectionID := "connection-0"
diff --git a/modules/core/04-channel/keeper/packet.go b/modules/core/04-channel/keeper/packet.go
index ad160bd8a0e..3fa66a6e989 100644
--- a/modules/core/04-channel/keeper/packet.go
+++ b/modules/core/04-channel/keeper/packet.go
@@ -84,25 +84,16 @@ func (k Keeper) SendPacket(
)
}
- clientType, _, err := clienttypes.ParseClientIdentifier(connectionEnd.GetClientID())
+ latestTimestamp, err := k.connectionKeeper.GetTimestampAtHeight(ctx, connectionEnd, latestHeight)
if err != nil {
return err
}
- // NOTE: this is a temporary fix. Solo machine does not support usage of 'GetTimestampAtHeight'
- // A future change should move this function to be a ClientState callback.
- if clientType != exported.Solomachine {
- latestTimestamp, err := k.connectionKeeper.GetTimestampAtHeight(ctx, connectionEnd, latestHeight)
- if err != nil {
- return err
- }
-
- if packet.GetTimeoutTimestamp() != 0 && latestTimestamp >= packet.GetTimeoutTimestamp() {
- return sdkerrors.Wrapf(
- types.ErrPacketTimeout,
- "receiving chain block timestamp >= packet timeout timestamp (%s >= %s)", time.Unix(0, int64(latestTimestamp)), time.Unix(0, int64(packet.GetTimeoutTimestamp())),
- )
- }
+ if packet.GetTimeoutTimestamp() != 0 && latestTimestamp >= packet.GetTimeoutTimestamp() {
+ return sdkerrors.Wrapf(
+ types.ErrPacketTimeout,
+ "receiving chain block timestamp >= packet timeout timestamp (%s >= %s)", time.Unix(0, int64(latestTimestamp)), time.Unix(0, int64(packet.GetTimeoutTimestamp())),
+ )
}
nextSequenceSend, found := k.GetNextSequenceSend(ctx, packet.GetSourcePort(), packet.GetSourceChannel())
diff --git a/modules/core/04-channel/keeper/packet_test.go b/modules/core/04-channel/keeper/packet_test.go
index 1080b1ebb73..8614f369bbd 100644
--- a/modules/core/04-channel/keeper/packet_test.go
+++ b/modules/core/04-channel/keeper/packet_test.go
@@ -12,7 +12,7 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
ibcmock "github.com/cosmos/ibc-go/v5/testing/mock"
)
@@ -20,7 +20,7 @@ import (
var (
disabledTimeoutTimestamp = uint64(0)
disabledTimeoutHeight = clienttypes.ZeroHeight()
- timeoutHeight = clienttypes.NewHeight(0, 100)
+ timeoutHeight = clienttypes.NewHeight(1, 100)
// for when the testing package cannot be used
clientIDA = "clientA"
@@ -148,7 +148,7 @@ func (suite *KeeperTestSuite) TestSendPacket() {
connection := path.EndpointA.GetConnection()
clientState := path.EndpointA.GetClientState()
- cs, ok := clientState.(*ibctmtypes.ClientState)
+ cs, ok := clientState.(*ibctm.ClientState)
suite.Require().True(ok)
// freeze client
@@ -177,6 +177,23 @@ func (suite *KeeperTestSuite) TestSendPacket() {
packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, disabledTimeoutHeight, timestamp)
channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
}, false},
+ {"timeout timestamp passed with solomachine", func() {
+ suite.coordinator.Setup(path)
+ // swap client with solomachine
+ solomachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachinesingle", "testing", 1)
+ path.EndpointA.ClientID = clienttypes.FormatClientIdentifier(exported.Solomachine, 10)
+ path.EndpointA.SetClientState(solomachine.ClientState())
+ connection := path.EndpointA.GetConnection()
+ connection.ClientId = path.EndpointA.ClientID
+ path.EndpointA.SetConnection(connection)
+
+ clientState := path.EndpointA.GetClientState()
+ timestamp, err := suite.chainA.App.GetIBCKeeper().ConnectionKeeper.GetTimestampAtHeight(suite.chainA.GetContext(), connection, clientState.GetLatestHeight())
+ suite.Require().NoError(err)
+
+ packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, disabledTimeoutHeight, timestamp)
+ channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
+ }, false},
{"next sequence send not found", func() {
path := ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupConnections(path)
diff --git a/modules/core/ante/ante_test.go b/modules/core/ante/ante_test.go
index 3d074429a66..363ea28e398 100644
--- a/modules/core/ante/ante_test.go
+++ b/modules/core/ante/ante_test.go
@@ -49,7 +49,7 @@ func (suite *AnteTestSuite) createRecvPacketMessage(sequenceNumber uint64, isRed
packet := channeltypes.NewPacket(ibctesting.MockPacketData, sequenceNumber,
suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID,
suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID,
- clienttypes.NewHeight(1, 0), 0)
+ clienttypes.NewHeight(2, 0), 0)
err := suite.path.EndpointA.SendPacket(packet)
suite.Require().NoError(err)
@@ -73,7 +73,7 @@ func (suite *AnteTestSuite) createAcknowledgementMessage(sequenceNumber uint64,
packet := channeltypes.NewPacket(ibctesting.MockPacketData, sequenceNumber,
suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID,
suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID,
- clienttypes.NewHeight(1, 0), 0)
+ clienttypes.NewHeight(2, 0), 0)
err := suite.path.EndpointB.SendPacket(packet)
suite.Require().NoError(err)
@@ -153,7 +153,7 @@ func (suite *AnteTestSuite) createUpdateClientMessage() sdk.Msg {
// ensure counterparty has committed state
endpoint.Chain.Coordinator.CommitBlock(endpoint.Counterparty.Chain)
- var header exported.Header
+ var header exported.ClientMessage
switch endpoint.ClientConfig.GetClientType() {
case exported.Tendermint:
@@ -415,11 +415,11 @@ func (suite *AnteTestSuite) TestAnteDecorator() {
packet := channeltypes.NewPacket(ibctesting.MockPacketData, 2,
suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID,
suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID,
- clienttypes.NewHeight(1, 0), 0)
+ clienttypes.NewHeight(2, 0), 0)
return []sdk.Msg{
suite.createRecvPacketMessage(uint64(1), false),
- channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer"),
+ channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(1, 1), "signer"),
}
},
false,
diff --git a/modules/core/exported/client.go b/modules/core/exported/client.go
index 4dce203bea4..ac76a647dc5 100644
--- a/modules/core/exported/client.go
+++ b/modules/core/exported/client.go
@@ -19,10 +19,6 @@ const (
// Tendermint is used to indicate that the client uses the Tendermint Consensus Algorithm.
Tendermint string = "07-tendermint"
- // 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"
@@ -44,137 +40,93 @@ type ClientState interface {
GetLatestHeight() Height
Validate() error
- // Initialization function
- // Clients must validate the initial consensus state, and may store any client-specific metadata
- // necessary for correct light client operation
- Initialize(sdk.Context, codec.BinaryCodec, sdk.KVStore, ConsensusState) error
-
- // Status function
- // Clients must return their status. Only Active clients are allowed to process packets.
+ // Status must return the status of the client. Only Active clients are allowed to process packets.
Status(ctx sdk.Context, clientStore sdk.KVStore, cdc codec.BinaryCodec) Status
- // Genesis function
- ExportMetadata(sdk.KVStore) []GenesisMetadata
-
- // Update and Misbehaviour functions
+ // ExportMetadata must export metadata stored within the clientStore for genesis export
+ ExportMetadata(clientStore sdk.KVStore) []GenesisMetadata
- CheckHeaderAndUpdateState(sdk.Context, codec.BinaryCodec, sdk.KVStore, Header) (ClientState, ConsensusState, error)
- CheckMisbehaviourAndUpdateState(sdk.Context, codec.BinaryCodec, sdk.KVStore, Misbehaviour) (ClientState, error)
- CheckSubstituteAndUpdateState(ctx sdk.Context, cdc codec.BinaryCodec, subjectClientStore, substituteClientStore sdk.KVStore, substituteClient ClientState) (ClientState, 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.
- VerifyUpgradeAndUpdateState(
- ctx sdk.Context,
- cdc codec.BinaryCodec,
- store sdk.KVStore,
- newClient ClientState,
- newConsState ConsensusState,
- proofUpgradeClient,
- proofUpgradeConsState []byte,
- ) (ClientState, ConsensusState, error)
- // Utility function that zeroes out any client customizable fields in client state
+ // ZeroCustomFields zeroes out any client customizable fields in client state
// Ledger enforced fields are maintained while all custom fields are zero values
// Used to verify upgrades
ZeroCustomFields() ClientState
- // State verification functions
-
- VerifyClientState(
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height Height,
- prefix Prefix,
- counterpartyClientIdentifier string,
- proof []byte,
- clientState ClientState,
- ) error
- VerifyClientConsensusState(
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height Height,
- counterpartyClientIdentifier string,
- consensusHeight Height,
- prefix Prefix,
- proof []byte,
- consensusState ConsensusState,
- ) error
- VerifyConnectionState(
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height Height,
- prefix Prefix,
- proof []byte,
- connectionID string,
- connectionEnd ConnectionI,
- ) error
- VerifyChannelState(
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height Height,
- prefix Prefix,
- proof []byte,
- portID,
- channelID string,
- channel ChannelI,
- ) error
- VerifyPacketCommitment(
+ // GetTimestampAtHeight must return the timestamp for the consensus state associated with the provided height.
+ GetTimestampAtHeight(
ctx sdk.Context,
- store sdk.KVStore,
+ clientStore sdk.KVStore,
cdc codec.BinaryCodec,
height Height,
- delayTimePeriod uint64,
- delayBlockPeriod uint64,
- prefix Prefix,
- proof []byte,
- portID,
- channelID string,
- sequence uint64,
- commitmentBytes []byte,
- ) error
- VerifyPacketAcknowledgement(
+ ) (uint64, error)
+
+ // Initialization function
+ // Clients must validate the initial consensus state, and may store any client-specific metadata
+ // necessary for correct light client operation
+ Initialize(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, consensusState ConsensusState) error
+
+ // VerifyMembership is a generic proof verification method which verifies a proof of the existence of a value at a given CommitmentPath at the specified height.
+ // The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24).
+ VerifyMembership(
ctx sdk.Context,
- store sdk.KVStore,
+ clientStore sdk.KVStore,
cdc codec.BinaryCodec,
height Height,
delayTimePeriod uint64,
delayBlockPeriod uint64,
- prefix Prefix,
proof []byte,
- portID,
- channelID string,
- sequence uint64,
- acknowledgement []byte,
+ path []byte,
+ value []byte,
) error
- VerifyPacketReceiptAbsence(
+
+ // VerifyNonMembership is a generic proof verification method which verifies the absence of a given CommitmentPath at a specified height.
+ // The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24).
+ VerifyNonMembership(
ctx sdk.Context,
- store sdk.KVStore,
+ clientStore sdk.KVStore,
cdc codec.BinaryCodec,
height Height,
delayTimePeriod uint64,
delayBlockPeriod uint64,
- prefix Prefix,
proof []byte,
- portID,
- channelID string,
- sequence uint64,
+ path []byte,
) error
- VerifyNextSequenceRecv(
+
+ // VerifyClientMessage must verify a ClientMessage. A ClientMessage could be a Header, Misbehaviour, or batch update.
+ // It must handle each type of ClientMessage appropriately. Calls to CheckForMisbehaviour, UpdateState, and UpdateStateOnMisbehaviour
+ // will assume that the content of the ClientMessage has been verified and can be trusted. An error should be returned
+ // if the ClientMessage fails to verify.
+ VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg ClientMessage) error
+
+ // Checks for evidence of a misbehaviour in Header or Misbehaviour type. It assumes the ClientMessage
+ // has already been verified.
+ CheckForMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg ClientMessage) bool
+
+ // UpdateStateOnMisbehaviour should perform appropriate state changes on a client state given that misbehaviour has been detected and verified
+ UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg ClientMessage)
+
+ // UpdateState updates and stores as necessary any associated information for an IBC client, such as the ClientState and corresponding ConsensusState.
+ // Upon successful update, a list of consensus heights is returned. It assumes the ClientMessage has already been verified.
+ UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg ClientMessage) []Height
+
+ // CheckSubstituteAndUpdateState must verify that the provided substitute may be used to update the subject client.
+ // The light client must set the updated client and consensus states within the clientStore for the subject client.
+ CheckSubstituteAndUpdateState(ctx sdk.Context, cdc codec.BinaryCodec, subjectClientStore, substituteClientStore sdk.KVStore, substituteClient ClientState) 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,
- store sdk.KVStore,
cdc codec.BinaryCodec,
- height Height,
- delayTimePeriod uint64,
- delayBlockPeriod uint64,
- prefix Prefix,
- proof []byte,
- portID,
- channelID string,
- nextSequenceRecv uint64,
+ store sdk.KVStore,
+ newClient ClientState,
+ newConsState ConsensusState,
+ proofUpgradeClient,
+ proofUpgradeConsState []byte,
) error
}
@@ -184,31 +136,19 @@ type ConsensusState interface {
ClientType() string // Consensus kind
- // GetRoot returns the commitment root of the consensus state,
- // which is used for key-value pair verification.
- GetRoot() Root
-
// GetTimestamp returns the timestamp (in nanoseconds) of the consensus state
GetTimestamp() uint64
ValidateBasic() error
}
-// Misbehaviour defines counterparty misbehaviour for a specific consensus type
-type Misbehaviour interface {
- proto.Message
-
- ClientType() string
- GetClientID() string
- ValidateBasic() error
-}
-
-// Header is the consensus state update information
-type Header interface {
+// ClientMessage is an interface used to update an IBC client.
+// The update may be done by a single header, a batch of headers, misbehaviour, or any type which when verified produces
+// a change to state of the IBC client
+type ClientMessage interface {
proto.Message
ClientType() string
- GetHeight() Height
ValidateBasic() error
}
diff --git a/modules/core/genesis.go b/modules/core/genesis.go
index 363b9a07717..e7875770dac 100644
--- a/modules/core/genesis.go
+++ b/modules/core/genesis.go
@@ -12,7 +12,7 @@ import (
// InitGenesis initializes the ibc state from a provided genesis
// state.
-func InitGenesis(ctx sdk.Context, k keeper.Keeper, createLocalhost bool, gs *types.GenesisState) {
+func InitGenesis(ctx sdk.Context, k keeper.Keeper, gs *types.GenesisState) {
client.InitGenesis(ctx, k.ClientKeeper, gs.ClientGenesis)
connection.InitGenesis(ctx, k.ConnectionKeeper, gs.ConnectionGenesis)
channel.InitGenesis(ctx, k.ChannelKeeper, gs.ChannelGenesis)
diff --git a/modules/core/genesis_test.go b/modules/core/genesis_test.go
index 0a4fa2e1fe4..c433e834de1 100644
--- a/modules/core/genesis_test.go
+++ b/modules/core/genesis_test.go
@@ -15,8 +15,7 @@ import (
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
"github.com/cosmos/ibc-go/v5/modules/core/types"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
- localhosttypes "github.com/cosmos/ibc-go/v5/modules/light-clients/09-localhost/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
"github.com/cosmos/ibc-go/v5/testing/simapp"
)
@@ -25,8 +24,7 @@ const (
connectionID = "connection-0"
clientID = "07-tendermint-0"
connectionID2 = "connection-1"
- clientID2 = "07-tendermin-1"
- localhostID = exported.Localhost + "-1"
+ clientID2 = "07-tendermint-1"
port1 = "firstport"
port2 = "secondport"
@@ -35,7 +33,7 @@ const (
channel2 = "channel-1"
)
-var clientHeight = clienttypes.NewHeight(0, 10)
+var clientHeight = clienttypes.NewHeight(1, 10)
type IBCTestSuite struct {
suite.Suite
@@ -77,10 +75,7 @@ func (suite *IBCTestSuite) TestValidateGenesis() {
ClientGenesis: clienttypes.NewGenesisState(
[]clienttypes.IdentifiedClientState{
clienttypes.NewIdentifiedClientState(
- clientID, ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ),
- clienttypes.NewIdentifiedClientState(
- localhostID, localhosttypes.NewClientState("chaindID", clientHeight),
+ clientID, ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
},
[]clienttypes.ClientConsensusStates{
@@ -89,7 +84,7 @@ func (suite *IBCTestSuite) TestValidateGenesis() {
[]clienttypes.ConsensusStateWithHeight{
clienttypes.NewConsensusStateWithHeight(
header.GetHeight().(clienttypes.Height),
- ibctmtypes.NewConsensusState(
+ ibctm.NewConsensusState(
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.AppHash), header.Header.NextValidatorsHash,
),
),
@@ -105,8 +100,8 @@ func (suite *IBCTestSuite) TestValidateGenesis() {
},
),
},
- clienttypes.NewParams(exported.Tendermint, exported.Localhost),
- true,
+ clienttypes.NewParams(exported.Tendermint),
+ false,
2,
),
ConnectionGenesis: connectiontypes.NewGenesisState(
@@ -157,10 +152,7 @@ func (suite *IBCTestSuite) TestValidateGenesis() {
ClientGenesis: clienttypes.NewGenesisState(
[]clienttypes.IdentifiedClientState{
clienttypes.NewIdentifiedClientState(
- clientID, ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ),
- clienttypes.NewIdentifiedClientState(
- localhostID, localhosttypes.NewClientState("(chaindID)", clienttypes.ZeroHeight()),
+ clientID, ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
},
nil,
@@ -241,10 +233,7 @@ func (suite *IBCTestSuite) TestInitGenesis() {
ClientGenesis: clienttypes.NewGenesisState(
[]clienttypes.IdentifiedClientState{
clienttypes.NewIdentifiedClientState(
- clientID, ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
- ),
- clienttypes.NewIdentifiedClientState(
- exported.Localhost, localhosttypes.NewClientState("chaindID", clientHeight),
+ clientID, ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false),
),
},
[]clienttypes.ClientConsensusStates{
@@ -253,7 +242,7 @@ func (suite *IBCTestSuite) TestInitGenesis() {
[]clienttypes.ConsensusStateWithHeight{
clienttypes.NewConsensusStateWithHeight(
header.GetHeight().(clienttypes.Height),
- ibctmtypes.NewConsensusState(
+ ibctm.NewConsensusState(
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.AppHash), header.Header.NextValidatorsHash,
),
),
@@ -269,8 +258,8 @@ func (suite *IBCTestSuite) TestInitGenesis() {
},
),
},
- clienttypes.NewParams(exported.Tendermint, exported.Localhost),
- true,
+ clienttypes.NewParams(exported.Tendermint),
+ false,
0,
),
ConnectionGenesis: connectiontypes.NewGenesisState(
@@ -320,7 +309,7 @@ func (suite *IBCTestSuite) TestInitGenesis() {
app := simapp.Setup(false)
suite.NotPanics(func() {
- ibc.InitGenesis(app.BaseApp.NewContext(false, tmproto.Header{Height: 1}), *app.IBCKeeper, true, tc.genState)
+ ibc.InitGenesis(app.BaseApp.NewContext(false, tmproto.Header{Height: 1}), *app.IBCKeeper, tc.genState)
})
}
}
@@ -355,7 +344,7 @@ func (suite *IBCTestSuite) TestExportGenesis() {
// init genesis based on export
suite.NotPanics(func() {
- ibc.InitGenesis(suite.chainA.GetContext(), *suite.chainA.App.GetIBCKeeper(), true, gs)
+ ibc.InitGenesis(suite.chainA.GetContext(), *suite.chainA.App.GetIBCKeeper(), gs)
})
suite.NotPanics(func() {
@@ -366,7 +355,7 @@ func (suite *IBCTestSuite) TestExportGenesis() {
// init genesis based on marshal and unmarshal
suite.NotPanics(func() {
- ibc.InitGenesis(suite.chainA.GetContext(), *suite.chainA.App.GetIBCKeeper(), true, gs)
+ ibc.InitGenesis(suite.chainA.GetContext(), *suite.chainA.App.GetIBCKeeper(), gs)
})
})
}
diff --git a/modules/core/keeper/msg_server.go b/modules/core/keeper/msg_server.go
index 500d1dd8cf7..5f6c77a3981 100644
--- a/modules/core/keeper/msg_server.go
+++ b/modules/core/keeper/msg_server.go
@@ -46,12 +46,12 @@ func (k Keeper) CreateClient(goCtx context.Context, msg *clienttypes.MsgCreateCl
func (k Keeper) UpdateClient(goCtx context.Context, msg *clienttypes.MsgUpdateClient) (*clienttypes.MsgUpdateClientResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
- header, err := clienttypes.UnpackHeader(msg.Header)
+ clientMsg, err := clienttypes.UnpackClientMessage(msg.ClientMessage)
if err != nil {
return nil, err
}
- if err = k.ClientKeeper.UpdateClient(ctx, msg.ClientId, header); err != nil {
+ if err = k.ClientKeeper.UpdateClient(ctx, msg.ClientId, clientMsg); err != nil {
return nil, err
}
@@ -80,16 +80,18 @@ func (k Keeper) UpgradeClient(goCtx context.Context, msg *clienttypes.MsgUpgrade
}
// SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour.
+// Warning: DEPRECATED
+// This handler is redudant as `MsgUpdateClient` is now capable of handling both a Header and a Misbehaviour
func (k Keeper) SubmitMisbehaviour(goCtx context.Context, msg *clienttypes.MsgSubmitMisbehaviour) (*clienttypes.MsgSubmitMisbehaviourResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
- misbehaviour, err := clienttypes.UnpackMisbehaviour(msg.Misbehaviour)
+ misbehaviour, err := clienttypes.UnpackClientMessage(msg.Misbehaviour)
if err != nil {
return nil, err
}
- if err := k.ClientKeeper.CheckMisbehaviourAndUpdateState(ctx, misbehaviour); err != nil {
- return nil, sdkerrors.Wrap(err, "failed to process misbehaviour for IBC client")
+ if err = k.ClientKeeper.UpdateClient(ctx, msg.ClientId, misbehaviour); err != nil {
+ return nil, err
}
return &clienttypes.MsgSubmitMisbehaviourResponse{}, nil
diff --git a/modules/core/keeper/msg_server_test.go b/modules/core/keeper/msg_server_test.go
index 420e8c429e6..1fd6a73ad87 100644
--- a/modules/core/keeper/msg_server_test.go
+++ b/modules/core/keeper/msg_server_test.go
@@ -10,13 +10,13 @@ import (
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
"github.com/cosmos/ibc-go/v5/modules/core/keeper"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
ibcmock "github.com/cosmos/ibc-go/v5/testing/mock"
)
var (
- timeoutHeight = clienttypes.NewHeight(0, 10000)
+ timeoutHeight = clienttypes.NewHeight(1, 10000)
maxSequence = uint64(10)
)
@@ -627,15 +627,13 @@ func (suite *KeeperTestSuite) TestHandleTimeoutOnClosePacket() {
func (suite *KeeperTestSuite) TestUpgradeClient() {
var (
path *ibctesting.Path
+ newChainID string
+ newClientHeight clienttypes.Height
upgradedClient exported.ClientState
upgradedConsState exported.ConsensusState
lastHeight exported.Height
msg *clienttypes.MsgUpgradeClient
)
-
- newClientHeight := clienttypes.NewHeight(1, 1)
- newChainId := "newChainId-1"
-
cases := []struct {
name string
setup func()
@@ -644,11 +642,11 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
{
name: "successful upgrade",
setup: func() {
- upgradedClient = ibctmtypes.NewClientState(newChainId, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
+ upgradedClient = ibctm.NewClientState(newChainID, ibctm.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
// Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient
upgradedClient = upgradedClient.ZeroCustomFields()
- upgradedConsState = &ibctmtypes.ConsensusState{
+ upgradedConsState = &ibctm.ConsensusState{
NextValidatorsHash: []byte("nextValsHash"),
}
@@ -684,11 +682,11 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
{
name: "VerifyUpgrade fails",
setup: func() {
- upgradedClient = ibctmtypes.NewClientState(newChainId, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
+ upgradedClient = ibctm.NewClientState(newChainID, ibctm.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
// Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient
upgradedClient = upgradedClient.ZeroCustomFields()
- upgradedConsState = &ibctmtypes.ConsensusState{
+ upgradedConsState = &ibctm.ConsensusState{
NextValidatorsHash: []byte("nextValsHash"),
}
@@ -721,9 +719,18 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
path = ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupClients(path)
+ var err error
+ clientState := path.EndpointA.GetClientState().(*ibctm.ClientState)
+ revisionNumber := clienttypes.ParseChainID(clientState.ChainId)
+
+ newChainID, err = clienttypes.SetRevisionNumber(clientState.ChainId, revisionNumber+1)
+ suite.Require().NoError(err)
+
+ newClientHeight = clienttypes.NewHeight(revisionNumber+1, clientState.GetLatestHeight().GetRevisionHeight()+1)
+
tc.setup()
- _, err := keeper.Keeper.UpgradeClient(*suite.chainA.App.GetIBCKeeper(), sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
+ _, err = keeper.Keeper.UpgradeClient(*suite.chainA.App.GetIBCKeeper(), sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
if tc.expPass {
suite.Require().NoError(err, "upgrade handler failed on valid case: %s", tc.name)
diff --git a/modules/core/legacy/v100/genesis_test.go b/modules/core/legacy/v100/genesis_test.go
index fa06a137756..b50a802b935 100644
--- a/modules/core/legacy/v100/genesis_test.go
+++ b/modules/core/legacy/v100/genesis_test.go
@@ -14,7 +14,7 @@ import (
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
connectiontypes "github.com/cosmos/ibc-go/v5/modules/core/03-connection/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
- v100 "github.com/cosmos/ibc-go/v5/modules/core/legacy/v100"
+ "github.com/cosmos/ibc-go/v5/modules/core/legacy/v100"
"github.com/cosmos/ibc-go/v5/modules/core/types"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
"github.com/cosmos/ibc-go/v5/testing/simapp"
diff --git a/modules/core/migrations/v5/migrations.go b/modules/core/migrations/v5/migrations.go
new file mode 100644
index 00000000000..dec7eb79d80
--- /dev/null
+++ b/modules/core/migrations/v5/migrations.go
@@ -0,0 +1,44 @@
+package v5
+
+import (
+ "strings"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ clientkeeper "github.com/cosmos/ibc-go/v5/modules/core/02-client/keeper"
+ clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
+ host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
+ "github.com/cosmos/ibc-go/v5/modules/core/exported"
+)
+
+// 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"
+
+// MigrateToV5 prunes the 09-Localhost client and associated consensus states from the ibc store
+func MigrateToV5(ctx sdk.Context, clientKeeper clientkeeper.Keeper) {
+ clientStore := clientKeeper.ClientStore(ctx, Localhost)
+
+ 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))
+ }
+
+ // delete the client state
+ clientStore.Delete(host.ClientStateKey())
+}
diff --git a/modules/core/migrations/v5/migrations_test.go b/modules/core/migrations/v5/migrations_test.go
new file mode 100644
index 00000000000..2e70ede1cae
--- /dev/null
+++ b/modules/core/migrations/v5/migrations_test.go
@@ -0,0 +1,116 @@
+package v5_test
+
+import (
+ "testing"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/stretchr/testify/suite"
+
+ clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
+ host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
+ "github.com/cosmos/ibc-go/v5/modules/core/exported"
+ v5 "github.com/cosmos/ibc-go/v5/modules/core/migrations/v5"
+ ibctesting "github.com/cosmos/ibc-go/v5/testing"
+)
+
+type MigrationsV5TestSuite struct {
+ suite.Suite
+
+ coordinator *ibctesting.Coordinator
+
+ chainA *ibctesting.TestChain
+ chainB *ibctesting.TestChain
+}
+
+func (suite *MigrationsV5TestSuite) SetupTest() {
+ suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2)
+
+ suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(1))
+ suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(2))
+}
+
+func TestIBCTestSuite(t *testing.T) {
+ suite.Run(t, new(MigrationsV5TestSuite))
+}
+
+func (suite *MigrationsV5TestSuite) TestMigrateToV5() {
+ var clientStore sdk.KVStore
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "success: prune localhost client state",
+ func() {
+ clientStore.Set(host.ClientStateKey(), []byte("clientState"))
+ },
+ true,
+ },
+ {
+ "success: prune localhost client state and consensus states",
+ func() {
+ clientStore.Set(host.ClientStateKey(), []byte("clientState"))
+
+ for i := 0; i < 10; i++ {
+ clientStore.Set(host.ConsensusStateKey(clienttypes.NewHeight(1, uint64(i))), []byte("consensusState"))
+ }
+ },
+ true,
+ },
+ {
+ "07-tendermint client state and consensus states remain in client store",
+ func() {
+ clientStore = suite.chainA.GetSimApp().IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clienttypes.FormatClientIdentifier(exported.Tendermint, 0))
+ clientStore.Set(host.ClientStateKey(), []byte("clientState"))
+
+ for i := 0; i < 10; i++ {
+ clientStore.Set(host.ConsensusStateKey(clienttypes.NewHeight(1, uint64(i))), []byte("consensusState"))
+ }
+ },
+ false,
+ },
+ {
+ "06-solomachine client state and consensus states remain in client store",
+ func() {
+ clientStore = suite.chainA.GetSimApp().IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clienttypes.FormatClientIdentifier(exported.Solomachine, 0))
+ clientStore.Set(host.ClientStateKey(), []byte("clientState"))
+
+ for i := 0; i < 10; i++ {
+ clientStore.Set(host.ConsensusStateKey(clienttypes.NewHeight(1, uint64(i))), []byte("consensusState"))
+ }
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+ suite.SetupTest() // reset
+
+ ctx := suite.chainA.GetContext()
+ clientStore = suite.chainA.GetSimApp().IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), v5.Localhost)
+
+ tc.malleate()
+
+ v5.MigrateToV5(ctx, suite.chainA.GetSimApp().IBCKeeper.ClientKeeper)
+
+ if tc.expPass {
+ suite.Require().False(clientStore.Has(host.ClientStateKey()))
+
+ for i := 0; i < 10; i++ {
+ suite.Require().False(clientStore.Has(host.ConsensusStateKey(clienttypes.NewHeight(1, uint64(i)))))
+ }
+ } else {
+ suite.Require().True(clientStore.Has(host.ClientStateKey()))
+
+ for i := 0; i < 10; i++ {
+ suite.Require().True(clientStore.Has(host.ConsensusStateKey(clienttypes.NewHeight(1, uint64(i)))))
+ }
+ }
+ })
+ }
+}
diff --git a/modules/core/module.go b/modules/core/module.go
index 19b5d445fb7..a2888a6d6bf 100644
--- a/modules/core/module.go
+++ b/modules/core/module.go
@@ -98,9 +98,6 @@ func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry)
type AppModule struct {
AppModuleBasic
keeper *keeper.Keeper
-
- // create localhost by default
- createLocalhost bool
}
// NewAppModule creates a new AppModule object
@@ -157,7 +154,7 @@ func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, bz json.Ra
if err != nil {
panic(fmt.Sprintf("failed to unmarshal %s genesis state: %s", host.ModuleName, err))
}
- InitGenesis(ctx, *am.keeper, am.createLocalhost, &gs)
+ InitGenesis(ctx, *am.keeper, &gs)
return []abci.ValidatorUpdate{}
}
diff --git a/modules/core/simulation/decoder_test.go b/modules/core/simulation/decoder_test.go
index c9575ccbe31..6701dca6b6f 100644
--- a/modules/core/simulation/decoder_test.go
+++ b/modules/core/simulation/decoder_test.go
@@ -12,7 +12,7 @@ import (
channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/simulation"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
"github.com/cosmos/ibc-go/v5/testing/simapp"
)
@@ -25,7 +25,7 @@ func TestDecodeStore(t *testing.T) {
channelID := "channelidone"
portID := "portidone"
- clientState := &ibctmtypes.ClientState{
+ clientState := &ibctm.ClientState{
FrozenHeight: clienttypes.NewHeight(0, 10),
}
connection := connectiontypes.ConnectionEnd{
diff --git a/modules/core/types/codec.go b/modules/core/types/codec.go
index d597141005f..5911d6d7215 100644
--- a/modules/core/types/codec.go
+++ b/modules/core/types/codec.go
@@ -7,9 +7,8 @@ import (
connectiontypes "github.com/cosmos/ibc-go/v5/modules/core/03-connection/types"
channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
- solomachinetypes "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
- localhosttypes "github.com/cosmos/ibc-go/v5/modules/light-clients/09-localhost/types"
+ solomachinetypes "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
)
// RegisterInterfaces registers x/ibc interfaces into protobuf Any.
@@ -18,7 +17,6 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
connectiontypes.RegisterInterfaces(registry)
channeltypes.RegisterInterfaces(registry)
solomachinetypes.RegisterInterfaces(registry)
- ibctmtypes.RegisterInterfaces(registry)
- localhosttypes.RegisterInterfaces(registry)
+ ibctm.RegisterInterfaces(registry)
commitmenttypes.RegisterInterfaces(registry)
}
diff --git a/modules/light-clients/06-solomachine/client_state.go b/modules/light-clients/06-solomachine/client_state.go
new file mode 100644
index 00000000000..29474f0d32b
--- /dev/null
+++ b/modules/light-clients/06-solomachine/client_state.go
@@ -0,0 +1,260 @@
+package solomachine
+
+import (
+ "reflect"
+
+ "github.com/cosmos/cosmos-sdk/codec"
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
+ "github.com/cosmos/cosmos-sdk/types/tx/signing"
+
+ clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
+ commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
+ host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
+ "github.com/cosmos/ibc-go/v5/modules/core/exported"
+)
+
+var _ exported.ClientState = (*ClientState)(nil)
+
+// NewClientState creates a new ClientState instance.
+func NewClientState(latestSequence uint64, consensusState *ConsensusState, allowUpdateAfterProposal bool) *ClientState {
+ return &ClientState{
+ Sequence: latestSequence,
+ IsFrozen: false,
+ ConsensusState: consensusState,
+ AllowUpdateAfterProposal: allowUpdateAfterProposal,
+ }
+}
+
+// ClientType is Solo Machine.
+func (cs ClientState) ClientType() string {
+ return exported.Solomachine
+}
+
+// GetLatestHeight returns the latest sequence number.
+// Return exported.Height to satisfy ClientState interface
+// Revision number is always 0 for a solo-machine.
+func (cs ClientState) GetLatestHeight() exported.Height {
+ return clienttypes.NewHeight(0, cs.Sequence)
+}
+
+// GetTimestampAtHeight returns the timestamp in nanoseconds of the consensus state at the given height.
+func (cs ClientState) GetTimestampAtHeight(
+ _ sdk.Context,
+ clientStore sdk.KVStore,
+ cdc codec.BinaryCodec,
+ height exported.Height,
+) (uint64, error) {
+ if !cs.GetLatestHeight().EQ(height) {
+ return 0, sdkerrors.Wrapf(ErrInvalidSequence, "not latest height (%s)", height)
+ }
+ return cs.ConsensusState.Timestamp, nil
+}
+
+// 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.BinaryCodec) exported.Status {
+ if cs.IsFrozen {
+ return exported.Frozen
+ }
+
+ return exported.Active
+}
+
+// Validate performs basic validation of the client state fields.
+func (cs ClientState) Validate() error {
+ if cs.Sequence == 0 {
+ return sdkerrors.Wrap(clienttypes.ErrInvalidClient, "sequence cannot be 0")
+ }
+ if cs.ConsensusState == nil {
+ return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "consensus state cannot be nil")
+ }
+ return cs.ConsensusState.ValidateBasic()
+}
+
+// ZeroCustomFields returns solomachine client state with client-specific fields FrozenSequence,
+// and AllowUpdateAfterProposal zeroed out
+func (cs ClientState) ZeroCustomFields() exported.ClientState {
+ return NewClientState(
+ cs.Sequence, cs.ConsensusState, false,
+ )
+}
+
+// Initialize will check that initial consensus state is equal to the latest consensus state of the initial client.
+func (cs ClientState) Initialize(_ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore, consState exported.ConsensusState) error {
+ if !reflect.DeepEqual(cs.ConsensusState, consState) {
+ return sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "consensus state in initial client does not equal initial consensus state. expected: %s, got: %s",
+ cs.ConsensusState, consState)
+ }
+ return nil
+}
+
+// ExportMetadata is a no-op since solomachine does not store any metadata in client store
+func (cs ClientState) ExportMetadata(_ sdk.KVStore) []exported.GenesisMetadata {
+ return nil
+}
+
+// VerifyUpgradeAndUpdateState returns an error since solomachine client does not support upgrades
+func (cs ClientState) VerifyUpgradeAndUpdateState(
+ _ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore,
+ _ exported.ClientState, _ exported.ConsensusState, _, _ []byte,
+) error {
+ return sdkerrors.Wrap(clienttypes.ErrInvalidUpgradeClient, "cannot upgrade solomachine client")
+}
+
+// VerifyMembership is a generic proof verification method which verifies a proof of the existence of a value at a given CommitmentPath at the specified height.
+// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24).
+func (cs *ClientState) VerifyMembership(
+ ctx sdk.Context,
+ clientStore sdk.KVStore,
+ cdc codec.BinaryCodec,
+ height exported.Height,
+ delayTimePeriod uint64,
+ delayBlockPeriod uint64,
+ proof []byte,
+ path []byte,
+ value []byte,
+) error {
+ publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, proof)
+ if err != nil {
+ return err
+ }
+
+ var merklePath commitmenttypes.MerklePath
+ if err := cdc.Unmarshal(path, &merklePath); err != nil {
+ return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "failed to unmarshal path into ICS 23 commitment merkle path")
+ }
+
+ signBytes := &SignBytes{
+ Sequence: sequence,
+ Timestamp: timestamp,
+ Diversifier: cs.ConsensusState.Diversifier,
+ Path: []byte(merklePath.String()),
+ Data: value,
+ }
+
+ signBz, err := cdc.Marshal(signBytes)
+ if err != nil {
+ return err
+ }
+
+ if err := VerifySignature(publicKey, signBz, sigData); err != nil {
+ return err
+ }
+
+ cs.Sequence++
+ cs.ConsensusState.Timestamp = timestamp
+ setClientState(clientStore, cdc, cs)
+
+ return nil
+}
+
+// VerifyNonMembership is a generic proof verification method which verifies the absence of a given CommitmentPath at a specified height.
+// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24).
+func (cs *ClientState) VerifyNonMembership(
+ ctx sdk.Context,
+ clientStore sdk.KVStore,
+ cdc codec.BinaryCodec,
+ height exported.Height,
+ delayTimePeriod uint64,
+ delayBlockPeriod uint64,
+ proof []byte,
+ path []byte,
+) error {
+ publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, proof)
+ if err != nil {
+ return err
+ }
+
+ var merklePath commitmenttypes.MerklePath
+ if err := cdc.Unmarshal(path, &merklePath); err != nil {
+ return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "failed to unmarshal path into ICS 23 commitment merkle path")
+ }
+
+ signBytes := &SignBytes{
+ Sequence: sequence,
+ Timestamp: timestamp,
+ Diversifier: cs.ConsensusState.Diversifier,
+ Path: []byte(merklePath.String()),
+ Data: nil,
+ }
+
+ signBz, err := cdc.Marshal(signBytes)
+ if err != nil {
+ return err
+ }
+
+ if err := VerifySignature(publicKey, signBz, sigData); err != nil {
+ return err
+ }
+
+ cs.Sequence++
+ cs.ConsensusState.Timestamp = timestamp
+ setClientState(clientStore, cdc, cs)
+
+ return nil
+}
+
+// produceVerificationArgs perfoms the basic checks on the arguments that are
+// shared between the verification functions and returns the public key of the
+// consensus state, the unmarshalled proof representing the signature and timestamp
+// along with the solo-machine sequence encoded in the proofHeight.
+func produceVerificationArgs(
+ cdc codec.BinaryCodec,
+ cs *ClientState,
+ height exported.Height,
+ proof []byte,
+) (cryptotypes.PubKey, signing.SignatureData, uint64, uint64, error) {
+ if revision := height.GetRevisionNumber(); revision != 0 {
+ return nil, nil, 0, 0, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "revision must be 0 for solomachine, got revision-number: %d", revision)
+ }
+
+ if proof == nil {
+ return nil, nil, 0, 0, sdkerrors.Wrap(ErrInvalidProof, "proof cannot be empty")
+ }
+
+ var timestampedSigData TimestampedSignatureData
+ if err := cdc.Unmarshal(proof, ×tampedSigData); err != nil {
+ return nil, nil, 0, 0, sdkerrors.Wrapf(err, "failed to unmarshal proof into type %T", timestampedSigData)
+ }
+
+ timestamp := timestampedSigData.Timestamp
+ if len(timestampedSigData.SignatureData) == 0 {
+ return nil, nil, 0, 0, sdkerrors.Wrap(ErrInvalidProof, "signature data cannot be empty")
+ }
+
+ sigData, err := UnmarshalSignatureData(cdc, timestampedSigData.SignatureData)
+ if err != nil {
+ return nil, nil, 0, 0, err
+ }
+
+ // sequence is encoded in the revision height of height struct
+ sequence := height.GetRevisionHeight()
+ latestSequence := cs.GetLatestHeight().GetRevisionHeight()
+ if latestSequence != sequence {
+ return nil, nil, 0, 0, sdkerrors.Wrapf(
+ sdkerrors.ErrInvalidHeight,
+ "client state sequence != proof sequence (%d != %d)", latestSequence, sequence,
+ )
+ }
+
+ if cs.ConsensusState.GetTimestamp() > timestamp {
+ return nil, nil, 0, 0, sdkerrors.Wrapf(ErrInvalidProof, "the consensus state timestamp is greater than the signature timestamp (%d >= %d)", cs.ConsensusState.GetTimestamp(), timestamp)
+ }
+
+ publicKey, err := cs.ConsensusState.GetPubKey()
+ if err != nil {
+ return nil, nil, 0, 0, err
+ }
+
+ return publicKey, sigData, timestamp, sequence, nil
+}
+
+// sets the client state to the store
+func setClientState(store sdk.KVStore, cdc codec.BinaryCodec, clientState exported.ClientState) {
+ bz := clienttypes.MustMarshalClientState(cdc, clientState)
+ store.Set([]byte(host.KeyClientState), bz)
+}
diff --git a/modules/light-clients/06-solomachine/client_state_test.go b/modules/light-clients/06-solomachine/client_state_test.go
new file mode 100644
index 00000000000..68bf15cace9
--- /dev/null
+++ b/modules/light-clients/06-solomachine/client_state_test.go
@@ -0,0 +1,875 @@
+package solomachine_test
+
+import (
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
+ channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
+ commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
+ "github.com/cosmos/ibc-go/v5/modules/core/exported"
+ solomachine "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
+ ibctesting "github.com/cosmos/ibc-go/v5/testing"
+)
+
+const (
+ counterpartyClientIdentifier = "chainA"
+ testConnectionID = "connectionid"
+ testChannelID = "testchannelid"
+ testPortID = "testportid"
+)
+
+func (suite *SoloMachineTestSuite) TestStatus() {
+ clientState := suite.solomachine.ClientState()
+ // solo machine discards arguments
+ status := clientState.Status(suite.chainA.GetContext(), nil, nil)
+ suite.Require().Equal(exported.Active, status)
+
+ // freeze solo machine
+ clientState.IsFrozen = true
+ 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 _, sm := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
+
+ testCases := []struct {
+ name string
+ clientState *solomachine.ClientState
+ expPass bool
+ }{
+ {
+ "valid client state",
+ sm.ClientState(),
+ true,
+ },
+ {
+ "empty ClientState",
+ &solomachine.ClientState{},
+ false,
+ },
+ {
+ "sequence is zero",
+ solomachine.NewClientState(0, &solomachine.ConsensusState{sm.ConsensusState().PublicKey, sm.Diversifier, sm.Time}, false),
+ false,
+ },
+ {
+ "timestamp is zero",
+ solomachine.NewClientState(1, &solomachine.ConsensusState{sm.ConsensusState().PublicKey, sm.Diversifier, 0}, false),
+ false,
+ },
+ {
+ "diversifier is blank",
+ solomachine.NewClientState(1, &solomachine.ConsensusState{sm.ConsensusState().PublicKey, " ", 1}, false),
+ false,
+ },
+ {
+ "pubkey is empty",
+ solomachine.NewClientState(1, &solomachine.ConsensusState{nil, sm.Diversifier, sm.Time}, false),
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+
+ err := tc.clientState.Validate()
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+ }
+}
+
+func (suite *SoloMachineTestSuite) TestInitialize() {
+ // test singlesig and multisig public keys
+ for _, sm := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
+ malleatedConsensus := sm.ClientState().ConsensusState
+ malleatedConsensus.Timestamp = malleatedConsensus.Timestamp + 10
+
+ testCases := []struct {
+ name string
+ consState exported.ConsensusState
+ expPass bool
+ }{
+ {
+ "valid consensus state",
+ sm.ConsensusState(),
+ true,
+ },
+ {
+ "nil consensus state",
+ nil,
+ false,
+ },
+ {
+ "invalid consensus state: Tendermint consensus state",
+ &ibctm.ConsensusState{},
+ false,
+ },
+ {
+ "invalid consensus state: consensus state does not match consensus state in client",
+ malleatedConsensus,
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ err := sm.ClientState().Initialize(
+ suite.chainA.GetContext(), suite.chainA.Codec,
+ suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "solomachine"),
+ tc.consState,
+ )
+
+ if tc.expPass {
+ suite.Require().NoError(err, "valid testcase: %s failed", tc.name)
+ } else {
+ suite.Require().Error(err, "invalid testcase: %s passed", tc.name)
+ }
+ }
+ }
+}
+
+func (suite *SoloMachineTestSuite) TestVerifyMembership() {
+ // test singlesig and multisig public keys
+ for _, sm := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
+
+ var (
+ clientState *solomachine.ClientState
+ err error
+ height clienttypes.Height
+ path []byte
+ proof []byte
+ testingPath *ibctesting.Path
+ signBytes solomachine.SignBytes
+ )
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "success",
+ func() {},
+ true,
+ },
+ {
+ "success: client state verification",
+ func() {
+ clientState = sm.ClientState()
+ clientStateBz, err := suite.chainA.Codec.Marshal(clientState)
+ suite.Require().NoError(err)
+
+ merklePath := suite.solomachine.GetClientStatePath(counterpartyClientIdentifier)
+ signBytes = solomachine.SignBytes{
+ Sequence: sm.GetHeight().GetRevisionHeight(),
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte(merklePath.String()),
+ Data: clientStateBz,
+ }
+
+ signBz, err := suite.chainA.Codec.Marshal(&signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(signBz)
+
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: sig,
+ Timestamp: sm.Time,
+ }
+
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+
+ },
+ true,
+ },
+ {
+ "success: consensus state verification",
+ func() {
+ clientState = sm.ClientState()
+ consensusState := clientState.ConsensusState
+ consensusStateBz, err := suite.chainA.Codec.Marshal(consensusState)
+ suite.Require().NoError(err)
+
+ merklePath := sm.GetConsensusStatePath(counterpartyClientIdentifier, height)
+ signBytes = solomachine.SignBytes{
+ Sequence: sm.Sequence,
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte(merklePath.String()),
+ Data: consensusStateBz,
+ }
+
+ signBz, err := suite.chainA.Codec.Marshal(&signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(signBz)
+
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: sig,
+ Timestamp: sm.Time,
+ }
+
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ {
+ "success: connection state verification",
+ func() {
+ suite.coordinator.SetupConnections(testingPath)
+
+ connectionEnd, found := suite.chainA.GetSimApp().IBCKeeper.ConnectionKeeper.GetConnection(suite.chainA.GetContext(), ibctesting.FirstConnectionID)
+ suite.Require().True(found)
+
+ connectionEndBz, err := suite.chainA.Codec.Marshal(&connectionEnd)
+ suite.Require().NoError(err)
+
+ merklePath := sm.GetConnectionStatePath(ibctesting.FirstConnectionID)
+ signBytes = solomachine.SignBytes{
+ Sequence: sm.Sequence,
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte(merklePath.String()),
+ Data: connectionEndBz,
+ }
+
+ signBz, err := suite.chainA.Codec.Marshal(&signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(signBz)
+
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: sig,
+ Timestamp: sm.Time,
+ }
+
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ {
+ "success: channel state verification",
+ func() {
+ suite.coordinator.SetupConnections(testingPath)
+ suite.coordinator.CreateMockChannels(testingPath)
+
+ channelEnd, found := suite.chainA.GetSimApp().IBCKeeper.ChannelKeeper.GetChannel(suite.chainA.GetContext(), ibctesting.MockPort, ibctesting.FirstChannelID)
+ suite.Require().True(found)
+
+ channelEndBz, err := suite.chainA.Codec.Marshal(&channelEnd)
+ suite.Require().NoError(err)
+
+ merklePath := sm.GetChannelStatePath(ibctesting.MockPort, ibctesting.FirstChannelID)
+ signBytes = solomachine.SignBytes{
+ Sequence: sm.Sequence,
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte(merklePath.String()),
+ Data: channelEndBz,
+ }
+
+ signBz, err := suite.chainA.Codec.Marshal(&signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(signBz)
+
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: sig,
+ Timestamp: sm.Time,
+ }
+
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ {
+ "success: next sequence recv verification",
+ func() {
+ suite.coordinator.SetupConnections(testingPath)
+ suite.coordinator.CreateMockChannels(testingPath)
+
+ nextSeqRecv, found := suite.chainA.GetSimApp().IBCKeeper.ChannelKeeper.GetNextSequenceRecv(suite.chainA.GetContext(), ibctesting.MockPort, ibctesting.FirstChannelID)
+ suite.Require().True(found)
+
+ merklePath := sm.GetNextSequenceRecvPath(ibctesting.MockPort, ibctesting.FirstChannelID)
+ signBytes = solomachine.SignBytes{
+ Sequence: sm.Sequence,
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte(merklePath.String()),
+ Data: sdk.Uint64ToBigEndian(nextSeqRecv),
+ }
+
+ signBz, err := suite.chainA.Codec.Marshal(&signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(signBz)
+
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: sig,
+ Timestamp: sm.Time,
+ }
+
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ {
+ "success: packet commitment verification",
+ func() {
+ packet := channeltypes.NewPacket(
+ ibctesting.MockPacketData,
+ 1,
+ ibctesting.MockPort,
+ ibctesting.FirstChannelID,
+ ibctesting.MockPort,
+ ibctesting.FirstChannelID,
+ clienttypes.NewHeight(0, 10),
+ 0,
+ )
+
+ commitmentBz := channeltypes.CommitPacket(suite.chainA.Codec, packet)
+ merklePath := sm.GetPacketCommitmentPath(ibctesting.MockPort, ibctesting.FirstChannelID)
+ signBytes = solomachine.SignBytes{
+ Sequence: sm.Sequence,
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte(merklePath.String()),
+ Data: commitmentBz,
+ }
+
+ signBz, err := suite.chainA.Codec.Marshal(&signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(signBz)
+
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: sig,
+ Timestamp: sm.Time,
+ }
+
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ {
+ "success: packet acknowledgement verification",
+ func() {
+ merklePath := sm.GetPacketAcknowledgementPath(ibctesting.MockPort, ibctesting.FirstChannelID)
+ signBytes = solomachine.SignBytes{
+ Sequence: sm.Sequence,
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte(merklePath.String()),
+ Data: ibctesting.MockAcknowledgement,
+ }
+
+ signBz, err := suite.chainA.Codec.Marshal(&signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(signBz)
+
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: sig,
+ Timestamp: sm.Time,
+ }
+
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ {
+ "success: packet receipt verification",
+ func() {
+ merklePath := sm.GetPacketReceiptPath(ibctesting.MockPort, ibctesting.FirstChannelID)
+ signBytes = solomachine.SignBytes{
+ Sequence: sm.Sequence,
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte(merklePath.String()),
+ Data: []byte{byte(1)}, // packet receipt is stored as a single byte
+ }
+
+ signBz, err := suite.chainA.Codec.Marshal(&signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(signBz)
+
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: sig,
+ Timestamp: sm.Time,
+ }
+
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ {
+ "client state latest height is less than sequence",
+ func() {
+ consensusState := &solomachine.ConsensusState{
+ Timestamp: sm.Time,
+ PublicKey: sm.ConsensusState().PublicKey,
+ }
+
+ clientState = solomachine.NewClientState(sm.Sequence-1, consensusState, false)
+ },
+ false,
+ },
+ {
+ "height revision number is not zero",
+ func() {
+ height = clienttypes.NewHeight(1, sm.GetHeight().GetRevisionHeight())
+ },
+ false,
+ },
+ {
+ "malformed merkle path fails to unmarshal",
+ func() {
+ path = []byte("invalid path")
+ },
+ false,
+ },
+ {
+ "malformed proof fails to unmarshal",
+ func() {
+ merklePath := suite.solomachine.GetClientStatePath(counterpartyClientIdentifier)
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof = []byte("invalid proof")
+ },
+ false,
+ },
+ {
+ "consensus state timestamp is greater than signature",
+ func() {
+ consensusState := &solomachine.ConsensusState{
+ Timestamp: sm.Time + 1,
+ PublicKey: sm.ConsensusState().PublicKey,
+ }
+
+ clientState = solomachine.NewClientState(sm.Sequence, consensusState, false)
+ },
+ false,
+ },
+ {
+ "signature data is nil",
+ func() {
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: nil,
+ Timestamp: sm.Time,
+ }
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+ },
+ false,
+ },
+ {
+ "consensus state public key is nil",
+ func() {
+ clientState.ConsensusState.PublicKey = nil
+ },
+ false,
+ },
+ {
+ "malformed signature data fails to unmarshal",
+ func() {
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: []byte("invalid signature data"),
+ Timestamp: sm.Time,
+ }
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+ },
+ false,
+ },
+ {
+ "proof is nil",
+ func() {
+ proof = nil
+ },
+ false,
+ },
+ {
+ "proof verification failed",
+ func() {
+ signBytes.Data = []byte("invalid membership data value")
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+ suite.SetupTest()
+ testingPath = ibctesting.NewPath(suite.chainA, suite.chainB)
+
+ clientState = sm.ClientState()
+ height = clienttypes.NewHeight(sm.GetHeight().GetRevisionNumber(), sm.GetHeight().GetRevisionHeight())
+
+ merklePath := commitmenttypes.NewMerklePath("ibc", "solomachine")
+ signBytes = solomachine.SignBytes{
+ Sequence: sm.GetHeight().GetRevisionHeight(),
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte(merklePath.String()),
+ Data: []byte("solomachine"),
+ }
+
+ signBz, err := suite.chainA.Codec.Marshal(&signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(signBz)
+
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: sig,
+ Timestamp: sm.Time,
+ }
+
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+
+ tc.malleate()
+
+ var expSeq uint64
+ if clientState.ConsensusState != nil {
+ expSeq = clientState.Sequence + 1
+ }
+
+ err = clientState.VerifyMembership(
+ suite.chainA.GetContext(), suite.store, suite.chainA.Codec,
+ height, 0, 0, // solomachine does not check delay periods
+ proof, path, signBytes.Data,
+ )
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ suite.Require().Equal(expSeq, clientState.Sequence)
+ suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %s", suite.GetSequenceFromStore(), tc.name)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+ }
+}
+
+func (suite *SoloMachineTestSuite) TestVerifyNonMembership() {
+ // test singlesig and multisig public keys
+ for _, sm := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
+
+ var (
+ clientState *solomachine.ClientState
+ err error
+ height clienttypes.Height
+ path []byte
+ proof []byte
+ signBytes solomachine.SignBytes
+ )
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "success",
+ func() {},
+ true,
+ },
+ {
+ "success: packet receipt absence verification",
+ func() {
+ merklePath := suite.solomachine.GetPacketReceiptPath(ibctesting.MockPort, ibctesting.FirstChannelID)
+ signBytes = solomachine.SignBytes{
+ Sequence: sm.GetHeight().GetRevisionHeight(),
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte(merklePath.String()),
+ Data: nil,
+ }
+
+ signBz, err := suite.chainA.Codec.Marshal(&signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(signBz)
+
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: sig,
+ Timestamp: sm.Time,
+ }
+
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ {
+ "client state latest height is less than sequence",
+ func() {
+ consensusState := &solomachine.ConsensusState{
+ Timestamp: sm.Time,
+ PublicKey: sm.ConsensusState().PublicKey,
+ }
+
+ clientState = solomachine.NewClientState(sm.Sequence-1, consensusState, false)
+ },
+ false,
+ },
+ {
+ "height revision number is not zero",
+ func() {
+ height = clienttypes.NewHeight(1, sm.GetHeight().GetRevisionHeight())
+ },
+ false,
+ },
+ {
+ "malformed merkle path fails to unmarshal",
+ func() {
+ path = []byte("invalid path")
+ },
+ false,
+ },
+ {
+ "malformed proof fails to unmarshal",
+ func() {
+ merklePath := suite.solomachine.GetClientStatePath(counterpartyClientIdentifier)
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof = []byte("invalid proof")
+ },
+ false,
+ },
+ {
+ "consensus state timestamp is greater than signature",
+ func() {
+ consensusState := &solomachine.ConsensusState{
+ Timestamp: sm.Time + 1,
+ PublicKey: sm.ConsensusState().PublicKey,
+ }
+
+ clientState = solomachine.NewClientState(sm.Sequence, consensusState, false)
+ },
+ false,
+ },
+ {
+ "signature data is nil",
+ func() {
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: nil,
+ Timestamp: sm.Time,
+ }
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+ },
+ false,
+ },
+ {
+ "consensus state public key is nil",
+ func() {
+ clientState.ConsensusState.PublicKey = nil
+ },
+ false,
+ },
+ {
+ "malformed signature data fails to unmarshal",
+ func() {
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: []byte("invalid signature data"),
+ Timestamp: sm.Time,
+ }
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+ },
+ false,
+ },
+ {
+ "proof is nil",
+ func() {
+ proof = nil
+ },
+ false,
+ },
+ {
+ "proof verification failed",
+ func() {
+ signBytes.Data = []byte("invalid non-membership data value")
+
+ signBz, err := suite.chainA.Codec.Marshal(&signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(signBz)
+
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: sig,
+ Timestamp: sm.Time,
+ }
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+ clientState = sm.ClientState()
+ height = clienttypes.NewHeight(sm.GetHeight().GetRevisionNumber(), sm.GetHeight().GetRevisionHeight())
+
+ merklePath := commitmenttypes.NewMerklePath("ibc", "solomachine")
+ signBytes = solomachine.SignBytes{
+ Sequence: sm.GetHeight().GetRevisionHeight(),
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte(merklePath.String()),
+ Data: nil,
+ }
+
+ signBz, err := suite.chainA.Codec.Marshal(&signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(signBz)
+
+ signatureDoc := &solomachine.TimestampedSignatureData{
+ SignatureData: sig,
+ Timestamp: sm.Time,
+ }
+
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, err = suite.chainA.Codec.Marshal(signatureDoc)
+ suite.Require().NoError(err)
+
+ tc.malleate()
+
+ var expSeq uint64
+ if clientState.ConsensusState != nil {
+ expSeq = clientState.Sequence + 1
+ }
+
+ err = clientState.VerifyNonMembership(
+ suite.chainA.GetContext(), suite.store, suite.chainA.Codec,
+ height, 0, 0, // solomachine does not check delay periods
+ proof, path,
+ )
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ suite.Require().Equal(expSeq, clientState.Sequence)
+ suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %s", suite.GetSequenceFromStore(), tc.name)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+ }
+}
+
+func (suite *SoloMachineTestSuite) TestGetTimestampAtHeight() {
+ tmPath := ibctesting.NewPath(suite.chainA, suite.chainB)
+ suite.coordinator.SetupClients(tmPath)
+ // Single setup for all test cases.
+ suite.SetupTest()
+
+ testCases := []struct {
+ name string
+ clientState *solomachine.ClientState
+ height exported.Height
+ expValue uint64
+ expPass bool
+ }{
+ {
+ name: "get timestamp at height exists",
+ clientState: suite.solomachine.ClientState(),
+ height: suite.solomachine.ClientState().GetLatestHeight(),
+ expValue: suite.solomachine.ClientState().ConsensusState.Timestamp,
+ expPass: true,
+ },
+ {
+ name: "get timestamp at height not exists",
+ clientState: suite.solomachine.ClientState(),
+ height: suite.solomachine.ClientState().GetLatestHeight().Increment(),
+ },
+ }
+
+ for i, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+ ctx := suite.chainA.GetContext()
+
+ ts, err := tc.clientState.GetTimestampAtHeight(
+ ctx, suite.store, suite.chainA.Codec, tc.height,
+ )
+
+ suite.Require().Equal(tc.expValue, ts)
+
+ if tc.expPass {
+ suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
+ } else {
+ suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
+ }
+ })
+ }
+}
diff --git a/modules/light-clients/06-solomachine/codec.go b/modules/light-clients/06-solomachine/codec.go
new file mode 100644
index 00000000000..2792e19c759
--- /dev/null
+++ b/modules/light-clients/06-solomachine/codec.go
@@ -0,0 +1,42 @@
+package solomachine
+
+import (
+ "github.com/cosmos/cosmos-sdk/codec"
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
+ "github.com/cosmos/cosmos-sdk/types/tx/signing"
+
+ "github.com/cosmos/ibc-go/v5/modules/core/exported"
+)
+
+// RegisterInterfaces register the ibc channel submodule interfaces to protobuf
+// Any.
+func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
+ registry.RegisterImplementations(
+ (*exported.ClientState)(nil),
+ &ClientState{},
+ )
+ registry.RegisterImplementations(
+ (*exported.ConsensusState)(nil),
+ &ConsensusState{},
+ )
+ registry.RegisterImplementations(
+ (*exported.ClientMessage)(nil),
+ &Header{},
+ )
+ registry.RegisterImplementations(
+ (*exported.ClientMessage)(nil),
+ &Misbehaviour{},
+ )
+}
+
+func UnmarshalSignatureData(cdc codec.BinaryCodec, data []byte) (signing.SignatureData, error) {
+ protoSigData := &signing.SignatureDescriptor_Data{}
+ if err := cdc.Unmarshal(data, protoSigData); err != nil {
+ return nil, sdkerrors.Wrapf(err, "failed to unmarshal proof into type %T", protoSigData)
+ }
+
+ sigData := signing.SignatureDataFromProto(protoSigData)
+
+ return sigData, nil
+}
diff --git a/modules/light-clients/06-solomachine/types/consensus_state.go b/modules/light-clients/06-solomachine/consensus_state.go
similarity index 92%
rename from modules/light-clients/06-solomachine/types/consensus_state.go
rename to modules/light-clients/06-solomachine/consensus_state.go
index 76a034b2760..1f63823663f 100644
--- a/modules/light-clients/06-solomachine/types/consensus_state.go
+++ b/modules/light-clients/06-solomachine/consensus_state.go
@@ -1,4 +1,4 @@
-package types
+package solomachine
import (
"strings"
@@ -22,11 +22,6 @@ func (cs ConsensusState) GetTimestamp() uint64 {
return cs.Timestamp
}
-// GetRoot returns nil since solo machines do not have roots.
-func (cs ConsensusState) GetRoot() exported.Root {
- return nil
-}
-
// GetPubKey unmarshals the public key into a cryptotypes.PubKey type.
// An error is returned if the public key is nil or the cached value
// is not a PubKey.
diff --git a/modules/light-clients/06-solomachine/types/consensus_state_test.go b/modules/light-clients/06-solomachine/consensus_state_test.go
similarity index 62%
rename from modules/light-clients/06-solomachine/types/consensus_state_test.go
rename to modules/light-clients/06-solomachine/consensus_state_test.go
index 5a2f519af1e..6319c418931 100644
--- a/modules/light-clients/06-solomachine/types/consensus_state_test.go
+++ b/modules/light-clients/06-solomachine/consensus_state_test.go
@@ -1,8 +1,8 @@
-package types_test
+package solomachine_test
import (
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
+ solomachine "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -11,46 +11,45 @@ func (suite *SoloMachineTestSuite) TestConsensusState() {
suite.Require().Equal(exported.Solomachine, consensusState.ClientType())
suite.Require().Equal(suite.solomachine.Time, consensusState.GetTimestamp())
- suite.Require().Nil(consensusState.GetRoot())
}
func (suite *SoloMachineTestSuite) TestConsensusStateValidateBasic() {
// test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
+ for _, sm := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
testCases := []struct {
name string
- consensusState *types.ConsensusState
+ consensusState *solomachine.ConsensusState
expPass bool
}{
{
"valid consensus state",
- solomachine.ConsensusState(),
+ sm.ConsensusState(),
true,
},
{
"timestamp is zero",
- &types.ConsensusState{
- PublicKey: solomachine.ConsensusState().PublicKey,
+ &solomachine.ConsensusState{
+ PublicKey: sm.ConsensusState().PublicKey,
Timestamp: 0,
- Diversifier: solomachine.Diversifier,
+ Diversifier: sm.Diversifier,
},
false,
},
{
"diversifier is blank",
- &types.ConsensusState{
- PublicKey: solomachine.ConsensusState().PublicKey,
- Timestamp: solomachine.Time,
+ &solomachine.ConsensusState{
+ PublicKey: sm.ConsensusState().PublicKey,
+ Timestamp: sm.Time,
Diversifier: " ",
},
false,
},
{
"pubkey is nil",
- &types.ConsensusState{
- Timestamp: solomachine.Time,
- Diversifier: solomachine.Diversifier,
+ &solomachine.ConsensusState{
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
PublicKey: nil,
},
false,
diff --git a/modules/light-clients/06-solomachine/types/errors.go b/modules/light-clients/06-solomachine/errors.go
similarity index 85%
rename from modules/light-clients/06-solomachine/types/errors.go
rename to modules/light-clients/06-solomachine/errors.go
index 3e27f60732a..7f41349337d 100644
--- a/modules/light-clients/06-solomachine/types/errors.go
+++ b/modules/light-clients/06-solomachine/errors.go
@@ -1,4 +1,4 @@
-package types
+package solomachine
import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
@@ -14,5 +14,4 @@ var (
ErrInvalidSignatureAndData = sdkerrors.Register(SubModuleName, 4, "invalid signature and data")
ErrSignatureVerificationFailed = sdkerrors.Register(SubModuleName, 5, "signature verification failed")
ErrInvalidProof = sdkerrors.Register(SubModuleName, 6, "invalid solo machine proof")
- ErrInvalidDataType = sdkerrors.Register(SubModuleName, 7, "invalid data type")
)
diff --git a/modules/light-clients/06-solomachine/types/header.go b/modules/light-clients/06-solomachine/header.go
similarity index 85%
rename from modules/light-clients/06-solomachine/types/header.go
rename to modules/light-clients/06-solomachine/header.go
index e22d0d605a9..b5bfe11f28d 100644
--- a/modules/light-clients/06-solomachine/types/header.go
+++ b/modules/light-clients/06-solomachine/header.go
@@ -1,4 +1,4 @@
-package types
+package solomachine
import (
"strings"
@@ -10,20 +10,13 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/exported"
)
-var _ exported.Header = &Header{}
+var _ exported.ClientMessage = &Header{}
// ClientType defines that the Header is a Solo Machine.
func (Header) ClientType() string {
return exported.Solomachine
}
-// GetHeight returns the current sequence number as the height.
-// Return clientexported.Height to satisfy interface
-// Revision number is always 0 for a solo-machine
-func (h Header) GetHeight() exported.Height {
- return clienttypes.NewHeight(0, h.Sequence)
-}
-
// GetPubKey unmarshals the new public key into a cryptotypes.PubKey type.
// An error is returned if the new public key is nil or the cached value
// is not a PubKey.
diff --git a/modules/light-clients/06-solomachine/types/header_test.go b/modules/light-clients/06-solomachine/header_test.go
similarity index 82%
rename from modules/light-clients/06-solomachine/types/header_test.go
rename to modules/light-clients/06-solomachine/header_test.go
index fb771b4c684..1a0ce46ee33 100644
--- a/modules/light-clients/06-solomachine/types/header_test.go
+++ b/modules/light-clients/06-solomachine/header_test.go
@@ -1,20 +1,20 @@
-package types_test
+package solomachine_test
import (
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
+ solomachine "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
func (suite *SoloMachineTestSuite) TestHeaderValidateBasic() {
// test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
+ for _, sm := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
- header := solomachine.CreateHeader()
+ header := sm.CreateHeader(sm.Diversifier)
cases := []struct {
name string
- header *types.Header
+ header *solomachine.Header
expPass bool
}{
{
@@ -24,7 +24,7 @@ func (suite *SoloMachineTestSuite) TestHeaderValidateBasic() {
},
{
"sequence is zero",
- &types.Header{
+ &solomachine.Header{
Sequence: 0,
Timestamp: header.Timestamp,
Signature: header.Signature,
@@ -35,7 +35,7 @@ func (suite *SoloMachineTestSuite) TestHeaderValidateBasic() {
},
{
"timestamp is zero",
- &types.Header{
+ &solomachine.Header{
Sequence: header.Sequence,
Timestamp: 0,
Signature: header.Signature,
@@ -46,7 +46,7 @@ func (suite *SoloMachineTestSuite) TestHeaderValidateBasic() {
},
{
"signature is empty",
- &types.Header{
+ &solomachine.Header{
Sequence: header.Sequence,
Timestamp: header.Timestamp,
Signature: []byte{},
@@ -57,7 +57,7 @@ func (suite *SoloMachineTestSuite) TestHeaderValidateBasic() {
},
{
"diversifier contains only spaces",
- &types.Header{
+ &solomachine.Header{
Sequence: header.Sequence,
Timestamp: header.Timestamp,
Signature: header.Signature,
@@ -68,7 +68,7 @@ func (suite *SoloMachineTestSuite) TestHeaderValidateBasic() {
},
{
"public key is nil",
- &types.Header{
+ &solomachine.Header{
Sequence: header.Sequence,
Timestamp: header.Timestamp,
Signature: header.Signature,
diff --git a/modules/light-clients/06-solomachine/types/misbehaviour.go b/modules/light-clients/06-solomachine/misbehaviour.go
similarity index 83%
rename from modules/light-clients/06-solomachine/types/misbehaviour.go
rename to modules/light-clients/06-solomachine/misbehaviour.go
index d13b1407be8..526fc76e839 100644
--- a/modules/light-clients/06-solomachine/types/misbehaviour.go
+++ b/modules/light-clients/06-solomachine/misbehaviour.go
@@ -1,4 +1,4 @@
-package types
+package solomachine
import (
"bytes"
@@ -10,24 +10,19 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/exported"
)
-var _ exported.Misbehaviour = &Misbehaviour{}
+var _ exported.ClientMessage = &Misbehaviour{}
// ClientType is a Solo Machine light client.
func (misbehaviour Misbehaviour) ClientType() string {
return exported.Solomachine
}
-// GetClientID returns the ID of the client that committed a misbehaviour.
-func (misbehaviour Misbehaviour) GetClientID() string {
- return misbehaviour.ClientId
-}
-
-// Type implements Evidence interface.
+// Type implements Misbehaviour interface.
func (misbehaviour Misbehaviour) Type() string {
return exported.TypeClientMisbehaviour
}
-// ValidateBasic implements Evidence interface.
+// ValidateBasic implements Misbehaviour interface.
func (misbehaviour Misbehaviour) ValidateBasic() error {
if err := host.ClientIdentifierValidator(misbehaviour.ClientId); err != nil {
return sdkerrors.Wrap(err, "invalid client identifier for solo machine")
@@ -66,8 +61,8 @@ func (sd SignatureAndData) ValidateBasic() error {
if len(sd.Data) == 0 {
return sdkerrors.Wrap(ErrInvalidSignatureAndData, "data for signature cannot be empty")
}
- if sd.DataType == UNSPECIFIED {
- return sdkerrors.Wrap(ErrInvalidSignatureAndData, "data type cannot be UNSPECIFIED")
+ if len(sd.Path) == 0 {
+ return sdkerrors.Wrap(ErrInvalidSignatureAndData, "path for signature cannot be empty")
}
if sd.Timestamp == 0 {
return sdkerrors.Wrap(ErrInvalidSignatureAndData, "timestamp cannot be 0")
diff --git a/modules/light-clients/06-solomachine/misbehaviour_handle.go b/modules/light-clients/06-solomachine/misbehaviour_handle.go
new file mode 100644
index 00000000000..e108931b7ea
--- /dev/null
+++ b/modules/light-clients/06-solomachine/misbehaviour_handle.go
@@ -0,0 +1,46 @@
+package solomachine
+
+import (
+ "github.com/cosmos/cosmos-sdk/codec"
+
+ commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
+)
+
+// verifySignatureAndData verifies that the currently registered public key has signed
+// over the provided data and that the data is valid. The data is valid if it can be
+// unmarshaled into the specified data type.
+func (cs ClientState) verifySignatureAndData(cdc codec.BinaryCodec, misbehaviour *Misbehaviour, sigAndData *SignatureAndData) error {
+ // do not check misbehaviour timestamp since we want to allow processing of past misbehaviour
+ if err := cdc.Unmarshal(sigAndData.Path, new(commitmenttypes.MerklePath)); err != nil {
+ return err
+ }
+
+ signBytes := SignBytes{
+ Sequence: misbehaviour.Sequence,
+ Timestamp: sigAndData.Timestamp,
+ Diversifier: cs.ConsensusState.Diversifier,
+ Path: sigAndData.Path,
+ Data: sigAndData.Data,
+ }
+
+ data, err := cdc.Marshal(&signBytes)
+ if err != nil {
+ return err
+ }
+
+ sigData, err := UnmarshalSignatureData(cdc, sigAndData.Signature)
+ if err != nil {
+ return err
+ }
+
+ publicKey, err := cs.ConsensusState.GetPubKey()
+ if err != nil {
+ return err
+ }
+
+ if err := VerifySignature(publicKey, data, sigData); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/modules/light-clients/06-solomachine/types/misbehaviour_test.go b/modules/light-clients/06-solomachine/misbehaviour_test.go
similarity index 63%
rename from modules/light-clients/06-solomachine/types/misbehaviour_test.go
rename to modules/light-clients/06-solomachine/misbehaviour_test.go
index bdcdc664504..2e6044b67d1 100644
--- a/modules/light-clients/06-solomachine/types/misbehaviour_test.go
+++ b/modules/light-clients/06-solomachine/misbehaviour_test.go
@@ -1,8 +1,8 @@
-package types_test
+package solomachine_test
import (
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
+ solomachine "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -10,100 +10,99 @@ func (suite *SoloMachineTestSuite) TestMisbehaviour() {
misbehaviour := suite.solomachine.CreateMisbehaviour()
suite.Require().Equal(exported.Solomachine, misbehaviour.ClientType())
- suite.Require().Equal(suite.solomachine.ClientID, misbehaviour.GetClientID())
}
func (suite *SoloMachineTestSuite) TestMisbehaviourValidateBasic() {
// test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
+ for _, sm := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
testCases := []struct {
name string
- malleateMisbehaviour func(misbehaviour *types.Misbehaviour)
+ malleateMisbehaviour func(misbehaviour *solomachine.Misbehaviour)
expPass bool
}{
{
"valid misbehaviour",
- func(*types.Misbehaviour) {},
+ func(*solomachine.Misbehaviour) {},
true,
},
{
"invalid client ID",
- func(misbehaviour *types.Misbehaviour) {
+ func(misbehaviour *solomachine.Misbehaviour) {
misbehaviour.ClientId = "(badclientid)"
},
false,
},
{
"sequence is zero",
- func(misbehaviour *types.Misbehaviour) {
+ func(misbehaviour *solomachine.Misbehaviour) {
misbehaviour.Sequence = 0
},
false,
},
{
"signature one sig is empty",
- func(misbehaviour *types.Misbehaviour) {
+ func(misbehaviour *solomachine.Misbehaviour) {
misbehaviour.SignatureOne.Signature = []byte{}
},
false,
},
{
"signature two sig is empty",
- func(misbehaviour *types.Misbehaviour) {
+ func(misbehaviour *solomachine.Misbehaviour) {
misbehaviour.SignatureTwo.Signature = []byte{}
},
false,
},
{
"signature one data is empty",
- func(misbehaviour *types.Misbehaviour) {
+ func(misbehaviour *solomachine.Misbehaviour) {
misbehaviour.SignatureOne.Data = nil
},
false,
},
{
"signature two data is empty",
- func(misbehaviour *types.Misbehaviour) {
+ func(misbehaviour *solomachine.Misbehaviour) {
misbehaviour.SignatureTwo.Data = []byte{}
},
false,
},
{
"signatures are identical",
- func(misbehaviour *types.Misbehaviour) {
+ func(misbehaviour *solomachine.Misbehaviour) {
misbehaviour.SignatureTwo.Signature = misbehaviour.SignatureOne.Signature
},
false,
},
{
"data signed is identical",
- func(misbehaviour *types.Misbehaviour) {
+ func(misbehaviour *solomachine.Misbehaviour) {
misbehaviour.SignatureTwo.Data = misbehaviour.SignatureOne.Data
},
false,
},
{
- "data type for SignatureOne is unspecified",
- func(misbehaviour *types.Misbehaviour) {
- misbehaviour.SignatureOne.DataType = types.UNSPECIFIED
+ "data path for SignatureOne is unspecified",
+ func(misbehaviour *solomachine.Misbehaviour) {
+ misbehaviour.SignatureOne.Path = []byte{}
}, false,
},
{
- "data type for SignatureTwo is unspecified",
- func(misbehaviour *types.Misbehaviour) {
- misbehaviour.SignatureTwo.DataType = types.UNSPECIFIED
+ "data path for SignatureTwo is unspecified",
+ func(misbehaviour *solomachine.Misbehaviour) {
+ misbehaviour.SignatureTwo.Path = []byte{}
}, false,
},
{
"timestamp for SignatureOne is zero",
- func(misbehaviour *types.Misbehaviour) {
+ func(misbehaviour *solomachine.Misbehaviour) {
misbehaviour.SignatureOne.Timestamp = 0
}, false,
},
{
"timestamp for SignatureTwo is zero",
- func(misbehaviour *types.Misbehaviour) {
+ func(misbehaviour *solomachine.Misbehaviour) {
misbehaviour.SignatureTwo.Timestamp = 0
}, false,
},
@@ -113,7 +112,8 @@ func (suite *SoloMachineTestSuite) TestMisbehaviourValidateBasic() {
tc := tc
suite.Run(tc.name, func() {
- misbehaviour := solomachine.CreateMisbehaviour()
+
+ misbehaviour := sm.CreateMisbehaviour()
tc.malleateMisbehaviour(misbehaviour)
err := misbehaviour.ValidateBasic()
diff --git a/modules/light-clients/06-solomachine/module.go b/modules/light-clients/06-solomachine/module.go
index 4acbc3d7a25..d66b482541c 100644
--- a/modules/light-clients/06-solomachine/module.go
+++ b/modules/light-clients/06-solomachine/module.go
@@ -1,10 +1,6 @@
package solomachine
-import (
- "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
-)
-
// Name returns the solo machine client name.
func Name() string {
- return types.SubModuleName
+ return SubModuleName
}
diff --git a/modules/light-clients/06-solomachine/proof.go b/modules/light-clients/06-solomachine/proof.go
new file mode 100644
index 00000000000..386830340cf
--- /dev/null
+++ b/modules/light-clients/06-solomachine/proof.go
@@ -0,0 +1,43 @@
+package solomachine
+
+import (
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ "github.com/cosmos/cosmos-sdk/crypto/types/multisig"
+ sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
+ "github.com/cosmos/cosmos-sdk/types/tx/signing"
+)
+
+// VerifySignature verifies if the the provided public key generated the signature
+// over the given data. Single and Multi signature public keys are supported.
+// The signature data type must correspond to the public key type. An error is
+// returned if signature verification fails or an invalid SignatureData type is
+// provided.
+func VerifySignature(pubKey cryptotypes.PubKey, signBytes []byte, sigData signing.SignatureData) error {
+ switch pubKey := pubKey.(type) {
+ case multisig.PubKey:
+ data, ok := sigData.(*signing.MultiSignatureData)
+ if !ok {
+ return sdkerrors.Wrapf(ErrSignatureVerificationFailed, "invalid signature data type, expected %T, got %T", (*signing.MultiSignatureData)(nil), data)
+ }
+
+ // The function supplied fulfills the VerifyMultisignature interface. No special
+ // adjustments need to be made to the sign bytes based on the sign mode.
+ if err := pubKey.VerifyMultisignature(func(signing.SignMode) ([]byte, error) {
+ return signBytes, nil
+ }, data); err != nil {
+ return err
+ }
+
+ default:
+ data, ok := sigData.(*signing.SingleSignatureData)
+ if !ok {
+ return sdkerrors.Wrapf(ErrSignatureVerificationFailed, "invalid signature data type, expected %T, got %T", (*signing.SingleSignatureData)(nil), data)
+ }
+
+ if !pubKey.VerifySignature(signBytes, data.Signature) {
+ return ErrSignatureVerificationFailed
+ }
+ }
+
+ return nil
+}
diff --git a/modules/light-clients/06-solomachine/proof_test.go b/modules/light-clients/06-solomachine/proof_test.go
new file mode 100644
index 00000000000..2fa853d46a5
--- /dev/null
+++ b/modules/light-clients/06-solomachine/proof_test.go
@@ -0,0 +1,67 @@
+package solomachine_test
+
+import (
+ cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+ "github.com/cosmos/cosmos-sdk/types/tx/signing"
+
+ solomachine "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
+)
+
+func (suite *SoloMachineTestSuite) TestVerifySignature() {
+ cdc := suite.chainA.App.AppCodec()
+ signBytes := []byte("sign bytes")
+
+ singleSignature := suite.solomachine.GenerateSignature(signBytes)
+ singleSigData, err := solomachine.UnmarshalSignatureData(cdc, singleSignature)
+ suite.Require().NoError(err)
+
+ multiSignature := suite.solomachineMulti.GenerateSignature(signBytes)
+ multiSigData, err := solomachine.UnmarshalSignatureData(cdc, multiSignature)
+ suite.Require().NoError(err)
+
+ testCases := []struct {
+ name string
+ publicKey cryptotypes.PubKey
+ sigData signing.SignatureData
+ expPass bool
+ }{
+ {
+ "single signature with regular public key",
+ suite.solomachine.PublicKey,
+ singleSigData,
+ true,
+ },
+ {
+ "multi signature with multisig public key",
+ suite.solomachineMulti.PublicKey,
+ multiSigData,
+ true,
+ },
+ {
+ "single signature with multisig public key",
+ suite.solomachineMulti.PublicKey,
+ singleSigData,
+ false,
+ },
+ {
+ "multi signature with regular public key",
+ suite.solomachine.PublicKey,
+ multiSigData,
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+ err := solomachine.VerifySignature(tc.publicKey, signBytes, tc.sigData)
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+}
diff --git a/modules/light-clients/06-solomachine/types/proposal_handle.go b/modules/light-clients/06-solomachine/proposal_handle.go
similarity index 62%
rename from modules/light-clients/06-solomachine/types/proposal_handle.go
rename to modules/light-clients/06-solomachine/proposal_handle.go
index 6cbcb2b3627..bef2db14299 100644
--- a/modules/light-clients/06-solomachine/types/proposal_handle.go
+++ b/modules/light-clients/06-solomachine/proposal_handle.go
@@ -1,4 +1,4 @@
-package types
+package solomachine
import (
"reflect"
@@ -21,43 +21,36 @@ import (
func (cs ClientState) CheckSubstituteAndUpdateState(
ctx sdk.Context, cdc codec.BinaryCodec, subjectClientStore,
_ sdk.KVStore, substituteClient exported.ClientState,
-) (exported.ClientState, error) {
+) error {
if !cs.AllowUpdateAfterProposal {
- return nil, sdkerrors.Wrapf(
- clienttypes.ErrUpdateClientFailed,
- "solo machine client is not allowed to updated with a proposal",
- )
+ return sdkerrors.Wrapf(clienttypes.ErrUpdateClientFailed, "solo machine client is not allowed to updated with a proposal")
}
substituteClientState, ok := substituteClient.(*ClientState)
if !ok {
- return nil, sdkerrors.Wrapf(
- clienttypes.ErrInvalidClientType, "substitute client state type %T, expected %T", substituteClient, &ClientState{},
- )
+ return sdkerrors.Wrapf(clienttypes.ErrInvalidClientType, "substitute client state type %T, expected %T", substituteClient, &ClientState{})
}
subjectPublicKey, err := cs.ConsensusState.GetPubKey()
if err != nil {
- return nil, sdkerrors.Wrap(err, "failed to get consensus public key")
+ return sdkerrors.Wrap(err, "failed to get consensus public key")
}
substitutePublicKey, err := substituteClientState.ConsensusState.GetPubKey()
if err != nil {
- return nil, sdkerrors.Wrap(err, "failed to get substitute client public key")
+ return sdkerrors.Wrap(err, "failed to get substitute client public key")
}
if reflect.DeepEqual(subjectPublicKey, substitutePublicKey) {
- return nil, sdkerrors.Wrapf(
- clienttypes.ErrInvalidHeader, "subject and substitute have the same public key",
- )
+ return sdkerrors.Wrapf(clienttypes.ErrInvalidHeader, "subject and substitute have the same public key")
}
- clientState := &cs
-
// update to substitute parameters
- clientState.Sequence = substituteClientState.Sequence
- clientState.ConsensusState = substituteClientState.ConsensusState
- clientState.IsFrozen = false
+ cs.Sequence = substituteClientState.Sequence
+ cs.ConsensusState = substituteClientState.ConsensusState
+ cs.IsFrozen = false
+
+ setClientState(subjectClientStore, cdc, &cs)
- return clientState, nil
+ return nil
}
diff --git a/modules/light-clients/06-solomachine/types/proposal_handle_test.go b/modules/light-clients/06-solomachine/proposal_handle_test.go
similarity index 51%
rename from modules/light-clients/06-solomachine/types/proposal_handle_test.go
rename to modules/light-clients/06-solomachine/proposal_handle_test.go
index 800f563f0b9..21a28564320 100644
--- a/modules/light-clients/06-solomachine/types/proposal_handle_test.go
+++ b/modules/light-clients/06-solomachine/proposal_handle_test.go
@@ -1,20 +1,22 @@
-package types_test
+package solomachine_test
import (
+ clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
+ host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ solomachine "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
func (suite *SoloMachineTestSuite) TestCheckSubstituteAndUpdateState() {
var (
- subjectClientState *types.ClientState
+ subjectClientState *solomachine.ClientState
substituteClientState exported.ClientState
)
// test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
+ for _, sm := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
testCases := []struct {
name string
@@ -33,7 +35,7 @@ func (suite *SoloMachineTestSuite) TestCheckSubstituteAndUpdateState() {
},
{
"substitute is not the solo machine", func() {
- substituteClientState = &ibctmtypes.ClientState{}
+ substituteClientState = &ibctm.ClientState{}
}, false,
},
{
@@ -44,12 +46,12 @@ func (suite *SoloMachineTestSuite) TestCheckSubstituteAndUpdateState() {
{
"substitute public key is nil", func() {
- substituteClientState.(*types.ClientState).ConsensusState.PublicKey = nil
+ substituteClientState.(*solomachine.ClientState).ConsensusState.PublicKey = nil
}, false,
},
{
"subject and substitute use the same public key", func() {
- substituteClientState.(*types.ClientState).ConsensusState.PublicKey = subjectClientState.ConsensusState.PublicKey
+ substituteClientState.(*solomachine.ClientState).ConsensusState.PublicKey = subjectClientState.ConsensusState.PublicKey
}, false,
},
}
@@ -60,27 +62,31 @@ func (suite *SoloMachineTestSuite) TestCheckSubstituteAndUpdateState() {
suite.Run(tc.name, func() {
suite.SetupTest()
- subjectClientState = solomachine.ClientState()
+ subjectClientState = sm.ClientState()
subjectClientState.AllowUpdateAfterProposal = true
substitute := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "substitute", "testing", 5)
substituteClientState = substitute.ClientState()
tc.malleate()
- subjectClientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), solomachine.ClientID)
+ subjectClientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), sm.ClientID)
substituteClientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), substitute.ClientID)
- updatedClient, err := subjectClientState.CheckSubstituteAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), subjectClientStore, substituteClientStore, substituteClientState)
+ err := subjectClientState.CheckSubstituteAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), subjectClientStore, substituteClientStore, substituteClientState)
if tc.expPass {
suite.Require().NoError(err)
- suite.Require().Equal(substituteClientState.(*types.ClientState).ConsensusState, updatedClient.(*types.ClientState).ConsensusState)
- suite.Require().Equal(substituteClientState.(*types.ClientState).Sequence, updatedClient.(*types.ClientState).Sequence)
- suite.Require().Equal(false, updatedClient.(*types.ClientState).IsFrozen)
+ // ensure updated client state is set in store
+ bz := subjectClientStore.Get(host.ClientStateKey())
+ updatedClient := clienttypes.MustUnmarshalClientState(suite.chainA.App.AppCodec(), bz).(*solomachine.ClientState)
+
+ suite.Require().Equal(substituteClientState.(*solomachine.ClientState).ConsensusState, updatedClient.ConsensusState)
+ suite.Require().Equal(substituteClientState.(*solomachine.ClientState).Sequence, updatedClient.Sequence)
+ suite.Require().Equal(false, updatedClient.IsFrozen)
+
} else {
suite.Require().Error(err)
- suite.Require().Nil(updatedClient)
}
})
}
diff --git a/modules/light-clients/06-solomachine/types/solomachine.go b/modules/light-clients/06-solomachine/solomachine.go
similarity index 69%
rename from modules/light-clients/06-solomachine/types/solomachine.go
rename to modules/light-clients/06-solomachine/solomachine.go
index 2e7fc46307e..41511910bf4 100644
--- a/modules/light-clients/06-solomachine/types/solomachine.go
+++ b/modules/light-clients/06-solomachine/solomachine.go
@@ -1,10 +1,8 @@
-package types
+package solomachine
import (
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
-
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
)
// Interface implementation checks.
@@ -32,13 +30,3 @@ func (h Header) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
func (hd HeaderData) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
return unpacker.UnpackAny(hd.NewPubKey, new(cryptotypes.PubKey))
}
-
-// UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method
-func (csd ClientStateData) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
- return unpacker.UnpackAny(csd.ClientState, new(exported.ClientState))
-}
-
-// UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method
-func (csd ConsensusStateData) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
- return unpacker.UnpackAny(csd.ConsensusState, new(exported.ConsensusState))
-}
diff --git a/modules/light-clients/06-solomachine/solomachine.pb.go b/modules/light-clients/06-solomachine/solomachine.pb.go
new file mode 100644
index 00000000000..4714f24f568
--- /dev/null
+++ b/modules/light-clients/06-solomachine/solomachine.pb.go
@@ -0,0 +1,2350 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: ibc/lightclients/solomachine/v3/solomachine.proto
+
+package solomachine
+
+import (
+ fmt "fmt"
+ types "github.com/cosmos/cosmos-sdk/codec/types"
+ _ "github.com/gogo/protobuf/gogoproto"
+ proto "github.com/gogo/protobuf/proto"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// ClientState defines a solo machine client that tracks the current consensus
+// state and if the client is frozen.
+type ClientState struct {
+ // latest sequence of the client state
+ Sequence uint64 `protobuf:"varint,1,opt,name=sequence,proto3" json:"sequence,omitempty"`
+ // frozen sequence of the solo machine
+ IsFrozen bool `protobuf:"varint,2,opt,name=is_frozen,json=isFrozen,proto3" json:"is_frozen,omitempty" yaml:"is_frozen"`
+ ConsensusState *ConsensusState `protobuf:"bytes,3,opt,name=consensus_state,json=consensusState,proto3" json:"consensus_state,omitempty" 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.
+ AllowUpdateAfterProposal bool `protobuf:"varint,4,opt,name=allow_update_after_proposal,json=allowUpdateAfterProposal,proto3" json:"allow_update_after_proposal,omitempty" yaml:"allow_update_after_proposal"`
+}
+
+func (m *ClientState) Reset() { *m = ClientState{} }
+func (m *ClientState) String() string { return proto.CompactTextString(m) }
+func (*ClientState) ProtoMessage() {}
+func (*ClientState) Descriptor() ([]byte, []int) {
+ return fileDescriptor_264187157b9220a4, []int{0}
+}
+func (m *ClientState) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *ClientState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_ClientState.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 *ClientState) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ClientState.Merge(m, src)
+}
+func (m *ClientState) XXX_Size() int {
+ return m.Size()
+}
+func (m *ClientState) XXX_DiscardUnknown() {
+ xxx_messageInfo_ClientState.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ClientState proto.InternalMessageInfo
+
+// ConsensusState defines a solo machine consensus state. The sequence of a
+// consensus state is contained in the "height" key used in storing the
+// consensus state.
+type ConsensusState struct {
+ // public key of the solo machine
+ PublicKey *types.Any `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty" 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.
+ Diversifier string `protobuf:"bytes,2,opt,name=diversifier,proto3" json:"diversifier,omitempty"`
+ Timestamp uint64 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+}
+
+func (m *ConsensusState) Reset() { *m = ConsensusState{} }
+func (m *ConsensusState) String() string { return proto.CompactTextString(m) }
+func (*ConsensusState) ProtoMessage() {}
+func (*ConsensusState) Descriptor() ([]byte, []int) {
+ return fileDescriptor_264187157b9220a4, []int{1}
+}
+func (m *ConsensusState) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *ConsensusState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_ConsensusState.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 *ConsensusState) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ConsensusState.Merge(m, src)
+}
+func (m *ConsensusState) XXX_Size() int {
+ return m.Size()
+}
+func (m *ConsensusState) XXX_DiscardUnknown() {
+ xxx_messageInfo_ConsensusState.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ConsensusState proto.InternalMessageInfo
+
+// Header defines a solo machine consensus header
+type Header struct {
+ // sequence to update solo machine public key at
+ Sequence uint64 `protobuf:"varint,1,opt,name=sequence,proto3" json:"sequence,omitempty"`
+ Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+ Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"`
+ NewPublicKey *types.Any `protobuf:"bytes,4,opt,name=new_public_key,json=newPublicKey,proto3" json:"new_public_key,omitempty" yaml:"new_public_key"`
+ NewDiversifier string `protobuf:"bytes,5,opt,name=new_diversifier,json=newDiversifier,proto3" json:"new_diversifier,omitempty" yaml:"new_diversifier"`
+}
+
+func (m *Header) Reset() { *m = Header{} }
+func (m *Header) String() string { return proto.CompactTextString(m) }
+func (*Header) ProtoMessage() {}
+func (*Header) Descriptor() ([]byte, []int) {
+ return fileDescriptor_264187157b9220a4, []int{2}
+}
+func (m *Header) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_Header.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 *Header) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Header.Merge(m, src)
+}
+func (m *Header) XXX_Size() int {
+ return m.Size()
+}
+func (m *Header) XXX_DiscardUnknown() {
+ xxx_messageInfo_Header.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Header proto.InternalMessageInfo
+
+// Misbehaviour defines misbehaviour for a solo machine which consists
+// of a sequence and two signatures over different messages at that sequence.
+type Misbehaviour struct {
+ // ClientID is deprecated
+ ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` // Deprecated: Do not use.
+ Sequence uint64 `protobuf:"varint,2,opt,name=sequence,proto3" json:"sequence,omitempty"`
+ SignatureOne *SignatureAndData `protobuf:"bytes,3,opt,name=signature_one,json=signatureOne,proto3" json:"signature_one,omitempty" yaml:"signature_one"`
+ SignatureTwo *SignatureAndData `protobuf:"bytes,4,opt,name=signature_two,json=signatureTwo,proto3" json:"signature_two,omitempty" yaml:"signature_two"`
+}
+
+func (m *Misbehaviour) Reset() { *m = Misbehaviour{} }
+func (m *Misbehaviour) String() string { return proto.CompactTextString(m) }
+func (*Misbehaviour) ProtoMessage() {}
+func (*Misbehaviour) Descriptor() ([]byte, []int) {
+ return fileDescriptor_264187157b9220a4, []int{3}
+}
+func (m *Misbehaviour) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *Misbehaviour) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_Misbehaviour.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 *Misbehaviour) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Misbehaviour.Merge(m, src)
+}
+func (m *Misbehaviour) XXX_Size() int {
+ return m.Size()
+}
+func (m *Misbehaviour) XXX_DiscardUnknown() {
+ xxx_messageInfo_Misbehaviour.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Misbehaviour proto.InternalMessageInfo
+
+// SignatureAndData contains a signature and the data signed over to create that
+// signature.
+type SignatureAndData struct {
+ Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"`
+ Path []byte `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
+ Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
+ Timestamp uint64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+}
+
+func (m *SignatureAndData) Reset() { *m = SignatureAndData{} }
+func (m *SignatureAndData) String() string { return proto.CompactTextString(m) }
+func (*SignatureAndData) ProtoMessage() {}
+func (*SignatureAndData) Descriptor() ([]byte, []int) {
+ return fileDescriptor_264187157b9220a4, []int{4}
+}
+func (m *SignatureAndData) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *SignatureAndData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_SignatureAndData.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 *SignatureAndData) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SignatureAndData.Merge(m, src)
+}
+func (m *SignatureAndData) XXX_Size() int {
+ return m.Size()
+}
+func (m *SignatureAndData) XXX_DiscardUnknown() {
+ xxx_messageInfo_SignatureAndData.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SignatureAndData proto.InternalMessageInfo
+
+// TimestampedSignatureData contains the signature data and the timestamp of the
+// signature.
+type TimestampedSignatureData struct {
+ SignatureData []byte `protobuf:"bytes,1,opt,name=signature_data,json=signatureData,proto3" json:"signature_data,omitempty" yaml:"signature_data"`
+ Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+}
+
+func (m *TimestampedSignatureData) Reset() { *m = TimestampedSignatureData{} }
+func (m *TimestampedSignatureData) String() string { return proto.CompactTextString(m) }
+func (*TimestampedSignatureData) ProtoMessage() {}
+func (*TimestampedSignatureData) Descriptor() ([]byte, []int) {
+ return fileDescriptor_264187157b9220a4, []int{5}
+}
+func (m *TimestampedSignatureData) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *TimestampedSignatureData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_TimestampedSignatureData.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 *TimestampedSignatureData) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_TimestampedSignatureData.Merge(m, src)
+}
+func (m *TimestampedSignatureData) XXX_Size() int {
+ return m.Size()
+}
+func (m *TimestampedSignatureData) XXX_DiscardUnknown() {
+ xxx_messageInfo_TimestampedSignatureData.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TimestampedSignatureData proto.InternalMessageInfo
+
+// SignBytes defines the signed bytes used for signature verification.
+type SignBytes struct {
+ // the sequence number
+ Sequence uint64 `protobuf:"varint,1,opt,name=sequence,proto3" json:"sequence,omitempty"`
+ // the proof timestamp
+ Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+ // the public key diversifier
+ Diversifier string `protobuf:"bytes,3,opt,name=diversifier,proto3" json:"diversifier,omitempty"`
+ // the standardised path bytes
+ Path []byte `protobuf:"bytes,4,opt,name=path,proto3" json:"path,omitempty"`
+ // the marshaled data bytes
+ Data []byte `protobuf:"bytes,5,opt,name=data,proto3" json:"data,omitempty"`
+}
+
+func (m *SignBytes) Reset() { *m = SignBytes{} }
+func (m *SignBytes) String() string { return proto.CompactTextString(m) }
+func (*SignBytes) ProtoMessage() {}
+func (*SignBytes) Descriptor() ([]byte, []int) {
+ return fileDescriptor_264187157b9220a4, []int{6}
+}
+func (m *SignBytes) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *SignBytes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_SignBytes.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 *SignBytes) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SignBytes.Merge(m, src)
+}
+func (m *SignBytes) XXX_Size() int {
+ return m.Size()
+}
+func (m *SignBytes) XXX_DiscardUnknown() {
+ xxx_messageInfo_SignBytes.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SignBytes proto.InternalMessageInfo
+
+// HeaderData returns the SignBytes data for update verification.
+type HeaderData struct {
+ // header public key
+ NewPubKey *types.Any `protobuf:"bytes,1,opt,name=new_pub_key,json=newPubKey,proto3" json:"new_pub_key,omitempty" yaml:"new_pub_key"`
+ // header diversifier
+ NewDiversifier string `protobuf:"bytes,2,opt,name=new_diversifier,json=newDiversifier,proto3" json:"new_diversifier,omitempty" yaml:"new_diversifier"`
+}
+
+func (m *HeaderData) Reset() { *m = HeaderData{} }
+func (m *HeaderData) String() string { return proto.CompactTextString(m) }
+func (*HeaderData) ProtoMessage() {}
+func (*HeaderData) Descriptor() ([]byte, []int) {
+ return fileDescriptor_264187157b9220a4, []int{7}
+}
+func (m *HeaderData) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *HeaderData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_HeaderData.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 *HeaderData) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_HeaderData.Merge(m, src)
+}
+func (m *HeaderData) XXX_Size() int {
+ return m.Size()
+}
+func (m *HeaderData) XXX_DiscardUnknown() {
+ xxx_messageInfo_HeaderData.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_HeaderData proto.InternalMessageInfo
+
+func init() {
+ proto.RegisterType((*ClientState)(nil), "ibc.lightclients.solomachine.v3.ClientState")
+ proto.RegisterType((*ConsensusState)(nil), "ibc.lightclients.solomachine.v3.ConsensusState")
+ proto.RegisterType((*Header)(nil), "ibc.lightclients.solomachine.v3.Header")
+ proto.RegisterType((*Misbehaviour)(nil), "ibc.lightclients.solomachine.v3.Misbehaviour")
+ proto.RegisterType((*SignatureAndData)(nil), "ibc.lightclients.solomachine.v3.SignatureAndData")
+ proto.RegisterType((*TimestampedSignatureData)(nil), "ibc.lightclients.solomachine.v3.TimestampedSignatureData")
+ proto.RegisterType((*SignBytes)(nil), "ibc.lightclients.solomachine.v3.SignBytes")
+ proto.RegisterType((*HeaderData)(nil), "ibc.lightclients.solomachine.v3.HeaderData")
+}
+
+func init() {
+ proto.RegisterFile("ibc/lightclients/solomachine/v3/solomachine.proto", fileDescriptor_264187157b9220a4)
+}
+
+var fileDescriptor_264187157b9220a4 = []byte{
+ // 784 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0x4d, 0x6f, 0xe3, 0x44,
+ 0x18, 0x8e, 0x5d, 0xb7, 0x4a, 0x26, 0x21, 0x2d, 0x56, 0x5a, 0xb9, 0x01, 0xc5, 0x91, 0x0f, 0xa8,
+ 0x97, 0xda, 0xb4, 0x11, 0x1c, 0xca, 0x85, 0xa6, 0x15, 0xe2, 0xa3, 0x88, 0xca, 0x6d, 0x2f, 0x5c,
+ 0xac, 0xb1, 0x3d, 0x71, 0x46, 0x38, 0x1e, 0xe3, 0x19, 0x27, 0x0a, 0xe2, 0x80, 0x38, 0x71, 0xe4,
+ 0xc2, 0x1d, 0x21, 0xf1, 0x3b, 0xb8, 0xb2, 0xb7, 0x1e, 0xf7, 0x14, 0xad, 0xda, 0x7f, 0x90, 0x5f,
+ 0xb0, 0xf2, 0xd8, 0x89, 0x3f, 0xda, 0x6d, 0xa5, 0xdd, 0xbd, 0xcd, 0xbc, 0x9f, 0xcf, 0xfb, 0xcc,
+ 0xf3, 0xda, 0xe0, 0x08, 0xdb, 0x8e, 0xe1, 0x63, 0x6f, 0xcc, 0x1c, 0x1f, 0xa3, 0x80, 0x51, 0x83,
+ 0x12, 0x9f, 0x4c, 0xa0, 0x33, 0xc6, 0x01, 0x32, 0xa6, 0x83, 0xe2, 0x55, 0x0f, 0x23, 0xc2, 0x88,
+ 0xac, 0x62, 0xdb, 0xd1, 0x8b, 0x29, 0x7a, 0x31, 0x66, 0x3a, 0xe8, 0x76, 0x3c, 0xe2, 0x11, 0x1e,
+ 0x6b, 0x24, 0xa7, 0x34, 0xad, 0xbb, 0xef, 0x11, 0xe2, 0xf9, 0xc8, 0xe0, 0x37, 0x3b, 0x1e, 0x19,
+ 0x30, 0x98, 0xa7, 0x2e, 0xed, 0x3f, 0x11, 0x34, 0xcf, 0x78, 0xad, 0x2b, 0x06, 0x19, 0x92, 0xbb,
+ 0xa0, 0x4e, 0xd1, 0xcf, 0x31, 0x0a, 0x1c, 0xa4, 0x08, 0x7d, 0xe1, 0x40, 0x32, 0xd7, 0x77, 0xf9,
+ 0x08, 0x34, 0x30, 0xb5, 0x46, 0x11, 0xf9, 0x05, 0x05, 0x8a, 0xd8, 0x17, 0x0e, 0xea, 0xc3, 0xce,
+ 0x72, 0xa1, 0xee, 0xcc, 0xe1, 0xc4, 0x3f, 0xd1, 0xd6, 0x2e, 0xcd, 0xac, 0x63, 0xfa, 0x15, 0x3f,
+ 0xca, 0x0c, 0x6c, 0x3b, 0x24, 0xa0, 0x28, 0xa0, 0x31, 0xb5, 0x68, 0xd2, 0x41, 0xd9, 0xe8, 0x0b,
+ 0x07, 0xcd, 0x63, 0x43, 0x7f, 0x66, 0x14, 0xfd, 0x6c, 0x95, 0xc7, 0x81, 0x0d, 0xbb, 0xcb, 0x85,
+ 0xba, 0x97, 0x76, 0xaa, 0x54, 0xd4, 0xcc, 0xb6, 0x53, 0x8a, 0x95, 0x11, 0xf8, 0x08, 0xfa, 0x3e,
+ 0x99, 0x59, 0x71, 0xe8, 0x42, 0x86, 0x2c, 0x38, 0x62, 0x28, 0xb2, 0xc2, 0x88, 0x84, 0x84, 0x42,
+ 0x5f, 0x91, 0x38, 0xf4, 0x4f, 0x96, 0x0b, 0x55, 0x4b, 0x0b, 0x3e, 0x11, 0xac, 0x99, 0x0a, 0xf7,
+ 0xde, 0x70, 0xe7, 0x69, 0xe2, 0xbb, 0xcc, 0x5c, 0x27, 0xd2, 0x1f, 0x7f, 0xab, 0x35, 0xed, 0x1f,
+ 0x01, 0xb4, 0xcb, 0x58, 0xe5, 0x6f, 0x01, 0x08, 0x63, 0xdb, 0xc7, 0x8e, 0xf5, 0x13, 0x9a, 0x73,
+ 0x1a, 0x9b, 0xc7, 0x1d, 0x3d, 0x7d, 0x04, 0x7d, 0xf5, 0x08, 0xfa, 0x69, 0x30, 0x1f, 0xee, 0x2e,
+ 0x17, 0xea, 0x87, 0x29, 0x88, 0x3c, 0x43, 0x33, 0x1b, 0xe9, 0xe5, 0x3b, 0x34, 0x97, 0xfb, 0xa0,
+ 0xe9, 0xe2, 0x29, 0x8a, 0x28, 0x1e, 0x61, 0x14, 0x71, 0xda, 0x1b, 0x66, 0xd1, 0x24, 0x7f, 0x0c,
+ 0x1a, 0x0c, 0x4f, 0x10, 0x65, 0x70, 0x12, 0x72, 0x76, 0x25, 0x33, 0x37, 0x64, 0x20, 0x7f, 0x17,
+ 0xc1, 0xd6, 0xd7, 0x08, 0xba, 0x28, 0x7a, 0xf2, 0x85, 0x4b, 0xa5, 0xc4, 0x4a, 0xa9, 0xc4, 0x4b,
+ 0xb1, 0x17, 0x40, 0x16, 0x47, 0xe9, 0x33, 0xb6, 0xcc, 0xdc, 0x20, 0xdf, 0x80, 0x76, 0x80, 0x66,
+ 0x56, 0x61, 0x70, 0xe9, 0x89, 0xc1, 0xf7, 0x97, 0x0b, 0x75, 0x37, 0x1d, 0xbc, 0x9c, 0xa5, 0x99,
+ 0xad, 0x00, 0xcd, 0x2e, 0xd7, 0xf3, 0x9f, 0x81, 0xed, 0x24, 0xa0, 0xc8, 0xc1, 0x66, 0xc2, 0x41,
+ 0x51, 0x10, 0x95, 0x00, 0xcd, 0x4c, 0x90, 0x9c, 0xe7, 0x86, 0x8c, 0x84, 0x17, 0x22, 0x68, 0x7d,
+ 0x8f, 0xa9, 0x8d, 0xc6, 0x70, 0x8a, 0x49, 0x1c, 0xc9, 0x03, 0xd0, 0x48, 0xc5, 0x67, 0x61, 0x97,
+ 0x73, 0xd1, 0x18, 0xee, 0xe5, 0x82, 0x5e, 0xbb, 0x34, 0x45, 0x30, 0xeb, 0xe9, 0xed, 0x1b, 0xb7,
+ 0xc4, 0x9f, 0x58, 0xe1, 0x2f, 0x04, 0x1f, 0xac, 0x09, 0xb1, 0x48, 0xb0, 0x12, 0xfb, 0xd1, 0xb3,
+ 0x62, 0xbf, 0x5a, 0x65, 0x9d, 0x06, 0xee, 0x39, 0x64, 0x70, 0xa8, 0x2c, 0x17, 0x6a, 0x27, 0xc5,
+ 0x51, 0xaa, 0xa8, 0x99, 0xad, 0xf5, 0xfd, 0x87, 0xa0, 0xd2, 0x91, 0xcd, 0x48, 0x46, 0xfa, 0xfb,
+ 0xea, 0xc8, 0x66, 0xa4, 0xd8, 0xf1, 0x7a, 0x46, 0x32, 0x2e, 0x7f, 0x05, 0x3b, 0xd5, 0x0a, 0x65,
+ 0x7d, 0x08, 0x55, 0x7d, 0xc8, 0x40, 0x0a, 0x21, 0x1b, 0x73, 0xce, 0x5a, 0x26, 0x3f, 0x27, 0x36,
+ 0x17, 0x32, 0x98, 0x89, 0x89, 0x9f, 0xcb, 0x1a, 0x94, 0x1e, 0x97, 0xf3, 0x6f, 0x02, 0x50, 0xae,
+ 0x57, 0x36, 0xe4, 0xae, 0x91, 0x70, 0x18, 0x5f, 0x82, 0x76, 0x3e, 0x00, 0x2f, 0xcf, 0xb1, 0x14,
+ 0x25, 0x57, 0xf6, 0x6b, 0x66, 0xce, 0xe1, 0xf9, 0x03, 0x08, 0xe2, 0xe3, 0x10, 0xfe, 0x12, 0x40,
+ 0x23, 0xe9, 0x3b, 0x9c, 0x33, 0x44, 0xdf, 0x61, 0xa9, 0x2a, 0xfb, 0xbd, 0xf1, 0x70, 0xbf, 0x57,
+ 0xc4, 0x49, 0x8f, 0x10, 0xb7, 0x99, 0x13, 0x97, 0xe1, 0xfa, 0x57, 0x00, 0x20, 0xdd, 0x74, 0x3e,
+ 0xca, 0x05, 0x68, 0x66, 0xfb, 0xf5, 0xec, 0xb7, 0x28, 0x91, 0xbe, 0x5c, 0x5a, 0xc9, 0xec, 0x63,
+ 0x94, 0xee, 0xe3, 0x1b, 0x96, 0x51, 0x7c, 0xbb, 0x65, 0x1c, 0x8e, 0xfe, 0xbf, 0xeb, 0x09, 0xb7,
+ 0x77, 0x3d, 0xe1, 0xd5, 0x5d, 0x4f, 0xf8, 0xf3, 0xbe, 0x57, 0xbb, 0xbd, 0xef, 0xd5, 0x5e, 0xde,
+ 0xf7, 0x6a, 0x3f, 0x5e, 0x78, 0x98, 0x8d, 0x63, 0x5b, 0x77, 0xc8, 0xc4, 0x70, 0x08, 0x9d, 0x10,
+ 0x6a, 0x60, 0xdb, 0x39, 0xf4, 0x88, 0x31, 0xfd, 0xcc, 0x98, 0x10, 0x37, 0xf6, 0x11, 0x4d, 0xff,
+ 0x9b, 0x87, 0xab, 0x1f, 0xe7, 0xa7, 0x9f, 0x1f, 0x16, 0xe4, 0xfd, 0x45, 0xe1, 0x6c, 0x6f, 0xf1,
+ 0x19, 0x07, 0xaf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x62, 0x3e, 0x62, 0x81, 0x6e, 0x07, 0x00, 0x00,
+}
+
+func (m *ClientState) 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 *ClientState) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ClientState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.AllowUpdateAfterProposal {
+ i--
+ if m.AllowUpdateAfterProposal {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x20
+ }
+ if m.ConsensusState != nil {
+ {
+ size, err := m.ConsensusState.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintSolomachine(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1a
+ }
+ if m.IsFrozen {
+ i--
+ if m.IsFrozen {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x10
+ }
+ if m.Sequence != 0 {
+ i = encodeVarintSolomachine(dAtA, i, uint64(m.Sequence))
+ i--
+ dAtA[i] = 0x8
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *ConsensusState) 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 *ConsensusState) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ConsensusState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.Timestamp != 0 {
+ i = encodeVarintSolomachine(dAtA, i, uint64(m.Timestamp))
+ i--
+ dAtA[i] = 0x18
+ }
+ if len(m.Diversifier) > 0 {
+ i -= len(m.Diversifier)
+ copy(dAtA[i:], m.Diversifier)
+ i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Diversifier)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if m.PublicKey != nil {
+ {
+ size, err := m.PublicKey.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintSolomachine(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *Header) 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 *Header) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Header) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.NewDiversifier) > 0 {
+ i -= len(m.NewDiversifier)
+ copy(dAtA[i:], m.NewDiversifier)
+ i = encodeVarintSolomachine(dAtA, i, uint64(len(m.NewDiversifier)))
+ i--
+ dAtA[i] = 0x2a
+ }
+ if m.NewPublicKey != nil {
+ {
+ size, err := m.NewPublicKey.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintSolomachine(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x22
+ }
+ if len(m.Signature) > 0 {
+ i -= len(m.Signature)
+ copy(dAtA[i:], m.Signature)
+ i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Signature)))
+ i--
+ dAtA[i] = 0x1a
+ }
+ if m.Timestamp != 0 {
+ i = encodeVarintSolomachine(dAtA, i, uint64(m.Timestamp))
+ i--
+ dAtA[i] = 0x10
+ }
+ if m.Sequence != 0 {
+ i = encodeVarintSolomachine(dAtA, i, uint64(m.Sequence))
+ i--
+ dAtA[i] = 0x8
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *Misbehaviour) 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 *Misbehaviour) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Misbehaviour) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.SignatureTwo != nil {
+ {
+ size, err := m.SignatureTwo.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintSolomachine(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x22
+ }
+ if m.SignatureOne != nil {
+ {
+ size, err := m.SignatureOne.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintSolomachine(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1a
+ }
+ if m.Sequence != 0 {
+ i = encodeVarintSolomachine(dAtA, i, uint64(m.Sequence))
+ i--
+ dAtA[i] = 0x10
+ }
+ if len(m.ClientId) > 0 {
+ i -= len(m.ClientId)
+ copy(dAtA[i:], m.ClientId)
+ i = encodeVarintSolomachine(dAtA, i, uint64(len(m.ClientId)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *SignatureAndData) 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 *SignatureAndData) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *SignatureAndData) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.Timestamp != 0 {
+ i = encodeVarintSolomachine(dAtA, i, uint64(m.Timestamp))
+ i--
+ dAtA[i] = 0x20
+ }
+ if len(m.Data) > 0 {
+ i -= len(m.Data)
+ copy(dAtA[i:], m.Data)
+ i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Data)))
+ i--
+ dAtA[i] = 0x1a
+ }
+ if len(m.Path) > 0 {
+ i -= len(m.Path)
+ copy(dAtA[i:], m.Path)
+ i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Path)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Signature) > 0 {
+ i -= len(m.Signature)
+ copy(dAtA[i:], m.Signature)
+ i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Signature)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *TimestampedSignatureData) 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 *TimestampedSignatureData) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *TimestampedSignatureData) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.Timestamp != 0 {
+ i = encodeVarintSolomachine(dAtA, i, uint64(m.Timestamp))
+ i--
+ dAtA[i] = 0x10
+ }
+ if len(m.SignatureData) > 0 {
+ i -= len(m.SignatureData)
+ copy(dAtA[i:], m.SignatureData)
+ i = encodeVarintSolomachine(dAtA, i, uint64(len(m.SignatureData)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *SignBytes) 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 *SignBytes) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *SignBytes) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.Data) > 0 {
+ i -= len(m.Data)
+ copy(dAtA[i:], m.Data)
+ i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Data)))
+ i--
+ dAtA[i] = 0x2a
+ }
+ if len(m.Path) > 0 {
+ i -= len(m.Path)
+ copy(dAtA[i:], m.Path)
+ i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Path)))
+ i--
+ dAtA[i] = 0x22
+ }
+ if len(m.Diversifier) > 0 {
+ i -= len(m.Diversifier)
+ copy(dAtA[i:], m.Diversifier)
+ i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Diversifier)))
+ i--
+ dAtA[i] = 0x1a
+ }
+ if m.Timestamp != 0 {
+ i = encodeVarintSolomachine(dAtA, i, uint64(m.Timestamp))
+ i--
+ dAtA[i] = 0x10
+ }
+ if m.Sequence != 0 {
+ i = encodeVarintSolomachine(dAtA, i, uint64(m.Sequence))
+ i--
+ dAtA[i] = 0x8
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *HeaderData) 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 *HeaderData) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *HeaderData) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.NewDiversifier) > 0 {
+ i -= len(m.NewDiversifier)
+ copy(dAtA[i:], m.NewDiversifier)
+ i = encodeVarintSolomachine(dAtA, i, uint64(len(m.NewDiversifier)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if m.NewPubKey != nil {
+ {
+ size, err := m.NewPubKey.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintSolomachine(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintSolomachine(dAtA []byte, offset int, v uint64) int {
+ offset -= sovSolomachine(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *ClientState) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Sequence != 0 {
+ n += 1 + sovSolomachine(uint64(m.Sequence))
+ }
+ if m.IsFrozen {
+ n += 2
+ }
+ if m.ConsensusState != nil {
+ l = m.ConsensusState.Size()
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ if m.AllowUpdateAfterProposal {
+ n += 2
+ }
+ return n
+}
+
+func (m *ConsensusState) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.PublicKey != nil {
+ l = m.PublicKey.Size()
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ l = len(m.Diversifier)
+ if l > 0 {
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ if m.Timestamp != 0 {
+ n += 1 + sovSolomachine(uint64(m.Timestamp))
+ }
+ return n
+}
+
+func (m *Header) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Sequence != 0 {
+ n += 1 + sovSolomachine(uint64(m.Sequence))
+ }
+ if m.Timestamp != 0 {
+ n += 1 + sovSolomachine(uint64(m.Timestamp))
+ }
+ l = len(m.Signature)
+ if l > 0 {
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ if m.NewPublicKey != nil {
+ l = m.NewPublicKey.Size()
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ l = len(m.NewDiversifier)
+ if l > 0 {
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ return n
+}
+
+func (m *Misbehaviour) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.ClientId)
+ if l > 0 {
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ if m.Sequence != 0 {
+ n += 1 + sovSolomachine(uint64(m.Sequence))
+ }
+ if m.SignatureOne != nil {
+ l = m.SignatureOne.Size()
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ if m.SignatureTwo != nil {
+ l = m.SignatureTwo.Size()
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ return n
+}
+
+func (m *SignatureAndData) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Signature)
+ if l > 0 {
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ l = len(m.Path)
+ if l > 0 {
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ l = len(m.Data)
+ if l > 0 {
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ if m.Timestamp != 0 {
+ n += 1 + sovSolomachine(uint64(m.Timestamp))
+ }
+ return n
+}
+
+func (m *TimestampedSignatureData) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.SignatureData)
+ if l > 0 {
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ if m.Timestamp != 0 {
+ n += 1 + sovSolomachine(uint64(m.Timestamp))
+ }
+ return n
+}
+
+func (m *SignBytes) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Sequence != 0 {
+ n += 1 + sovSolomachine(uint64(m.Sequence))
+ }
+ if m.Timestamp != 0 {
+ n += 1 + sovSolomachine(uint64(m.Timestamp))
+ }
+ l = len(m.Diversifier)
+ if l > 0 {
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ l = len(m.Path)
+ if l > 0 {
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ l = len(m.Data)
+ if l > 0 {
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ return n
+}
+
+func (m *HeaderData) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.NewPubKey != nil {
+ l = m.NewPubKey.Size()
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ l = len(m.NewDiversifier)
+ if l > 0 {
+ n += 1 + l + sovSolomachine(uint64(l))
+ }
+ return n
+}
+
+func sovSolomachine(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozSolomachine(x uint64) (n int) {
+ return sovSolomachine(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *ClientState) 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 ErrIntOverflowSolomachine
+ }
+ 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: ClientState: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ClientState: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType)
+ }
+ m.Sequence = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Sequence |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field IsFrozen", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.IsFrozen = bool(v != 0)
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ConsensusState", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.ConsensusState == nil {
+ m.ConsensusState = &ConsensusState{}
+ }
+ if err := m.ConsensusState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AllowUpdateAfterProposal", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.AllowUpdateAfterProposal = bool(v != 0)
+ default:
+ iNdEx = preIndex
+ skippy, err := skipSolomachine(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *ConsensusState) 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 ErrIntOverflowSolomachine
+ }
+ 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: ConsensusState: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ConsensusState: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PublicKey", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.PublicKey == nil {
+ m.PublicKey = &types.Any{}
+ }
+ if err := m.PublicKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Diversifier", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ 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 ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Diversifier = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType)
+ }
+ m.Timestamp = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Timestamp |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipSolomachine(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Header) 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 ErrIntOverflowSolomachine
+ }
+ 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: Header: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Header: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType)
+ }
+ m.Sequence = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Sequence |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType)
+ }
+ m.Timestamp = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Timestamp |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...)
+ if m.Signature == nil {
+ m.Signature = []byte{}
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field NewPublicKey", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.NewPublicKey == nil {
+ m.NewPublicKey = &types.Any{}
+ }
+ if err := m.NewPublicKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field NewDiversifier", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ 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 ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.NewDiversifier = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipSolomachine(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Misbehaviour) 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 ErrIntOverflowSolomachine
+ }
+ 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: Misbehaviour: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Misbehaviour: 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 ErrIntOverflowSolomachine
+ }
+ 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 ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ClientId = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType)
+ }
+ m.Sequence = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Sequence |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field SignatureOne", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.SignatureOne == nil {
+ m.SignatureOne = &SignatureAndData{}
+ }
+ if err := m.SignatureOne.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field SignatureTwo", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.SignatureTwo == nil {
+ m.SignatureTwo = &SignatureAndData{}
+ }
+ if err := m.SignatureTwo.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipSolomachine(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *SignatureAndData) 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 ErrIntOverflowSolomachine
+ }
+ 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: SignatureAndData: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: SignatureAndData: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...)
+ if m.Signature == nil {
+ m.Signature = []byte{}
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Path = append(m.Path[:0], dAtA[iNdEx:postIndex]...)
+ if m.Path == nil {
+ m.Path = []byte{}
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
+ if m.Data == nil {
+ m.Data = []byte{}
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType)
+ }
+ m.Timestamp = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Timestamp |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipSolomachine(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *TimestampedSignatureData) 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 ErrIntOverflowSolomachine
+ }
+ 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: TimestampedSignatureData: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: TimestampedSignatureData: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field SignatureData", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.SignatureData = append(m.SignatureData[:0], dAtA[iNdEx:postIndex]...)
+ if m.SignatureData == nil {
+ m.SignatureData = []byte{}
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType)
+ }
+ m.Timestamp = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Timestamp |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipSolomachine(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *SignBytes) 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 ErrIntOverflowSolomachine
+ }
+ 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: SignBytes: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: SignBytes: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType)
+ }
+ m.Sequence = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Sequence |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType)
+ }
+ m.Timestamp = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Timestamp |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Diversifier", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ 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 ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Diversifier = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Path = append(m.Path[:0], dAtA[iNdEx:postIndex]...)
+ if m.Path == nil {
+ m.Path = []byte{}
+ }
+ iNdEx = postIndex
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
+ if m.Data == nil {
+ m.Data = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipSolomachine(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *HeaderData) 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 ErrIntOverflowSolomachine
+ }
+ 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: HeaderData: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: HeaderData: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field NewPubKey", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.NewPubKey == nil {
+ m.NewPubKey = &types.Any{}
+ }
+ if err := m.NewPubKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field NewDiversifier", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSolomachine
+ }
+ 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 ErrInvalidLengthSolomachine
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.NewDiversifier = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipSolomachine(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthSolomachine
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipSolomachine(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowSolomachine
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthSolomachine
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupSolomachine
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthSolomachine
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthSolomachine = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowSolomachine = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupSolomachine = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/modules/light-clients/06-solomachine/types/solomachine_test.go b/modules/light-clients/06-solomachine/solomachine_test.go
similarity index 85%
rename from modules/light-clients/06-solomachine/types/solomachine_test.go
rename to modules/light-clients/06-solomachine/solomachine_test.go
index c789df47228..c73a8ecebc4 100644
--- a/modules/light-clients/06-solomachine/types/solomachine_test.go
+++ b/modules/light-clients/06-solomachine/solomachine_test.go
@@ -1,4 +1,4 @@
-package types_test
+package solomachine_test
import (
"testing"
@@ -6,7 +6,6 @@ import (
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
- cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
@@ -14,7 +13,7 @@ import (
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
+ solomachine "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -58,7 +57,7 @@ func (suite *SoloMachineTestSuite) GetSequenceFromStore() uint64 {
}
func (suite *SoloMachineTestSuite) GetInvalidProof() []byte {
- invalidProof, err := suite.chainA.Codec.Marshal(&types.TimestampedSignatureData{Timestamp: suite.solomachine.Time})
+ invalidProof, err := suite.chainA.Codec.Marshal(&solomachine.TimestampedSignatureData{Timestamp: suite.solomachine.Time})
suite.Require().NoError(err)
return invalidProof
@@ -68,17 +67,17 @@ func TestUnpackInterfaces_Header(t *testing.T) {
registry := testdata.NewTestInterfaceRegistry()
cryptocodec.RegisterInterfaces(registry)
- pk := secp256k1.GenPrivKey().PubKey().(cryptotypes.PubKey)
+ pk := secp256k1.GenPrivKey().PubKey()
any, err := codectypes.NewAnyWithValue(pk)
require.NoError(t, err)
- header := types.Header{
+ header := solomachine.Header{
NewPublicKey: any,
}
bz, err := header.Marshal()
require.NoError(t, err)
- var header2 types.Header
+ var header2 solomachine.Header
err = header2.Unmarshal(bz)
require.NoError(t, err)
@@ -92,17 +91,17 @@ func TestUnpackInterfaces_HeaderData(t *testing.T) {
registry := testdata.NewTestInterfaceRegistry()
cryptocodec.RegisterInterfaces(registry)
- pk := secp256k1.GenPrivKey().PubKey().(cryptotypes.PubKey)
+ pk := secp256k1.GenPrivKey().PubKey()
any, err := codectypes.NewAnyWithValue(pk)
require.NoError(t, err)
- hd := types.HeaderData{
+ hd := solomachine.HeaderData{
NewPubKey: any,
}
bz, err := hd.Marshal()
require.NoError(t, err)
- var hd2 types.HeaderData
+ var hd2 solomachine.HeaderData
err = hd2.Unmarshal(bz)
require.NoError(t, err)
diff --git a/modules/light-clients/06-solomachine/spec/01_concepts.md b/modules/light-clients/06-solomachine/spec/01_concepts.md
index 75d31bf5340..602c9947f71 100644
--- a/modules/light-clients/06-solomachine/spec/01_concepts.md
+++ b/modules/light-clients/06-solomachine/spec/01_concepts.md
@@ -56,7 +56,7 @@ data := &ClientStateData{
dataBz, err := cdc.Marshal(data)
```
-The helper functions `...DataBytes()` in [proof.go](../types/proof.go) handle this
+The helper functions `...DataBytes()` in [proof.go](../proof.go) handle this
functionality.
2. Construct the `SignBytes` and marshal it.
@@ -75,7 +75,7 @@ signBytes := &SignBytes{
signBz, err := cdc.Marshal(signBytes)
```
-The helper functions `...SignBytes()` in [proof.go](../types/proof.go) handle this functionality.
+The helper functions `...SignBytes()` in [proof.go](../proof.go) handle this functionality.
The `DataType` field is used to disambiguate what type of data was signed to prevent potential
proto encoding overlap.
@@ -100,7 +100,7 @@ as the proof parameter to the verification functions.
For example:
```go
-timestampedSignatureData := &types.TimestampedSignatureData{
+timestampedSignatureData := &solomachine.TimestampedSignatureData{
SignatureData: sigData,
Timestamp: solomachine.Time,
}
diff --git a/modules/light-clients/06-solomachine/types/client_state.go b/modules/light-clients/06-solomachine/types/client_state.go
deleted file mode 100644
index e489486ed4f..00000000000
--- a/modules/light-clients/06-solomachine/types/client_state.go
+++ /dev/null
@@ -1,491 +0,0 @@
-package types
-
-import (
- "reflect"
-
- "github.com/cosmos/cosmos-sdk/codec"
- cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
- sdk "github.com/cosmos/cosmos-sdk/types"
- sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
- "github.com/cosmos/cosmos-sdk/types/tx/signing"
-
- clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
- host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
-)
-
-var _ exported.ClientState = (*ClientState)(nil)
-
-// NewClientState creates a new ClientState instance.
-func NewClientState(latestSequence uint64, consensusState *ConsensusState, allowUpdateAfterProposal bool) *ClientState {
- return &ClientState{
- Sequence: latestSequence,
- IsFrozen: false,
- ConsensusState: consensusState,
- AllowUpdateAfterProposal: allowUpdateAfterProposal,
- }
-}
-
-// ClientType is Solo Machine.
-func (cs ClientState) ClientType() string {
- return exported.Solomachine
-}
-
-// GetLatestHeight returns the latest sequence number.
-// Return exported.Height to satisfy ClientState interface
-// Revision number is always 0 for a solo-machine.
-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.BinaryCodec) exported.Status {
- if cs.IsFrozen {
- return exported.Frozen
- }
-
- return exported.Active
-}
-
-// Validate performs basic validation of the client state fields.
-func (cs ClientState) Validate() error {
- if cs.Sequence == 0 {
- return sdkerrors.Wrap(clienttypes.ErrInvalidClient, "sequence cannot be 0")
- }
- if cs.ConsensusState == nil {
- return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "consensus state cannot be nil")
- }
- return cs.ConsensusState.ValidateBasic()
-}
-
-// ZeroCustomFields returns solomachine client state with client-specific fields FrozenSequence,
-// and AllowUpdateAfterProposal zeroed out
-func (cs ClientState) ZeroCustomFields() exported.ClientState {
- return NewClientState(
- cs.Sequence, cs.ConsensusState, false,
- )
-}
-
-// Initialize will check that initial consensus state is equal to the latest consensus state of the initial client.
-func (cs ClientState) Initialize(_ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore, consState exported.ConsensusState) error {
- if !reflect.DeepEqual(cs.ConsensusState, consState) {
- return sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "consensus state in initial client does not equal initial consensus state. expected: %s, got: %s",
- cs.ConsensusState, consState)
- }
- return nil
-}
-
-// ExportMetadata is a no-op since solomachine does not store any metadata in client store
-func (cs ClientState) ExportMetadata(_ sdk.KVStore) []exported.GenesisMetadata {
- return nil
-}
-
-// VerifyUpgradeAndUpdateState returns an error since solomachine client does not support upgrades
-func (cs ClientState) VerifyUpgradeAndUpdateState(
- _ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore,
- _ exported.ClientState, _ exported.ConsensusState, _, _ []byte,
-) (exported.ClientState, exported.ConsensusState, error) {
- return nil, nil, sdkerrors.Wrap(clienttypes.ErrInvalidUpgradeClient, "cannot upgrade solomachine client")
-}
-
-// VerifyClientState verifies a proof of the client state of the running chain
-// stored on the solo machine.
-func (cs *ClientState) VerifyClientState(
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- prefix exported.Prefix,
- counterpartyClientIdentifier string,
- proof []byte,
- clientState exported.ClientState,
-) error {
- // NOTE: the proof height sequence is incremented by one due to the connection handshake verification ordering
- height = clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1)
-
- publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- clientPrefixedPath := commitmenttypes.NewMerklePath(host.FullClientStatePath(counterpartyClientIdentifier))
- path, err := commitmenttypes.ApplyPrefix(prefix, clientPrefixedPath)
- if err != nil {
- return err
- }
-
- signBz, err := ClientStateSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path, clientState)
- if err != nil {
- return err
- }
-
- if err := VerifySignature(publicKey, signBz, sigData); err != nil {
- return err
- }
-
- cs.Sequence++
- cs.ConsensusState.Timestamp = timestamp
- setClientState(store, cdc, cs)
- return nil
-}
-
-// VerifyClientConsensusState verifies a proof of the consensus state of the
-// running chain stored on the solo machine.
-func (cs *ClientState) VerifyClientConsensusState(
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- counterpartyClientIdentifier string,
- consensusHeight exported.Height,
- prefix exported.Prefix,
- proof []byte,
- consensusState exported.ConsensusState,
-) error {
- // NOTE: the proof height sequence is incremented by two due to the connection handshake verification ordering
- height = clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+2)
-
- publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- clientPrefixedPath := commitmenttypes.NewMerklePath(host.FullConsensusStatePath(counterpartyClientIdentifier, consensusHeight))
- path, err := commitmenttypes.ApplyPrefix(prefix, clientPrefixedPath)
- if err != nil {
- return err
- }
-
- signBz, err := ConsensusStateSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path, consensusState)
- if err != nil {
- return err
- }
-
- if err := VerifySignature(publicKey, signBz, sigData); err != nil {
- return err
- }
-
- cs.Sequence++
- cs.ConsensusState.Timestamp = timestamp
- setClientState(store, cdc, cs)
- return nil
-}
-
-// VerifyConnectionState verifies a proof of the connection state of the
-// specified connection end stored on the target machine.
-func (cs *ClientState) VerifyConnectionState(
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- prefix exported.Prefix,
- proof []byte,
- connectionID string,
- connectionEnd exported.ConnectionI,
-) error {
- publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- connectionPath := commitmenttypes.NewMerklePath(host.ConnectionPath(connectionID))
- path, err := commitmenttypes.ApplyPrefix(prefix, connectionPath)
- if err != nil {
- return err
- }
-
- signBz, err := ConnectionStateSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path, connectionEnd)
- if err != nil {
- return err
- }
-
- if err := VerifySignature(publicKey, signBz, sigData); err != nil {
- return err
- }
-
- cs.Sequence++
- cs.ConsensusState.Timestamp = timestamp
- setClientState(store, cdc, cs)
- return nil
-}
-
-// VerifyChannelState verifies a proof of the channel state of the specified
-// channel end, under the specified port, stored on the target machine.
-func (cs *ClientState) VerifyChannelState(
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- prefix exported.Prefix,
- proof []byte,
- portID,
- channelID string,
- channel exported.ChannelI,
-) error {
- publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- channelPath := commitmenttypes.NewMerklePath(host.ChannelPath(portID, channelID))
- path, err := commitmenttypes.ApplyPrefix(prefix, channelPath)
- if err != nil {
- return err
- }
-
- signBz, err := ChannelStateSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path, channel)
- if err != nil {
- return err
- }
-
- if err := VerifySignature(publicKey, signBz, sigData); err != nil {
- return err
- }
-
- cs.Sequence++
- cs.ConsensusState.Timestamp = timestamp
- setClientState(store, cdc, cs)
- return nil
-}
-
-// VerifyPacketCommitment verifies a proof of an outgoing packet commitment at
-// the specified port, specified channel, and specified sequence.
-func (cs *ClientState) VerifyPacketCommitment(
- ctx sdk.Context,
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- _ uint64,
- _ uint64,
- prefix exported.Prefix,
- proof []byte,
- portID,
- channelID string,
- packetSequence uint64,
- commitmentBytes []byte,
-) error {
- publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- commitmentPath := commitmenttypes.NewMerklePath(host.PacketCommitmentPath(portID, channelID, packetSequence))
- path, err := commitmenttypes.ApplyPrefix(prefix, commitmentPath)
- if err != nil {
- return err
- }
-
- signBz, err := PacketCommitmentSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path, commitmentBytes)
- if err != nil {
- return err
- }
-
- if err := VerifySignature(publicKey, signBz, sigData); err != nil {
- return err
- }
-
- cs.Sequence++
- cs.ConsensusState.Timestamp = timestamp
- setClientState(store, cdc, cs)
- return nil
-}
-
-// VerifyPacketAcknowledgement verifies a proof of an incoming packet
-// acknowledgement at the specified port, specified channel, and specified sequence.
-func (cs *ClientState) VerifyPacketAcknowledgement(
- ctx sdk.Context,
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- _ uint64,
- _ uint64,
- prefix exported.Prefix,
- proof []byte,
- portID,
- channelID string,
- packetSequence uint64,
- acknowledgement []byte,
-) error {
- publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- ackPath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementPath(portID, channelID, packetSequence))
- path, err := commitmenttypes.ApplyPrefix(prefix, ackPath)
- if err != nil {
- return err
- }
-
- signBz, err := PacketAcknowledgementSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path, acknowledgement)
- if err != nil {
- return err
- }
-
- if err := VerifySignature(publicKey, signBz, sigData); err != nil {
- return err
- }
-
- cs.Sequence++
- cs.ConsensusState.Timestamp = timestamp
- setClientState(store, cdc, cs)
- return nil
-}
-
-// VerifyPacketReceiptAbsence verifies a proof of the absence of an
-// incoming packet receipt at the specified port, specified channel, and
-// specified sequence.
-func (cs *ClientState) VerifyPacketReceiptAbsence(
- ctx sdk.Context,
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- _ uint64,
- _ uint64,
- prefix exported.Prefix,
- proof []byte,
- portID,
- channelID string,
- packetSequence uint64,
-) error {
- publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- receiptPath := commitmenttypes.NewMerklePath(host.PacketReceiptPath(portID, channelID, packetSequence))
- path, err := commitmenttypes.ApplyPrefix(prefix, receiptPath)
- if err != nil {
- return err
- }
-
- signBz, err := PacketReceiptAbsenceSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path)
- if err != nil {
- return err
- }
-
- if err := VerifySignature(publicKey, signBz, sigData); err != nil {
- return err
- }
-
- cs.Sequence++
- cs.ConsensusState.Timestamp = timestamp
- setClientState(store, cdc, cs)
- return nil
-}
-
-// VerifyNextSequenceRecv verifies a proof of the next sequence number to be
-// received of the specified channel at the specified port.
-func (cs *ClientState) VerifyNextSequenceRecv(
- ctx sdk.Context,
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- _ uint64,
- _ uint64,
- prefix exported.Prefix,
- proof []byte,
- portID,
- channelID string,
- nextSequenceRecv uint64,
-) error {
- publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- nextSequenceRecvPath := commitmenttypes.NewMerklePath(host.NextSequenceRecvPath(portID, channelID))
- path, err := commitmenttypes.ApplyPrefix(prefix, nextSequenceRecvPath)
- if err != nil {
- return err
- }
-
- signBz, err := NextSequenceRecvSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path, nextSequenceRecv)
- if err != nil {
- return err
- }
-
- if err := VerifySignature(publicKey, signBz, sigData); err != nil {
- return err
- }
-
- cs.Sequence++
- cs.ConsensusState.Timestamp = timestamp
- setClientState(store, cdc, cs)
- return nil
-}
-
-// produceVerificationArgs perfoms the basic checks on the arguments that are
-// shared between the verification functions and returns the public key of the
-// consensus state, the unmarshalled proof representing the signature and timestamp
-// along with the solo-machine sequence encoded in the proofHeight.
-func produceVerificationArgs(
- cdc codec.BinaryCodec,
- cs *ClientState,
- height exported.Height,
- prefix exported.Prefix,
- proof []byte,
-) (cryptotypes.PubKey, signing.SignatureData, uint64, uint64, error) {
- if revision := height.GetRevisionNumber(); revision != 0 {
- return nil, nil, 0, 0, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "revision must be 0 for solomachine, got revision-number: %d", revision)
- }
- // sequence is encoded in the revision height of height struct
- sequence := height.GetRevisionHeight()
- if prefix == nil {
- return nil, nil, 0, 0, sdkerrors.Wrap(commitmenttypes.ErrInvalidPrefix, "prefix cannot be empty")
- }
-
- _, ok := prefix.(*commitmenttypes.MerklePrefix)
- if !ok {
- return nil, nil, 0, 0, sdkerrors.Wrapf(commitmenttypes.ErrInvalidPrefix, "invalid prefix type %T, expected MerklePrefix", prefix)
- }
-
- if proof == nil {
- return nil, nil, 0, 0, sdkerrors.Wrap(ErrInvalidProof, "proof cannot be empty")
- }
-
- timestampedSigData := &TimestampedSignatureData{}
- if err := cdc.Unmarshal(proof, timestampedSigData); err != nil {
- return nil, nil, 0, 0, sdkerrors.Wrapf(err, "failed to unmarshal proof into type %T", timestampedSigData)
- }
-
- timestamp := timestampedSigData.Timestamp
-
- if len(timestampedSigData.SignatureData) == 0 {
- return nil, nil, 0, 0, sdkerrors.Wrap(ErrInvalidProof, "signature data cannot be empty")
- }
-
- sigData, err := UnmarshalSignatureData(cdc, timestampedSigData.SignatureData)
- if err != nil {
- return nil, nil, 0, 0, err
- }
-
- if cs.ConsensusState == nil {
- return nil, nil, 0, 0, sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "consensus state cannot be empty")
- }
-
- latestSequence := cs.GetLatestHeight().GetRevisionHeight()
- if latestSequence != sequence {
- return nil, nil, 0, 0, sdkerrors.Wrapf(
- sdkerrors.ErrInvalidHeight,
- "client state sequence != proof sequence (%d != %d)", latestSequence, sequence,
- )
- }
-
- if cs.ConsensusState.GetTimestamp() > timestamp {
- return nil, nil, 0, 0, sdkerrors.Wrapf(ErrInvalidProof, "the consensus state timestamp is greater than the signature timestamp (%d >= %d)", cs.ConsensusState.GetTimestamp(), timestamp)
- }
-
- publicKey, err := cs.ConsensusState.GetPubKey()
- if err != nil {
- return nil, nil, 0, 0, err
- }
-
- return publicKey, sigData, timestamp, sequence, nil
-}
-
-// sets the client state to the store
-func setClientState(store sdk.KVStore, cdc codec.BinaryCodec, clientState exported.ClientState) {
- bz := clienttypes.MustMarshalClientState(cdc, clientState)
- store.Set([]byte(host.KeyClientState), bz)
-}
diff --git a/modules/light-clients/06-solomachine/types/client_state_test.go b/modules/light-clients/06-solomachine/types/client_state_test.go
deleted file mode 100644
index 496688bb43d..00000000000
--- a/modules/light-clients/06-solomachine/types/client_state_test.go
+++ /dev/null
@@ -1,844 +0,0 @@
-package types_test
-
-import (
- clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- connectiontypes "github.com/cosmos/ibc-go/v5/modules/core/03-connection/types"
- channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
- commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
- ibctesting "github.com/cosmos/ibc-go/v5/testing"
-)
-
-const (
- counterpartyClientIdentifier = "chainA"
- testConnectionID = "connectionid"
- testChannelID = "testchannelid"
- testPortID = "testportid"
-)
-
-var (
- prefix = &commitmenttypes.MerklePrefix{
- KeyPrefix: []byte("ibc"),
- }
- consensusHeight = clienttypes.ZeroHeight()
-)
-
-func (suite *SoloMachineTestSuite) TestStatus() {
- clientState := suite.solomachine.ClientState()
- // solo machine discards arguments
- status := clientState.Status(suite.chainA.GetContext(), nil, nil)
- suite.Require().Equal(exported.Active, status)
-
- // freeze solo machine
- clientState.IsFrozen = true
- 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} {
-
- testCases := []struct {
- name string
- clientState *types.ClientState
- expPass bool
- }{
- {
- "valid client state",
- solomachine.ClientState(),
- true,
- },
- {
- "empty ClientState",
- &types.ClientState{},
- false,
- },
- {
- "sequence is zero",
- types.NewClientState(0, &types.ConsensusState{solomachine.ConsensusState().PublicKey, solomachine.Diversifier, solomachine.Time}, false),
- false,
- },
- {
- "timestamp is zero",
- types.NewClientState(1, &types.ConsensusState{solomachine.ConsensusState().PublicKey, solomachine.Diversifier, 0}, false),
- false,
- },
- {
- "diversifier is blank",
- types.NewClientState(1, &types.ConsensusState{solomachine.ConsensusState().PublicKey, " ", 1}, false),
- false,
- },
- {
- "pubkey is empty",
- types.NewClientState(1, &types.ConsensusState{nil, solomachine.Diversifier, solomachine.Time}, false),
- false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- err := tc.clientState.Validate()
-
- if tc.expPass {
- suite.Require().NoError(err)
- } else {
- suite.Require().Error(err)
- }
- })
- }
- }
-}
-
-func (suite *SoloMachineTestSuite) TestInitialize() {
- // test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
- malleatedConsensus := solomachine.ClientState().ConsensusState
- malleatedConsensus.Timestamp = malleatedConsensus.Timestamp + 10
-
- testCases := []struct {
- name string
- consState exported.ConsensusState
- expPass bool
- }{
- {
- "valid consensus state",
- solomachine.ConsensusState(),
- true,
- },
- {
- "nil consensus state",
- nil,
- false,
- },
- {
- "invalid consensus state: Tendermint consensus state",
- &ibctmtypes.ConsensusState{},
- false,
- },
- {
- "invalid consensus state: consensus state does not match consensus state in client",
- malleatedConsensus,
- false,
- },
- }
-
- for _, tc := range testCases {
- err := solomachine.ClientState().Initialize(
- suite.chainA.GetContext(), suite.chainA.Codec,
- suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "solomachine"),
- tc.consState,
- )
-
- if tc.expPass {
- suite.Require().NoError(err, "valid testcase: %s failed", tc.name)
- } else {
- suite.Require().Error(err, "invalid testcase: %s passed", tc.name)
- }
- }
- }
-}
-
-func (suite *SoloMachineTestSuite) TestVerifyClientState() {
- // create client for tendermint so we can use client state for verification
- tmPath := ibctesting.NewPath(suite.chainA, suite.chainB)
- suite.coordinator.SetupClients(tmPath)
- clientState := suite.chainA.GetClientState(tmPath.EndpointA.ClientID)
- path := suite.solomachine.GetClientStatePath(counterpartyClientIdentifier)
-
- // test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
-
- value, err := types.ClientStateSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, clientState)
- suite.Require().NoError(err)
-
- sig := solomachine.GenerateSignature(value)
-
- signatureDoc := &types.TimestampedSignatureData{
- SignatureData: sig,
- Timestamp: solomachine.Time,
- }
-
- proof, err := suite.chainA.Codec.Marshal(signatureDoc)
- suite.Require().NoError(err)
-
- testCases := []struct {
- name string
- clientState *types.ClientState
- prefix exported.Prefix
- proof []byte
- expPass bool
- }{
- {
- "successful verification",
- solomachine.ClientState(),
- prefix,
- proof,
- true,
- },
- {
- "ApplyPrefix failed",
- solomachine.ClientState(),
- nil,
- proof,
- false,
- },
- {
- "consensus state in client state is nil",
- types.NewClientState(1, nil, false),
- prefix,
- proof,
- false,
- },
- {
- "client state latest height is less than sequence",
- types.NewClientState(solomachine.Sequence-1,
- &types.ConsensusState{
- Timestamp: solomachine.Time,
- PublicKey: solomachine.ConsensusState().PublicKey,
- }, false),
- prefix,
- proof,
- false,
- },
- {
- "consensus state timestamp is greater than signature",
- types.NewClientState(solomachine.Sequence,
- &types.ConsensusState{
- Timestamp: solomachine.Time + 1,
- PublicKey: solomachine.ConsensusState().PublicKey,
- }, false),
- prefix,
- proof,
- false,
- },
-
- {
- "proof is nil",
- solomachine.ClientState(),
- prefix,
- nil,
- false,
- },
- {
- "proof verification failed",
- solomachine.ClientState(),
- prefix,
- suite.GetInvalidProof(),
- false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- var expSeq uint64
- if tc.clientState.ConsensusState != nil {
- expSeq = tc.clientState.Sequence + 1
- }
-
- // NOTE: to replicate the ordering of connection handshake, we must decrement proof height by 1
- height := clienttypes.NewHeight(solomachine.GetHeight().GetRevisionNumber(), solomachine.GetHeight().GetRevisionHeight()-1)
-
- err := tc.clientState.VerifyClientState(
- suite.store, suite.chainA.Codec, height, tc.prefix, counterpartyClientIdentifier, tc.proof, clientState,
- )
-
- if tc.expPass {
- suite.Require().NoError(err)
- suite.Require().Equal(expSeq, tc.clientState.Sequence)
- suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %s", suite.GetSequenceFromStore(), tc.name)
- } else {
- suite.Require().Error(err)
- }
- })
- }
- }
-}
-
-func (suite *SoloMachineTestSuite) TestVerifyClientConsensusState() {
- // create client for tendermint so we can use consensus state for verification
- tmPath := ibctesting.NewPath(suite.chainA, suite.chainB)
- suite.coordinator.SetupClients(tmPath)
- clientState := suite.chainA.GetClientState(tmPath.EndpointA.ClientID)
- consensusState, found := suite.chainA.GetConsensusState(tmPath.EndpointA.ClientID, clientState.GetLatestHeight())
- suite.Require().True(found)
-
- path := suite.solomachine.GetConsensusStatePath(counterpartyClientIdentifier, consensusHeight)
-
- // test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
-
- value, err := types.ConsensusStateSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, consensusState)
- suite.Require().NoError(err)
-
- sig := solomachine.GenerateSignature(value)
- signatureDoc := &types.TimestampedSignatureData{
- SignatureData: sig,
- Timestamp: solomachine.Time,
- }
-
- proof, err := suite.chainA.Codec.Marshal(signatureDoc)
- suite.Require().NoError(err)
-
- testCases := []struct {
- name string
- clientState *types.ClientState
- prefix exported.Prefix
- proof []byte
- expPass bool
- }{
- {
- "successful verification",
- solomachine.ClientState(),
- prefix,
- proof,
- true,
- },
- {
- "ApplyPrefix failed",
- solomachine.ClientState(),
- nil,
- proof,
- false,
- },
- {
- "consensus state in client state is nil",
- types.NewClientState(1, nil, false),
- prefix,
- proof,
- false,
- },
- {
- "client state latest height is less than sequence",
- types.NewClientState(solomachine.Sequence-1,
- &types.ConsensusState{
- Timestamp: solomachine.Time,
- PublicKey: solomachine.ConsensusState().PublicKey,
- }, false),
- prefix,
- proof,
- false,
- },
- {
- "consensus state timestamp is greater than signature",
- types.NewClientState(solomachine.Sequence,
- &types.ConsensusState{
- Timestamp: solomachine.Time + 1,
- PublicKey: solomachine.ConsensusState().PublicKey,
- }, false),
- prefix,
- proof,
- false,
- },
-
- {
- "proof is nil",
- solomachine.ClientState(),
- prefix,
- nil,
- false,
- },
- {
- "proof verification failed",
- solomachine.ClientState(),
- prefix,
- suite.GetInvalidProof(),
- false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- var expSeq uint64
- if tc.clientState.ConsensusState != nil {
- expSeq = tc.clientState.Sequence + 1
- }
-
- // NOTE: to replicate the ordering of connection handshake, we must decrement proof height by 1
- height := clienttypes.NewHeight(solomachine.GetHeight().GetRevisionNumber(), solomachine.GetHeight().GetRevisionHeight()-2)
-
- err := tc.clientState.VerifyClientConsensusState(
- suite.store, suite.chainA.Codec, height, counterpartyClientIdentifier, consensusHeight, tc.prefix, tc.proof, consensusState,
- )
-
- if tc.expPass {
- suite.Require().NoError(err)
- suite.Require().Equal(expSeq, tc.clientState.Sequence)
- suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %s", suite.GetSequenceFromStore(), tc.name)
- } else {
- suite.Require().Error(err)
- }
- })
- }
- }
-}
-
-func (suite *SoloMachineTestSuite) TestVerifyConnectionState() {
- counterparty := connectiontypes.NewCounterparty("clientB", testConnectionID, *prefix)
- conn := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "clientA", counterparty, connectiontypes.ExportedVersionsToProto(connectiontypes.GetCompatibleVersions()), 0)
-
- path := suite.solomachine.GetConnectionStatePath(testConnectionID)
-
- // test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
-
- value, err := types.ConnectionStateSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, conn)
- suite.Require().NoError(err)
-
- sig := solomachine.GenerateSignature(value)
- signatureDoc := &types.TimestampedSignatureData{
- SignatureData: sig,
- Timestamp: solomachine.Time,
- }
-
- proof, err := suite.chainA.Codec.Marshal(signatureDoc)
- suite.Require().NoError(err)
-
- testCases := []struct {
- name string
- clientState *types.ClientState
- prefix exported.Prefix
- proof []byte
- expPass bool
- }{
- {
- "successful verification",
- solomachine.ClientState(),
- prefix,
- proof,
- true,
- },
- {
- "ApplyPrefix failed",
- solomachine.ClientState(),
- commitmenttypes.NewMerklePrefix([]byte{}),
- proof,
- false,
- },
- {
- "proof is nil",
- solomachine.ClientState(),
- prefix,
- nil,
- false,
- },
- {
- "proof verification failed",
- solomachine.ClientState(),
- prefix,
- suite.GetInvalidProof(),
- false,
- },
- }
-
- for i, tc := range testCases {
- tc := tc
-
- expSeq := tc.clientState.Sequence + 1
-
- err := tc.clientState.VerifyConnectionState(
- suite.store, suite.chainA.Codec, solomachine.GetHeight(), tc.prefix, tc.proof, testConnectionID, conn,
- )
-
- if tc.expPass {
- suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
- suite.Require().Equal(expSeq, tc.clientState.Sequence)
- suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %d: %s", suite.GetSequenceFromStore(), i, tc.name)
- } else {
- suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
- }
- }
- }
-}
-
-func (suite *SoloMachineTestSuite) TestVerifyChannelState() {
- counterparty := channeltypes.NewCounterparty(testPortID, testChannelID)
- ch := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, counterparty, []string{testConnectionID}, "1.0.0")
-
- path := suite.solomachine.GetChannelStatePath(testPortID, testChannelID)
-
- // test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
-
- value, err := types.ChannelStateSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, ch)
- suite.Require().NoError(err)
-
- sig := solomachine.GenerateSignature(value)
- signatureDoc := &types.TimestampedSignatureData{
- SignatureData: sig,
- Timestamp: solomachine.Time,
- }
-
- proof, err := suite.chainA.Codec.Marshal(signatureDoc)
- suite.Require().NoError(err)
-
- testCases := []struct {
- name string
- clientState *types.ClientState
- prefix exported.Prefix
- proof []byte
- expPass bool
- }{
- {
- "successful verification",
- solomachine.ClientState(),
- prefix,
- proof,
- true,
- },
- {
- "ApplyPrefix failed",
- solomachine.ClientState(),
- nil,
- proof,
- false,
- },
- {
- "proof is nil",
- solomachine.ClientState(),
- prefix,
- nil,
- false,
- },
- {
- "proof verification failed",
- solomachine.ClientState(),
- prefix,
- suite.GetInvalidProof(),
- false,
- },
- }
-
- for i, tc := range testCases {
- tc := tc
-
- expSeq := tc.clientState.Sequence + 1
-
- err := tc.clientState.VerifyChannelState(
- suite.store, suite.chainA.Codec, solomachine.GetHeight(), tc.prefix, tc.proof, testPortID, testChannelID, ch,
- )
-
- if tc.expPass {
- suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
- suite.Require().Equal(expSeq, tc.clientState.Sequence)
- suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %d: %s", suite.GetSequenceFromStore(), i, tc.name)
- } else {
- suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
- }
- }
- }
-}
-
-func (suite *SoloMachineTestSuite) TestVerifyPacketCommitment() {
- commitmentBytes := []byte("COMMITMENT BYTES")
-
- // test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
-
- path := solomachine.GetPacketCommitmentPath(testPortID, testChannelID)
-
- value, err := types.PacketCommitmentSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, commitmentBytes)
- suite.Require().NoError(err)
-
- sig := solomachine.GenerateSignature(value)
- signatureDoc := &types.TimestampedSignatureData{
- SignatureData: sig,
- Timestamp: solomachine.Time,
- }
-
- proof, err := suite.chainA.Codec.Marshal(signatureDoc)
- suite.Require().NoError(err)
-
- testCases := []struct {
- name string
- clientState *types.ClientState
- prefix exported.Prefix
- proof []byte
- expPass bool
- }{
- {
- "successful verification",
- solomachine.ClientState(),
- prefix,
- proof,
- true,
- },
- {
- "ApplyPrefix failed",
- solomachine.ClientState(),
- commitmenttypes.NewMerklePrefix([]byte{}),
- proof,
- false,
- },
- {
- "proof is nil",
- solomachine.ClientState(),
- prefix,
- nil,
- false,
- },
- {
- "proof verification failed",
- solomachine.ClientState(),
- prefix,
- suite.GetInvalidProof(),
- false,
- },
- }
-
- for i, tc := range testCases {
- tc := tc
-
- expSeq := tc.clientState.Sequence + 1
- ctx := suite.chainA.GetContext()
-
- err := tc.clientState.VerifyPacketCommitment(
- ctx, suite.store, suite.chainA.Codec, solomachine.GetHeight(), 0, 0, tc.prefix, tc.proof, testPortID, testChannelID, solomachine.Sequence, commitmentBytes,
- )
-
- if tc.expPass {
- suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
- suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %d: %s", suite.GetSequenceFromStore(), i, tc.name)
- } else {
- suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
- }
- }
- }
-}
-
-func (suite *SoloMachineTestSuite) TestVerifyPacketAcknowledgement() {
- ack := []byte("ACK")
- // test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
-
- path := solomachine.GetPacketAcknowledgementPath(testPortID, testChannelID)
-
- value, err := types.PacketAcknowledgementSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, ack)
- suite.Require().NoError(err)
-
- sig := solomachine.GenerateSignature(value)
- signatureDoc := &types.TimestampedSignatureData{
- SignatureData: sig,
- Timestamp: solomachine.Time,
- }
-
- proof, err := suite.chainA.Codec.Marshal(signatureDoc)
- suite.Require().NoError(err)
-
- testCases := []struct {
- name string
- clientState *types.ClientState
- prefix exported.Prefix
- proof []byte
- expPass bool
- }{
- {
- "successful verification",
- solomachine.ClientState(),
- prefix,
- proof,
- true,
- },
- {
- "ApplyPrefix failed",
- solomachine.ClientState(),
- commitmenttypes.NewMerklePrefix([]byte{}),
- proof,
- false,
- },
- {
- "proof is nil",
- solomachine.ClientState(),
- prefix,
- nil,
- false,
- },
- {
- "proof verification failed",
- solomachine.ClientState(),
- prefix,
- suite.GetInvalidProof(),
- false,
- },
- }
-
- for i, tc := range testCases {
- tc := tc
-
- expSeq := tc.clientState.Sequence + 1
- ctx := suite.chainA.GetContext()
-
- err := tc.clientState.VerifyPacketAcknowledgement(
- ctx, suite.store, suite.chainA.Codec, solomachine.GetHeight(), 0, 0, tc.prefix, tc.proof, testPortID, testChannelID, solomachine.Sequence, ack,
- )
-
- if tc.expPass {
- suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
- suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %d: %s", suite.GetSequenceFromStore(), i, tc.name)
- } else {
- suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
- }
- }
- }
-}
-
-func (suite *SoloMachineTestSuite) TestVerifyPacketReceiptAbsence() {
- // test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
-
- // absence uses receipt path as well
- path := solomachine.GetPacketReceiptPath(testPortID, testChannelID)
-
- value, err := types.PacketReceiptAbsenceSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path)
- suite.Require().NoError(err)
-
- sig := solomachine.GenerateSignature(value)
- signatureDoc := &types.TimestampedSignatureData{
- SignatureData: sig,
- Timestamp: solomachine.Time,
- }
-
- proof, err := suite.chainA.Codec.Marshal(signatureDoc)
- suite.Require().NoError(err)
-
- testCases := []struct {
- name string
- clientState *types.ClientState
- prefix exported.Prefix
- proof []byte
- expPass bool
- }{
- {
- "successful verification",
- solomachine.ClientState(),
- prefix,
- proof,
- true,
- },
- {
- "ApplyPrefix failed",
- solomachine.ClientState(),
- commitmenttypes.NewMerklePrefix([]byte{}),
- proof,
- false,
- },
- {
- "proof is nil",
- solomachine.ClientState(),
- prefix,
- nil,
- false,
- },
- {
- "proof verification failed",
- solomachine.ClientState(),
- prefix,
- suite.GetInvalidProof(),
- false,
- },
- }
-
- for i, tc := range testCases {
- tc := tc
-
- expSeq := tc.clientState.Sequence + 1
- ctx := suite.chainA.GetContext()
-
- err := tc.clientState.VerifyPacketReceiptAbsence(
- ctx, suite.store, suite.chainA.Codec, solomachine.GetHeight(), 0, 0, tc.prefix, tc.proof, testPortID, testChannelID, solomachine.Sequence,
- )
-
- if tc.expPass {
- suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
- suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %d: %s", suite.GetSequenceFromStore(), i, tc.name)
- } else {
- suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
- }
- }
- }
-}
-
-func (suite *SoloMachineTestSuite) TestVerifyNextSeqRecv() {
- // test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
-
- nextSeqRecv := solomachine.Sequence + 1
- path := solomachine.GetNextSequenceRecvPath(testPortID, testChannelID)
-
- value, err := types.NextSequenceRecvSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, nextSeqRecv)
- suite.Require().NoError(err)
-
- sig := solomachine.GenerateSignature(value)
- signatureDoc := &types.TimestampedSignatureData{
- SignatureData: sig,
- Timestamp: solomachine.Time,
- }
-
- proof, err := suite.chainA.Codec.Marshal(signatureDoc)
- suite.Require().NoError(err)
-
- testCases := []struct {
- name string
- clientState *types.ClientState
- prefix exported.Prefix
- proof []byte
- expPass bool
- }{
- {
- "successful verification",
- solomachine.ClientState(),
- prefix,
- proof,
- true,
- },
- {
- "ApplyPrefix failed",
- solomachine.ClientState(),
- commitmenttypes.NewMerklePrefix([]byte{}),
- proof,
- false,
- },
- {
- "proof is nil",
- solomachine.ClientState(),
- prefix,
- nil,
- false,
- },
- {
- "proof verification failed",
- solomachine.ClientState(),
- prefix,
- suite.GetInvalidProof(),
- false,
- },
- }
-
- for i, tc := range testCases {
- tc := tc
-
- expSeq := tc.clientState.Sequence + 1
- ctx := suite.chainA.GetContext()
-
- err := tc.clientState.VerifyNextSequenceRecv(
- ctx, suite.store, suite.chainA.Codec, solomachine.GetHeight(), 0, 0, tc.prefix, tc.proof, testPortID, testChannelID, nextSeqRecv,
- )
-
- if tc.expPass {
- suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
- suite.Require().Equal(expSeq, tc.clientState.Sequence)
- suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %d: %s", suite.GetSequenceFromStore(), i, tc.name)
- } else {
- suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
- }
- }
- }
-}
diff --git a/modules/light-clients/06-solomachine/types/codec.go b/modules/light-clients/06-solomachine/types/codec.go
deleted file mode 100644
index 3946b3ee2b5..00000000000
--- a/modules/light-clients/06-solomachine/types/codec.go
+++ /dev/null
@@ -1,131 +0,0 @@
-package types
-
-import (
- "github.com/cosmos/cosmos-sdk/codec"
- codectypes "github.com/cosmos/cosmos-sdk/codec/types"
- sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
- "github.com/cosmos/cosmos-sdk/types/tx/signing"
-
- clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
-)
-
-// RegisterInterfaces register the ibc channel submodule interfaces to protobuf
-// Any.
-func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
- registry.RegisterImplementations(
- (*exported.ClientState)(nil),
- &ClientState{},
- )
- registry.RegisterImplementations(
- (*exported.ConsensusState)(nil),
- &ConsensusState{},
- )
- registry.RegisterImplementations(
- (*exported.Header)(nil),
- &Header{},
- )
- registry.RegisterImplementations(
- (*exported.Misbehaviour)(nil),
- &Misbehaviour{},
- )
-}
-
-func UnmarshalSignatureData(cdc codec.BinaryCodec, data []byte) (signing.SignatureData, error) {
- protoSigData := &signing.SignatureDescriptor_Data{}
- if err := cdc.Unmarshal(data, protoSigData); err != nil {
- return nil, sdkerrors.Wrapf(err, "failed to unmarshal proof into type %T", protoSigData)
- }
-
- sigData := signing.SignatureDataFromProto(protoSigData)
-
- return sigData, nil
-}
-
-// UnmarshalDataByType attempts to unmarshal the data to the specified type. An error is
-// return if it fails.
-func UnmarshalDataByType(cdc codec.BinaryCodec, dataType DataType, data []byte) (Data, error) {
- if len(data) == 0 {
- return nil, sdkerrors.Wrap(ErrInvalidSignatureAndData, "data cannot be empty")
- }
-
- switch dataType {
- case UNSPECIFIED:
- return nil, sdkerrors.Wrap(ErrInvalidDataType, "data type cannot be UNSPECIFIED")
-
- case CLIENT:
- clientData := &ClientStateData{}
- if err := cdc.Unmarshal(data, clientData); err != nil {
- return nil, err
- }
-
- // unpack any
- if _, err := clienttypes.UnpackClientState(clientData.ClientState); err != nil {
- return nil, err
- }
- return clientData, nil
-
- case CONSENSUS:
- consensusData := &ConsensusStateData{}
- if err := cdc.Unmarshal(data, consensusData); err != nil {
- return nil, err
- }
-
- // unpack any
- if _, err := clienttypes.UnpackConsensusState(consensusData.ConsensusState); err != nil {
- return nil, err
- }
- return consensusData, nil
-
- case CONNECTION:
- connectionData := &ConnectionStateData{}
- if err := cdc.Unmarshal(data, connectionData); err != nil {
- return nil, err
- }
-
- return connectionData, nil
-
- case CHANNEL:
- channelData := &ChannelStateData{}
- if err := cdc.Unmarshal(data, channelData); err != nil {
- return nil, err
- }
-
- return channelData, nil
-
- case PACKETCOMMITMENT:
- commitmentData := &PacketCommitmentData{}
- if err := cdc.Unmarshal(data, commitmentData); err != nil {
- return nil, err
- }
-
- return commitmentData, nil
-
- case PACKETACKNOWLEDGEMENT:
- ackData := &PacketAcknowledgementData{}
- if err := cdc.Unmarshal(data, ackData); err != nil {
- return nil, err
- }
-
- return ackData, nil
-
- case PACKETRECEIPTABSENCE:
- receiptAbsenceData := &PacketReceiptAbsenceData{}
- if err := cdc.Unmarshal(data, receiptAbsenceData); err != nil {
- return nil, err
- }
-
- return receiptAbsenceData, nil
-
- case NEXTSEQUENCERECV:
- nextSeqRecvData := &NextSequenceRecvData{}
- if err := cdc.Unmarshal(data, nextSeqRecvData); err != nil {
- return nil, err
- }
-
- return nextSeqRecvData, nil
-
- default:
- return nil, sdkerrors.Wrapf(ErrInvalidDataType, "unsupported data type %T", dataType)
- }
-}
diff --git a/modules/light-clients/06-solomachine/types/codec_test.go b/modules/light-clients/06-solomachine/types/codec_test.go
deleted file mode 100644
index bef62d2654d..00000000000
--- a/modules/light-clients/06-solomachine/types/codec_test.go
+++ /dev/null
@@ -1,186 +0,0 @@
-package types_test
-
-import (
- clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- connectiontypes "github.com/cosmos/ibc-go/v5/modules/core/03-connection/types"
- channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
- ibctesting "github.com/cosmos/ibc-go/v5/testing"
-)
-
-func (suite SoloMachineTestSuite) TestUnmarshalDataByType() {
- var (
- data []byte
- err error
- )
-
- // test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
-
- cdc := suite.chainA.App.AppCodec()
- cases := []struct {
- name string
- dataType types.DataType
- malleate func()
- expPass bool
- }{
- {
- "empty data", types.CLIENT, func() {
- data = []byte{}
- }, false,
- },
- {
- "unspecified", types.UNSPECIFIED, func() {
- path := solomachine.GetClientStatePath(counterpartyClientIdentifier)
- data, err = types.ClientStateDataBytes(cdc, path, solomachine.ClientState())
- suite.Require().NoError(err)
- }, false,
- },
- {
- "client", types.CLIENT, func() {
- path := solomachine.GetClientStatePath(counterpartyClientIdentifier)
- data, err = types.ClientStateDataBytes(cdc, path, solomachine.ClientState())
- suite.Require().NoError(err)
- }, true,
- },
- {
- "bad client (provides consensus state data)", types.CLIENT, func() {
- path := solomachine.GetConsensusStatePath(counterpartyClientIdentifier, clienttypes.NewHeight(0, 5))
- data, err = types.ConsensusStateDataBytes(cdc, path, solomachine.ConsensusState())
- suite.Require().NoError(err)
- }, false,
- },
- {
- "consensus", types.CONSENSUS, func() {
- path := solomachine.GetConsensusStatePath(counterpartyClientIdentifier, clienttypes.NewHeight(0, 5))
- data, err = types.ConsensusStateDataBytes(cdc, path, solomachine.ConsensusState())
- suite.Require().NoError(err)
- }, true,
- },
- {
- "bad consensus (provides client state data)", types.CONSENSUS, func() {
- path := solomachine.GetClientStatePath(counterpartyClientIdentifier)
- data, err = types.ClientStateDataBytes(cdc, path, solomachine.ClientState())
- suite.Require().NoError(err)
- }, false,
- },
- {
- "connection", types.CONNECTION, func() {
- counterparty := connectiontypes.NewCounterparty("clientB", testConnectionID, *prefix)
- conn := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "clientA", counterparty, connectiontypes.ExportedVersionsToProto(connectiontypes.GetCompatibleVersions()), 0)
- path := solomachine.GetConnectionStatePath("connectionID")
-
- data, err = types.ConnectionStateDataBytes(cdc, path, conn)
- suite.Require().NoError(err)
- }, true,
- },
- {
- "bad connection (uses channel data)", types.CONNECTION, func() {
- counterparty := channeltypes.NewCounterparty(testPortID, testChannelID)
- ch := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, counterparty, []string{testConnectionID}, "1.0.0")
- path := solomachine.GetChannelStatePath("portID", "channelID")
-
- data, err = types.ChannelStateDataBytes(cdc, path, ch)
- suite.Require().NoError(err)
- }, false,
- },
- {
- "channel", types.CHANNEL, func() {
- counterparty := channeltypes.NewCounterparty(testPortID, testChannelID)
- ch := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, counterparty, []string{testConnectionID}, "1.0.0")
- path := solomachine.GetChannelStatePath("portID", "channelID")
-
- data, err = types.ChannelStateDataBytes(cdc, path, ch)
- suite.Require().NoError(err)
- }, true,
- },
- {
- "bad channel (uses connection data)", types.CHANNEL, func() {
- counterparty := connectiontypes.NewCounterparty("clientB", testConnectionID, *prefix)
- conn := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "clientA", counterparty, connectiontypes.ExportedVersionsToProto(connectiontypes.GetCompatibleVersions()), 0)
- path := solomachine.GetConnectionStatePath("connectionID")
-
- data, err = types.ConnectionStateDataBytes(cdc, path, conn)
- suite.Require().NoError(err)
- }, false,
- },
- {
- "packet commitment", types.PACKETCOMMITMENT, func() {
- commitment := []byte("packet commitment")
- path := solomachine.GetPacketCommitmentPath("portID", "channelID")
-
- data, err = types.PacketCommitmentDataBytes(cdc, path, commitment)
- suite.Require().NoError(err)
- }, true,
- },
- {
- "bad packet commitment (uses next seq recv)", types.PACKETCOMMITMENT, func() {
- path := solomachine.GetNextSequenceRecvPath("portID", "channelID")
-
- data, err = types.NextSequenceRecvDataBytes(cdc, path, 10)
- suite.Require().NoError(err)
- }, false,
- },
- {
- "packet acknowledgement", types.PACKETACKNOWLEDGEMENT, func() {
- commitment := []byte("packet acknowledgement")
- path := solomachine.GetPacketAcknowledgementPath("portID", "channelID")
-
- data, err = types.PacketAcknowledgementDataBytes(cdc, path, commitment)
- suite.Require().NoError(err)
- }, true,
- },
- {
- "bad packet acknowledgement (uses next sequence recv)", types.PACKETACKNOWLEDGEMENT, func() {
- path := solomachine.GetNextSequenceRecvPath("portID", "channelID")
-
- data, err = types.NextSequenceRecvDataBytes(cdc, path, 10)
- suite.Require().NoError(err)
- }, false,
- },
- {
- "packet acknowledgement absence", types.PACKETRECEIPTABSENCE, func() {
- path := solomachine.GetPacketReceiptPath("portID", "channelID")
-
- data, err = types.PacketReceiptAbsenceDataBytes(cdc, path)
- suite.Require().NoError(err)
- }, true,
- },
- {
- "next sequence recv", types.NEXTSEQUENCERECV, func() {
- path := solomachine.GetNextSequenceRecvPath("portID", "channelID")
-
- data, err = types.NextSequenceRecvDataBytes(cdc, path, 10)
- suite.Require().NoError(err)
- }, true,
- },
- {
- "bad next sequence recv (uses packet commitment)", types.NEXTSEQUENCERECV, func() {
- commitment := []byte("packet commitment")
- path := solomachine.GetPacketCommitmentPath("portID", "channelID")
-
- data, err = types.PacketCommitmentDataBytes(cdc, path, commitment)
- suite.Require().NoError(err)
- }, false,
- },
- }
-
- for _, tc := range cases {
- tc := tc
-
- suite.Run(tc.name, func() {
- tc.malleate()
-
- data, err := types.UnmarshalDataByType(cdc, tc.dataType, data)
-
- if tc.expPass {
- suite.Require().NoError(err)
- suite.Require().NotNil(data)
- } else {
- suite.Require().Error(err)
- suite.Require().Nil(data)
- }
- })
- }
- }
-}
diff --git a/modules/light-clients/06-solomachine/types/misbehaviour_handle.go b/modules/light-clients/06-solomachine/types/misbehaviour_handle.go
deleted file mode 100644
index 805847e9b21..00000000000
--- a/modules/light-clients/06-solomachine/types/misbehaviour_handle.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package types
-
-import (
- "github.com/cosmos/cosmos-sdk/codec"
- sdk "github.com/cosmos/cosmos-sdk/types"
- sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
-
- clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
-)
-
-// CheckMisbehaviourAndUpdateState determines whether or not the currently registered
-// public key signed over two different messages with the same sequence. If this is true
-// the client state is updated to a frozen status.
-// NOTE: Misbehaviour is not tracked for previous public keys, a solo machine may update to
-// a new public key before the misbehaviour is processed. Therefore, misbehaviour is data
-// order processing dependent.
-func (cs ClientState) CheckMisbehaviourAndUpdateState(
- ctx sdk.Context,
- cdc codec.BinaryCodec,
- clientStore sdk.KVStore,
- misbehaviour exported.Misbehaviour,
-) (exported.ClientState, error) {
- soloMisbehaviour, ok := misbehaviour.(*Misbehaviour)
- if !ok {
- return nil, sdkerrors.Wrapf(
- clienttypes.ErrInvalidClientType,
- "misbehaviour type %T, expected %T", misbehaviour, &Misbehaviour{},
- )
- }
-
- // NOTE: a check that the misbehaviour message data are not equal is done by
- // misbehaviour.ValidateBasic which is called by the 02-client keeper.
-
- // verify first signature
- if err := verifySignatureAndData(cdc, cs, soloMisbehaviour, soloMisbehaviour.SignatureOne); err != nil {
- return nil, sdkerrors.Wrap(err, "failed to verify signature one")
- }
-
- // verify second signature
- if err := verifySignatureAndData(cdc, cs, soloMisbehaviour, soloMisbehaviour.SignatureTwo); err != nil {
- return nil, sdkerrors.Wrap(err, "failed to verify signature two")
- }
-
- cs.IsFrozen = true
- return &cs, nil
-}
-
-// verifySignatureAndData verifies that the currently registered public key has signed
-// over the provided data and that the data is valid. The data is valid if it can be
-// unmarshaled into the specified data type.
-func verifySignatureAndData(cdc codec.BinaryCodec, clientState ClientState, misbehaviour *Misbehaviour, sigAndData *SignatureAndData) error {
- // do not check misbehaviour timestamp since we want to allow processing of past misbehaviour
-
- // ensure data can be unmarshaled to the specified data type
- if _, err := UnmarshalDataByType(cdc, sigAndData.DataType, sigAndData.Data); err != nil {
- return err
- }
-
- data, err := MisbehaviourSignBytes(
- cdc,
- misbehaviour.Sequence, sigAndData.Timestamp,
- clientState.ConsensusState.Diversifier,
- sigAndData.DataType,
- sigAndData.Data,
- )
- if err != nil {
- return err
- }
-
- sigData, err := UnmarshalSignatureData(cdc, sigAndData.Signature)
- if err != nil {
- return err
- }
-
- publicKey, err := clientState.ConsensusState.GetPubKey()
- if err != nil {
- return err
- }
-
- if err := VerifySignature(publicKey, data, sigData); err != nil {
- return err
- }
-
- return nil
-}
diff --git a/modules/light-clients/06-solomachine/types/misbehaviour_handle_test.go b/modules/light-clients/06-solomachine/types/misbehaviour_handle_test.go
deleted file mode 100644
index 945aff3c481..00000000000
--- a/modules/light-clients/06-solomachine/types/misbehaviour_handle_test.go
+++ /dev/null
@@ -1,264 +0,0 @@
-package types_test
-
-import (
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
- ibctesting "github.com/cosmos/ibc-go/v5/testing"
-)
-
-func (suite *SoloMachineTestSuite) TestCheckMisbehaviourAndUpdateState() {
- var (
- clientState exported.ClientState
- misbehaviour exported.Misbehaviour
- )
-
- // test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
-
- testCases := []struct {
- name string
- setup func()
- expPass bool
- }{
- {
- "valid misbehaviour",
- func() {
- clientState = solomachine.ClientState()
- misbehaviour = solomachine.CreateMisbehaviour()
- },
- true,
- },
- {
- "old misbehaviour is successful (timestamp is less than current consensus state)",
- func() {
- clientState = solomachine.ClientState()
- solomachine.Time = solomachine.Time - 5
- misbehaviour = solomachine.CreateMisbehaviour()
- }, true,
- },
- {
- "wrong client state type",
- func() {
- clientState = &ibctmtypes.ClientState{}
- misbehaviour = solomachine.CreateMisbehaviour()
- },
- false,
- },
- {
- "invalid misbehaviour type",
- func() {
- clientState = solomachine.ClientState()
- misbehaviour = &ibctmtypes.Misbehaviour{}
- },
- false,
- },
- {
- "invalid SignatureOne SignatureData",
- func() {
- clientState = solomachine.ClientState()
- m := solomachine.CreateMisbehaviour()
-
- m.SignatureOne.Signature = suite.GetInvalidProof()
- misbehaviour = m
- }, false,
- },
- {
- "invalid SignatureTwo SignatureData",
- func() {
- clientState = solomachine.ClientState()
- m := solomachine.CreateMisbehaviour()
-
- m.SignatureTwo.Signature = suite.GetInvalidProof()
- misbehaviour = m
- }, false,
- },
- {
- "invalid SignatureOne timestamp",
- func() {
- clientState = solomachine.ClientState()
- m := solomachine.CreateMisbehaviour()
-
- m.SignatureOne.Timestamp = 1000000000000
- misbehaviour = m
- }, false,
- },
- {
- "invalid SignatureTwo timestamp",
- func() {
- clientState = solomachine.ClientState()
- m := solomachine.CreateMisbehaviour()
-
- m.SignatureTwo.Timestamp = 1000000000000
- misbehaviour = m
- }, false,
- },
- {
- "invalid first signature data",
- func() {
- clientState = solomachine.ClientState()
-
- // store in temp before assigning to interface type
- m := solomachine.CreateMisbehaviour()
-
- msg := []byte("DATA ONE")
- signBytes := &types.SignBytes{
- Sequence: solomachine.Sequence + 1,
- Timestamp: solomachine.Time,
- Diversifier: solomachine.Diversifier,
- DataType: types.CLIENT,
- Data: msg,
- }
-
- data, err := suite.chainA.Codec.Marshal(signBytes)
- suite.Require().NoError(err)
-
- sig := solomachine.GenerateSignature(data)
-
- m.SignatureOne.Signature = sig
- m.SignatureOne.Data = msg
- misbehaviour = m
- },
- false,
- },
- {
- "invalid second signature data",
- func() {
- clientState = solomachine.ClientState()
-
- // store in temp before assigning to interface type
- m := solomachine.CreateMisbehaviour()
-
- msg := []byte("DATA TWO")
- signBytes := &types.SignBytes{
- Sequence: solomachine.Sequence + 1,
- Timestamp: solomachine.Time,
- Diversifier: solomachine.Diversifier,
- DataType: types.CLIENT,
- Data: msg,
- }
-
- data, err := suite.chainA.Codec.Marshal(signBytes)
- suite.Require().NoError(err)
-
- sig := solomachine.GenerateSignature(data)
-
- m.SignatureTwo.Signature = sig
- m.SignatureTwo.Data = msg
- misbehaviour = m
- },
- false,
- },
- {
- "wrong pubkey generates first signature",
- func() {
- clientState = solomachine.ClientState()
- badMisbehaviour := solomachine.CreateMisbehaviour()
-
- // update public key to a new one
- solomachine.CreateHeader()
- m := solomachine.CreateMisbehaviour()
-
- // set SignatureOne to use the wrong signature
- m.SignatureOne = badMisbehaviour.SignatureOne
- misbehaviour = m
- }, false,
- },
- {
- "wrong pubkey generates second signature",
- func() {
- clientState = solomachine.ClientState()
- badMisbehaviour := solomachine.CreateMisbehaviour()
-
- // update public key to a new one
- solomachine.CreateHeader()
- m := solomachine.CreateMisbehaviour()
-
- // set SignatureTwo to use the wrong signature
- m.SignatureTwo = badMisbehaviour.SignatureTwo
- misbehaviour = m
- }, false,
- },
-
- {
- "signatures sign over different sequence",
- func() {
- clientState = solomachine.ClientState()
-
- // store in temp before assigning to interface type
- m := solomachine.CreateMisbehaviour()
-
- // Signature One
- msg := []byte("DATA ONE")
- // sequence used is plus 1
- signBytes := &types.SignBytes{
- Sequence: solomachine.Sequence + 1,
- Timestamp: solomachine.Time,
- Diversifier: solomachine.Diversifier,
- DataType: types.CLIENT,
- Data: msg,
- }
-
- data, err := suite.chainA.Codec.Marshal(signBytes)
- suite.Require().NoError(err)
-
- sig := solomachine.GenerateSignature(data)
-
- m.SignatureOne.Signature = sig
- m.SignatureOne.Data = msg
-
- // Signature Two
- msg = []byte("DATA TWO")
- // sequence used is minus 1
-
- signBytes = &types.SignBytes{
- Sequence: solomachine.Sequence - 1,
- Timestamp: solomachine.Time,
- Diversifier: solomachine.Diversifier,
- DataType: types.CLIENT,
- Data: msg,
- }
- data, err = suite.chainA.Codec.Marshal(signBytes)
- suite.Require().NoError(err)
-
- sig = solomachine.GenerateSignature(data)
-
- m.SignatureTwo.Signature = sig
- m.SignatureTwo.Data = msg
-
- misbehaviour = m
- },
- false,
- },
- {
- "consensus state pubkey is nil",
- func() {
- cs := solomachine.ClientState()
- cs.ConsensusState.PublicKey = nil
- clientState = cs
- misbehaviour = solomachine.CreateMisbehaviour()
- },
- false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- // setup test
- tc.setup()
-
- clientState, err := clientState.CheckMisbehaviourAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), suite.store, misbehaviour)
-
- if tc.expPass {
- suite.Require().NoError(err)
- suite.Require().True(clientState.(*types.ClientState).IsFrozen, "client not frozen")
- } else {
- suite.Require().Error(err)
- suite.Require().Nil(clientState)
- }
- })
- }
- }
-}
diff --git a/modules/light-clients/06-solomachine/types/proof.go b/modules/light-clients/06-solomachine/types/proof.go
deleted file mode 100644
index 35ce4d9cd54..00000000000
--- a/modules/light-clients/06-solomachine/types/proof.go
+++ /dev/null
@@ -1,477 +0,0 @@
-package types
-
-import (
- "github.com/cosmos/cosmos-sdk/codec"
- cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
- "github.com/cosmos/cosmos-sdk/crypto/types/multisig"
- sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
- "github.com/cosmos/cosmos-sdk/types/tx/signing"
-
- clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- connectiontypes "github.com/cosmos/ibc-go/v5/modules/core/03-connection/types"
- channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
- commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
-)
-
-// VerifySignature verifies if the the provided public key generated the signature
-// over the given data. Single and Multi signature public keys are supported.
-// The signature data type must correspond to the public key type. An error is
-// returned if signature verification fails or an invalid SignatureData type is
-// provided.
-func VerifySignature(pubKey cryptotypes.PubKey, signBytes []byte, sigData signing.SignatureData) error {
- switch pubKey := pubKey.(type) {
- case multisig.PubKey:
- data, ok := sigData.(*signing.MultiSignatureData)
- if !ok {
- return sdkerrors.Wrapf(ErrSignatureVerificationFailed, "invalid signature data type, expected %T, got %T", (*signing.MultiSignatureData)(nil), data)
- }
-
- // The function supplied fulfills the VerifyMultisignature interface. No special
- // adjustments need to be made to the sign bytes based on the sign mode.
- if err := pubKey.VerifyMultisignature(func(signing.SignMode) ([]byte, error) {
- return signBytes, nil
- }, data); err != nil {
- return err
- }
-
- default:
- data, ok := sigData.(*signing.SingleSignatureData)
- if !ok {
- return sdkerrors.Wrapf(ErrSignatureVerificationFailed, "invalid signature data type, expected %T, got %T", (*signing.SingleSignatureData)(nil), data)
- }
-
- if !pubKey.VerifySignature(signBytes, data.Signature) {
- return ErrSignatureVerificationFailed
- }
- }
-
- return nil
-}
-
-// MisbehaviourSignBytes returns the sign bytes for verification of misbehaviour.
-func MisbehaviourSignBytes(
- cdc codec.BinaryCodec,
- sequence, timestamp uint64,
- diversifier string,
- dataType DataType,
- data []byte,
-) ([]byte, error) {
- signBytes := &SignBytes{
- Sequence: sequence,
- Timestamp: timestamp,
- Diversifier: diversifier,
- DataType: dataType,
- Data: data,
- }
-
- return cdc.Marshal(signBytes)
-}
-
-// HeaderSignBytes returns the sign bytes for verification of misbehaviour.
-func HeaderSignBytes(
- cdc codec.BinaryCodec,
- header *Header,
-) ([]byte, error) {
- data := &HeaderData{
- NewPubKey: header.NewPublicKey,
- NewDiversifier: header.NewDiversifier,
- }
-
- dataBz, err := cdc.Marshal(data)
- if err != nil {
- return nil, err
- }
-
- signBytes := &SignBytes{
- Sequence: header.Sequence,
- Timestamp: header.Timestamp,
- Diversifier: header.NewDiversifier,
- DataType: HEADER,
- Data: dataBz,
- }
-
- return cdc.Marshal(signBytes)
-}
-
-// ClientStateSignBytes returns the sign bytes for verification of the
-// client state.
-func ClientStateSignBytes(
- cdc codec.BinaryCodec,
- sequence, timestamp uint64,
- diversifier string,
- path commitmenttypes.MerklePath,
- clientState exported.ClientState,
-) ([]byte, error) {
- dataBz, err := ClientStateDataBytes(cdc, path, clientState)
- if err != nil {
- return nil, err
- }
-
- signBytes := &SignBytes{
- Sequence: sequence,
- Timestamp: timestamp,
- Diversifier: diversifier,
- DataType: CLIENT,
- Data: dataBz,
- }
-
- return cdc.Marshal(signBytes)
-}
-
-// ClientStateDataBytes returns the client state data bytes used in constructing
-// SignBytes.
-func ClientStateDataBytes(
- cdc codec.BinaryCodec,
- path commitmenttypes.MerklePath, //nolint:interfacer
- clientState exported.ClientState,
-) ([]byte, error) {
- any, err := clienttypes.PackClientState(clientState)
- if err != nil {
- return nil, err
- }
-
- data := &ClientStateData{
- Path: []byte(path.String()),
- ClientState: any,
- }
-
- dataBz, err := cdc.Marshal(data)
- if err != nil {
- return nil, err
- }
-
- return dataBz, nil
-}
-
-// ConsensusStateSignBytes returns the sign bytes for verification of the
-// consensus state.
-func ConsensusStateSignBytes(
- cdc codec.BinaryCodec,
- sequence, timestamp uint64,
- diversifier string,
- path commitmenttypes.MerklePath,
- consensusState exported.ConsensusState,
-) ([]byte, error) {
- dataBz, err := ConsensusStateDataBytes(cdc, path, consensusState)
- if err != nil {
- return nil, err
- }
-
- signBytes := &SignBytes{
- Sequence: sequence,
- Timestamp: timestamp,
- Diversifier: diversifier,
- DataType: CONSENSUS,
- Data: dataBz,
- }
-
- return cdc.Marshal(signBytes)
-}
-
-// ConsensusStateDataBytes returns the consensus state data bytes used in constructing
-// SignBytes.
-func ConsensusStateDataBytes(
- cdc codec.BinaryCodec,
- path commitmenttypes.MerklePath, //nolint:interfacer
- consensusState exported.ConsensusState,
-) ([]byte, error) {
- any, err := clienttypes.PackConsensusState(consensusState)
- if err != nil {
- return nil, err
- }
-
- data := &ConsensusStateData{
- Path: []byte(path.String()),
- ConsensusState: any,
- }
-
- dataBz, err := cdc.Marshal(data)
- if err != nil {
- return nil, err
- }
-
- return dataBz, nil
-}
-
-// ConnectionStateSignBytes returns the sign bytes for verification of the
-// connection state.
-func ConnectionStateSignBytes(
- cdc codec.BinaryCodec,
- sequence, timestamp uint64,
- diversifier string,
- path commitmenttypes.MerklePath,
- connectionEnd exported.ConnectionI,
-) ([]byte, error) {
- dataBz, err := ConnectionStateDataBytes(cdc, path, connectionEnd)
- if err != nil {
- return nil, err
- }
-
- signBytes := &SignBytes{
- Sequence: sequence,
- Timestamp: timestamp,
- Diversifier: diversifier,
- DataType: CONNECTION,
- Data: dataBz,
- }
-
- return cdc.Marshal(signBytes)
-}
-
-// ConnectionStateDataBytes returns the connection state data bytes used in constructing
-// SignBytes.
-func ConnectionStateDataBytes(
- cdc codec.BinaryCodec,
- path commitmenttypes.MerklePath, //nolint:interfacer
- connectionEnd exported.ConnectionI,
-) ([]byte, error) {
- connection, ok := connectionEnd.(connectiontypes.ConnectionEnd)
- if !ok {
- return nil, sdkerrors.Wrapf(
- connectiontypes.ErrInvalidConnection,
- "expected type %T, got %T", connectiontypes.ConnectionEnd{}, connectionEnd,
- )
- }
-
- data := &ConnectionStateData{
- Path: []byte(path.String()),
- Connection: &connection,
- }
-
- dataBz, err := cdc.Marshal(data)
- if err != nil {
- return nil, err
- }
-
- return dataBz, nil
-}
-
-// ChannelStateSignBytes returns the sign bytes for verification of the
-// channel state.
-func ChannelStateSignBytes(
- cdc codec.BinaryCodec,
- sequence, timestamp uint64,
- diversifier string,
- path commitmenttypes.MerklePath,
- channelEnd exported.ChannelI,
-) ([]byte, error) {
- dataBz, err := ChannelStateDataBytes(cdc, path, channelEnd)
- if err != nil {
- return nil, err
- }
-
- signBytes := &SignBytes{
- Sequence: sequence,
- Timestamp: timestamp,
- Diversifier: diversifier,
- DataType: CHANNEL,
- Data: dataBz,
- }
-
- return cdc.Marshal(signBytes)
-}
-
-// ChannelStateDataBytes returns the channel state data bytes used in constructing
-// SignBytes.
-func ChannelStateDataBytes(
- cdc codec.BinaryCodec,
- path commitmenttypes.MerklePath, //nolint:interfacer
- channelEnd exported.ChannelI,
-) ([]byte, error) {
- channel, ok := channelEnd.(channeltypes.Channel)
- if !ok {
- return nil, sdkerrors.Wrapf(
- channeltypes.ErrInvalidChannel,
- "expected channel type %T, got %T", channeltypes.Channel{}, channelEnd)
- }
-
- data := &ChannelStateData{
- Path: []byte(path.String()),
- Channel: &channel,
- }
-
- dataBz, err := cdc.Marshal(data)
- if err != nil {
- return nil, err
- }
-
- return dataBz, nil
-}
-
-// PacketCommitmentSignBytes returns the sign bytes for verification of the
-// packet commitment.
-func PacketCommitmentSignBytes(
- cdc codec.BinaryCodec,
- sequence, timestamp uint64,
- diversifier string,
- path commitmenttypes.MerklePath,
- commitmentBytes []byte,
-) ([]byte, error) {
- dataBz, err := PacketCommitmentDataBytes(cdc, path, commitmentBytes)
- if err != nil {
- return nil, err
- }
-
- signBytes := &SignBytes{
- Sequence: sequence,
- Timestamp: timestamp,
- Diversifier: diversifier,
- DataType: PACKETCOMMITMENT,
- Data: dataBz,
- }
-
- return cdc.Marshal(signBytes)
-}
-
-// PacketCommitmentDataBytes returns the packet commitment data bytes used in constructing
-// SignBytes.
-func PacketCommitmentDataBytes(
- cdc codec.BinaryCodec,
- path commitmenttypes.MerklePath, //nolint:interfacer
- commitmentBytes []byte,
-) ([]byte, error) {
- data := &PacketCommitmentData{
- Path: []byte(path.String()),
- Commitment: commitmentBytes,
- }
-
- dataBz, err := cdc.Marshal(data)
- if err != nil {
- return nil, err
- }
-
- return dataBz, nil
-}
-
-// PacketAcknowledgementSignBytes returns the sign bytes for verification of
-// the acknowledgement.
-func PacketAcknowledgementSignBytes(
- cdc codec.BinaryCodec,
- sequence, timestamp uint64,
- diversifier string,
- path commitmenttypes.MerklePath,
- acknowledgement []byte,
-) ([]byte, error) {
- dataBz, err := PacketAcknowledgementDataBytes(cdc, path, acknowledgement)
- if err != nil {
- return nil, err
- }
-
- signBytes := &SignBytes{
- Sequence: sequence,
- Timestamp: timestamp,
- Diversifier: diversifier,
- DataType: PACKETACKNOWLEDGEMENT,
- Data: dataBz,
- }
-
- return cdc.Marshal(signBytes)
-}
-
-// PacketAcknowledgementDataBytes returns the packet acknowledgement data bytes used in constructing
-// SignBytes.
-func PacketAcknowledgementDataBytes(
- cdc codec.BinaryCodec,
- path commitmenttypes.MerklePath, //nolint:interfacer
- acknowledgement []byte,
-) ([]byte, error) {
- data := &PacketAcknowledgementData{
- Path: []byte(path.String()),
- Acknowledgement: acknowledgement,
- }
-
- dataBz, err := cdc.Marshal(data)
- if err != nil {
- return nil, err
- }
-
- return dataBz, nil
-}
-
-// PacketReceiptAbsenceSignBytes returns the sign bytes for verification
-// of the absence of an receipt.
-func PacketReceiptAbsenceSignBytes(
- cdc codec.BinaryCodec,
- sequence, timestamp uint64,
- diversifier string,
- path commitmenttypes.MerklePath,
-) ([]byte, error) {
- dataBz, err := PacketReceiptAbsenceDataBytes(cdc, path)
- if err != nil {
- return nil, err
- }
-
- signBytes := &SignBytes{
- Sequence: sequence,
- Timestamp: timestamp,
- Diversifier: diversifier,
- DataType: PACKETRECEIPTABSENCE,
- Data: dataBz,
- }
-
- return cdc.Marshal(signBytes)
-}
-
-// PacketReceiptAbsenceDataBytes returns the packet receipt absence data bytes
-// used in constructing SignBytes.
-func PacketReceiptAbsenceDataBytes(
- cdc codec.BinaryCodec,
- path commitmenttypes.MerklePath, //nolint:interfacer
-) ([]byte, error) {
- data := &PacketReceiptAbsenceData{
- Path: []byte(path.String()),
- }
-
- dataBz, err := cdc.Marshal(data)
- if err != nil {
- return nil, err
- }
-
- return dataBz, nil
-}
-
-// NextSequenceRecvSignBytes returns the sign bytes for verification of the next
-// sequence to be received.
-func NextSequenceRecvSignBytes(
- cdc codec.BinaryCodec,
- sequence, timestamp uint64,
- diversifier string,
- path commitmenttypes.MerklePath,
- nextSequenceRecv uint64,
-) ([]byte, error) {
- dataBz, err := NextSequenceRecvDataBytes(cdc, path, nextSequenceRecv)
- if err != nil {
- return nil, err
- }
-
- signBytes := &SignBytes{
- Sequence: sequence,
- Timestamp: timestamp,
- Diversifier: diversifier,
- DataType: NEXTSEQUENCERECV,
- Data: dataBz,
- }
-
- return cdc.Marshal(signBytes)
-}
-
-// NextSequenceRecvDataBytes returns the next sequence recv data bytes used in constructing
-// SignBytes.
-func NextSequenceRecvDataBytes(
- cdc codec.BinaryCodec,
- path commitmenttypes.MerklePath, //nolint:interfacer
- nextSequenceRecv uint64,
-) ([]byte, error) {
- data := &NextSequenceRecvData{
- Path: []byte(path.String()),
- NextSeqRecv: nextSequenceRecv,
- }
-
- dataBz, err := cdc.Marshal(data)
- if err != nil {
- return nil, err
- }
-
- return dataBz, nil
-}
diff --git a/modules/light-clients/06-solomachine/types/proof_test.go b/modules/light-clients/06-solomachine/types/proof_test.go
deleted file mode 100644
index 6a79998ab33..00000000000
--- a/modules/light-clients/06-solomachine/types/proof_test.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package types_test
-
-import (
- cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
- "github.com/cosmos/cosmos-sdk/types/tx/signing"
-
- "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
- solomachinetypes "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
- ibctesting "github.com/cosmos/ibc-go/v5/testing"
-)
-
-func (suite *SoloMachineTestSuite) TestVerifySignature() {
- cdc := suite.chainA.App.AppCodec()
- signBytes := []byte("sign bytes")
-
- singleSignature := suite.solomachine.GenerateSignature(signBytes)
- singleSigData, err := solomachinetypes.UnmarshalSignatureData(cdc, singleSignature)
- suite.Require().NoError(err)
-
- multiSignature := suite.solomachineMulti.GenerateSignature(signBytes)
- multiSigData, err := solomachinetypes.UnmarshalSignatureData(cdc, multiSignature)
- suite.Require().NoError(err)
-
- testCases := []struct {
- name string
- publicKey cryptotypes.PubKey
- sigData signing.SignatureData
- expPass bool
- }{
- {
- "single signature with regular public key",
- suite.solomachine.PublicKey,
- singleSigData,
- true,
- },
- {
- "multi signature with multisig public key",
- suite.solomachineMulti.PublicKey,
- multiSigData,
- true,
- },
- {
- "single signature with multisig public key",
- suite.solomachineMulti.PublicKey,
- singleSigData,
- false,
- },
- {
- "multi signature with regular public key",
- suite.solomachine.PublicKey,
- multiSigData,
- false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- err := solomachinetypes.VerifySignature(tc.publicKey, signBytes, tc.sigData)
-
- if tc.expPass {
- suite.Require().NoError(err)
- } else {
- suite.Require().Error(err)
- }
- })
- }
-}
-
-func (suite *SoloMachineTestSuite) TestClientStateSignBytes() {
- cdc := suite.chainA.App.AppCodec()
-
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
- // success
- path := solomachine.GetClientStatePath(counterpartyClientIdentifier)
- bz, err := types.ClientStateSignBytes(cdc, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, solomachine.ClientState())
- suite.Require().NoError(err)
- suite.Require().NotNil(bz)
-
- // nil client state
- bz, err = types.ClientStateSignBytes(cdc, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, nil)
- suite.Require().Error(err)
- suite.Require().Nil(bz)
- }
-}
-
-func (suite *SoloMachineTestSuite) TestConsensusStateSignBytes() {
- cdc := suite.chainA.App.AppCodec()
-
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
- // success
- path := solomachine.GetConsensusStatePath(counterpartyClientIdentifier, consensusHeight)
- bz, err := types.ConsensusStateSignBytes(cdc, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, solomachine.ConsensusState())
- suite.Require().NoError(err)
- suite.Require().NotNil(bz)
-
- // nil consensus state
- bz, err = types.ConsensusStateSignBytes(cdc, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, nil)
- suite.Require().Error(err)
- suite.Require().Nil(bz)
- }
-}
diff --git a/modules/light-clients/06-solomachine/types/update.go b/modules/light-clients/06-solomachine/types/update.go
deleted file mode 100644
index 38db4a6b9cd..00000000000
--- a/modules/light-clients/06-solomachine/types/update.go
+++ /dev/null
@@ -1,90 +0,0 @@
-package types
-
-import (
- "github.com/cosmos/cosmos-sdk/codec"
- sdk "github.com/cosmos/cosmos-sdk/types"
- sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
-
- clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
-)
-
-// CheckHeaderAndUpdateState checks if the provided header is valid and updates
-// the consensus state if appropriate. It returns an error if:
-// - the header provided is not parseable to a solo machine header
-// - the header sequence does not match the current sequence
-// - the header timestamp is less than the consensus state timestamp
-// - the currently registered public key did not provide the update signature
-func (cs ClientState) CheckHeaderAndUpdateState(
- ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore,
- header exported.Header,
-) (exported.ClientState, exported.ConsensusState, error) {
- smHeader, ok := header.(*Header)
- if !ok {
- return nil, nil, sdkerrors.Wrapf(
- clienttypes.ErrInvalidHeader, "header type %T, expected %T", header, &Header{},
- )
- }
-
- if err := checkHeader(cdc, &cs, smHeader); err != nil {
- return nil, nil, err
- }
-
- clientState, consensusState := update(&cs, smHeader)
- return clientState, consensusState, nil
-}
-
-// checkHeader checks if the Solo Machine update signature is valid.
-func checkHeader(cdc codec.BinaryCodec, clientState *ClientState, header *Header) error {
- // assert update sequence is current sequence
- if header.Sequence != clientState.Sequence {
- return sdkerrors.Wrapf(
- clienttypes.ErrInvalidHeader,
- "header sequence does not match the client state sequence (%d != %d)", header.Sequence, clientState.Sequence,
- )
- }
-
- // assert update timestamp is not less than current consensus state timestamp
- if header.Timestamp < clientState.ConsensusState.Timestamp {
- return sdkerrors.Wrapf(
- clienttypes.ErrInvalidHeader,
- "header timestamp is less than to the consensus state timestamp (%d < %d)", header.Timestamp, clientState.ConsensusState.Timestamp,
- )
- }
-
- // assert currently registered public key signed over the new public key with correct sequence
- data, err := HeaderSignBytes(cdc, header)
- if err != nil {
- return err
- }
-
- sigData, err := UnmarshalSignatureData(cdc, header.Signature)
- if err != nil {
- return err
- }
-
- publicKey, err := clientState.ConsensusState.GetPubKey()
- if err != nil {
- return err
- }
-
- if err := VerifySignature(publicKey, data, sigData); err != nil {
- return sdkerrors.Wrap(ErrInvalidHeader, err.Error())
- }
-
- return nil
-}
-
-// update the consensus state to the new public key and an incremented sequence
-func update(clientState *ClientState, header *Header) (*ClientState, *ConsensusState) {
- consensusState := &ConsensusState{
- PublicKey: header.NewPublicKey,
- Diversifier: header.NewDiversifier,
- Timestamp: header.Timestamp,
- }
-
- // increment sequence number
- clientState.Sequence++
- clientState.ConsensusState = consensusState
- return clientState, consensusState
-}
diff --git a/modules/light-clients/06-solomachine/types/update_test.go b/modules/light-clients/06-solomachine/types/update_test.go
deleted file mode 100644
index f1bcaac9d98..00000000000
--- a/modules/light-clients/06-solomachine/types/update_test.go
+++ /dev/null
@@ -1,181 +0,0 @@
-package types_test
-
-import (
- codectypes "github.com/cosmos/cosmos-sdk/codec/types"
- sdk "github.com/cosmos/cosmos-sdk/types"
-
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
- ibctesting "github.com/cosmos/ibc-go/v5/testing"
-)
-
-func (suite *SoloMachineTestSuite) TestCheckHeaderAndUpdateState() {
- var (
- clientState exported.ClientState
- header exported.Header
- )
-
- // test singlesig and multisig public keys
- for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
-
- testCases := []struct {
- name string
- setup func()
- expPass bool
- }{
- {
- "successful update",
- func() {
- clientState = solomachine.ClientState()
- header = solomachine.CreateHeader()
- },
- true,
- },
- {
- "wrong client state type",
- func() {
- clientState = &ibctmtypes.ClientState{}
- header = solomachine.CreateHeader()
- },
- false,
- },
- {
- "invalid header type",
- func() {
- clientState = solomachine.ClientState()
- header = &ibctmtypes.Header{}
- },
- false,
- },
- {
- "wrong sequence in header",
- func() {
- clientState = solomachine.ClientState()
- // store in temp before assigning to interface type
- h := solomachine.CreateHeader()
- h.Sequence++
- header = h
- },
- false,
- },
- {
- "invalid header Signature",
- func() {
- clientState = solomachine.ClientState()
- h := solomachine.CreateHeader()
- h.Signature = suite.GetInvalidProof()
- header = h
- }, false,
- },
- {
- "invalid timestamp in header",
- func() {
- clientState = solomachine.ClientState()
- h := solomachine.CreateHeader()
- h.Timestamp--
- header = h
- }, false,
- },
- {
- "signature uses wrong sequence",
- func() {
- clientState = solomachine.ClientState()
- solomachine.Sequence++
- header = solomachine.CreateHeader()
- },
- false,
- },
- {
- "signature uses new pubkey to sign",
- func() {
- // store in temp before assinging to interface type
- cs := solomachine.ClientState()
- h := solomachine.CreateHeader()
-
- publicKey, err := codectypes.NewAnyWithValue(solomachine.PublicKey)
- suite.NoError(err)
-
- data := &types.HeaderData{
- NewPubKey: publicKey,
- NewDiversifier: h.NewDiversifier,
- }
-
- dataBz, err := suite.chainA.Codec.Marshal(data)
- suite.Require().NoError(err)
-
- // generate invalid signature
- signBytes := &types.SignBytes{
- Sequence: cs.Sequence,
- Timestamp: solomachine.Time,
- Diversifier: solomachine.Diversifier,
- DataType: types.CLIENT,
- Data: dataBz,
- }
-
- signBz, err := suite.chainA.Codec.Marshal(signBytes)
- suite.Require().NoError(err)
-
- sig := solomachine.GenerateSignature(signBz)
- suite.Require().NoError(err)
- h.Signature = sig
-
- clientState = cs
- header = h
- },
- false,
- },
- {
- "signature signs over old pubkey",
- func() {
- // store in temp before assinging to interface type
- cs := solomachine.ClientState()
- oldPubKey := solomachine.PublicKey
- h := solomachine.CreateHeader()
-
- // generate invalid signature
- data := append(sdk.Uint64ToBigEndian(cs.Sequence), oldPubKey.Bytes()...)
- sig := solomachine.GenerateSignature(data)
- h.Signature = sig
-
- clientState = cs
- header = h
- },
- false,
- },
- {
- "consensus state public key is nil",
- func() {
- cs := solomachine.ClientState()
- cs.ConsensusState.PublicKey = nil
- clientState = cs
- header = solomachine.CreateHeader()
- },
- false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- // setup test
- tc.setup()
-
- clientState, consensusState, err := clientState.CheckHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.Codec, suite.store, header)
-
- if tc.expPass {
- suite.Require().NoError(err)
- suite.Require().Equal(header.(*types.Header).NewPublicKey, clientState.(*types.ClientState).ConsensusState.PublicKey)
- suite.Require().Equal(false, clientState.(*types.ClientState).IsFrozen)
- suite.Require().Equal(header.(*types.Header).Sequence+1, clientState.(*types.ClientState).Sequence)
- suite.Require().Equal(consensusState, clientState.(*types.ClientState).ConsensusState)
- } else {
- suite.Require().Error(err)
- suite.Require().Nil(clientState)
- suite.Require().Nil(consensusState)
- }
- })
- }
- }
-}
diff --git a/modules/light-clients/06-solomachine/update.go b/modules/light-clients/06-solomachine/update.go
new file mode 100644
index 00000000000..4594363a5af
--- /dev/null
+++ b/modules/light-clients/06-solomachine/update.go
@@ -0,0 +1,140 @@
+package solomachine
+
+import (
+ "fmt"
+
+ "github.com/cosmos/cosmos-sdk/codec"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
+
+ clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
+ "github.com/cosmos/ibc-go/v5/modules/core/exported"
+)
+
+// VerifyClientMessage introspects the provided ClientMessage and checks its validity
+// A Solomachine Header is considered valid if the currently registered public key has signed over the new public key with the correct sequence
+// A Solomachine Misbehaviour is considered valid if duplicate signatures of the current public key are found on two different messages at a given sequence
+func (cs ClientState) VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg exported.ClientMessage) error {
+ switch msg := clientMsg.(type) {
+ case *Header:
+ return cs.verifyHeader(ctx, cdc, clientStore, msg)
+ case *Misbehaviour:
+ return cs.verifyMisbehaviour(ctx, cdc, clientStore, msg)
+ default:
+ return sdkerrors.Wrapf(clienttypes.ErrInvalidClientType, "expected type of %T or %T, got type %T", Header{}, Misbehaviour{}, msg)
+ }
+}
+
+func (cs ClientState) verifyHeader(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, header *Header) error {
+ // assert update sequence is current sequence
+ if header.Sequence != cs.Sequence {
+ return sdkerrors.Wrapf(
+ clienttypes.ErrInvalidHeader,
+ "header sequence does not match the client state sequence (%d != %d)", header.Sequence, cs.Sequence,
+ )
+ }
+
+ // assert update timestamp is not less than current consensus state timestamp
+ if header.Timestamp < cs.ConsensusState.Timestamp {
+ return sdkerrors.Wrapf(
+ clienttypes.ErrInvalidHeader,
+ "header timestamp is less than to the consensus state timestamp (%d < %d)", header.Timestamp, cs.ConsensusState.Timestamp,
+ )
+ }
+
+ // assert currently registered public key signed over the new public key with correct sequence
+ headerData := &HeaderData{
+ NewPubKey: header.NewPublicKey,
+ NewDiversifier: header.NewDiversifier,
+ }
+
+ dataBz, err := cdc.Marshal(headerData)
+ if err != nil {
+ return err
+ }
+
+ signBytes := &SignBytes{
+ Sequence: header.Sequence,
+ Timestamp: header.Timestamp,
+ Diversifier: cs.ConsensusState.Diversifier,
+ Path: []byte{},
+ Data: dataBz,
+ }
+
+ data, err := cdc.Marshal(signBytes)
+ if err != nil {
+ return err
+ }
+
+ sigData, err := UnmarshalSignatureData(cdc, header.Signature)
+ if err != nil {
+ return err
+ }
+
+ publicKey, err := cs.ConsensusState.GetPubKey()
+ if err != nil {
+ return err
+ }
+
+ if err := VerifySignature(publicKey, data, sigData); err != nil {
+ return sdkerrors.Wrap(ErrInvalidHeader, err.Error())
+ }
+
+ return nil
+}
+
+func (cs ClientState) verifyMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, misbehaviour *Misbehaviour) error {
+ // NOTE: a check that the misbehaviour message data are not equal is done by
+ // misbehaviour.ValidateBasic which is called by the 02-client keeper.
+ // verify first signature
+ if err := cs.verifySignatureAndData(cdc, misbehaviour, misbehaviour.SignatureOne); err != nil {
+ return sdkerrors.Wrap(err, "failed to verify signature one")
+ }
+
+ // verify second signature
+ if err := cs.verifySignatureAndData(cdc, misbehaviour, misbehaviour.SignatureTwo); err != nil {
+ return sdkerrors.Wrap(err, "failed to verify signature two")
+ }
+
+ return nil
+}
+
+// UpdateState updates the consensus state to the new public key and an incremented sequence.
+// A list containing the updated consensus height is returned.
+func (cs ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg exported.ClientMessage) []exported.Height {
+ smHeader, ok := clientMsg.(*Header)
+ if !ok {
+ panic(fmt.Errorf("unsupported ClientMessage: %T", clientMsg))
+ }
+
+ // create new solomachine ConsensusState
+ consensusState := &ConsensusState{
+ PublicKey: smHeader.NewPublicKey,
+ Diversifier: smHeader.NewDiversifier,
+ Timestamp: smHeader.Timestamp,
+ }
+
+ cs.Sequence++
+ cs.ConsensusState = consensusState
+
+ setClientState(clientStore, cdc, &cs)
+
+ return []exported.Height{clienttypes.NewHeight(0, cs.Sequence)}
+}
+
+// CheckForMisbehaviour returns true for type Misbehaviour (passed VerifyClientMessage check), otherwise returns false
+func (cs ClientState) CheckForMisbehaviour(_ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore, clientMsg exported.ClientMessage) bool {
+ if _, ok := clientMsg.(*Misbehaviour); ok {
+ return true
+ }
+
+ return false
+}
+
+// UpdateStateOnMisbehaviour updates state upon misbehaviour. This method should only be called on misbehaviour
+// as it does not perform any misbehaviour checks.
+func (cs ClientState) UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, _ exported.ClientMessage) {
+ cs.IsFrozen = true
+
+ setClientState(clientStore, cdc, &cs)
+}
diff --git a/modules/light-clients/06-solomachine/update_test.go b/modules/light-clients/06-solomachine/update_test.go
new file mode 100644
index 00000000000..12ef195b220
--- /dev/null
+++ b/modules/light-clients/06-solomachine/update_test.go
@@ -0,0 +1,564 @@
+package solomachine_test
+
+import (
+ codectypes "github.com/cosmos/cosmos-sdk/codec/types"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
+ host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
+ "github.com/cosmos/ibc-go/v5/modules/core/exported"
+ solomachine "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
+ ibctesting "github.com/cosmos/ibc-go/v5/testing"
+)
+
+func (suite *SoloMachineTestSuite) TestVerifyClientMessageHeader() {
+ var (
+ clientMsg exported.ClientMessage
+ clientState *solomachine.ClientState
+ )
+
+ // test singlesig and multisig public keys
+ for _, sm := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
+
+ testCases := []struct {
+ name string
+ setup func()
+ expPass bool
+ }{
+ {
+ "successful header",
+ func() {
+ clientMsg = sm.CreateHeader(sm.Diversifier)
+ },
+ true,
+ },
+ {
+ "successful header with new diversifier",
+ func() {
+ clientMsg = sm.CreateHeader(sm.Diversifier + "0")
+ },
+ true,
+ },
+ {
+ "successful misbehaviour",
+ func() {
+ clientMsg = sm.CreateMisbehaviour()
+ },
+ true,
+ },
+ {
+ "invalid client message type",
+ func() {
+ clientMsg = &ibctm.Header{}
+ },
+ false,
+ },
+ {
+ "wrong sequence in header",
+ func() {
+ // store in temp before assigning to interface type
+ h := sm.CreateHeader(sm.Diversifier)
+ h.Sequence++
+ clientMsg = h
+ },
+ false,
+ },
+ {
+ "invalid header Signature",
+ func() {
+ h := sm.CreateHeader(sm.Diversifier)
+ h.Signature = suite.GetInvalidProof()
+ clientMsg = h
+ }, false,
+ },
+ {
+ "invalid timestamp in header",
+ func() {
+ h := sm.CreateHeader(sm.Diversifier)
+ h.Timestamp--
+ clientMsg = h
+ }, false,
+ },
+ {
+ "signature uses wrong sequence",
+ func() {
+
+ sm.Sequence++
+ clientMsg = sm.CreateHeader(sm.Diversifier)
+ },
+ false,
+ },
+ {
+ "signature uses new pubkey to sign",
+ func() {
+ // store in temp before assinging to interface type
+ cs := sm.ClientState()
+ h := sm.CreateHeader(sm.Diversifier)
+
+ publicKey, err := codectypes.NewAnyWithValue(sm.PublicKey)
+ suite.NoError(err)
+
+ data := &solomachine.HeaderData{
+ NewPubKey: publicKey,
+ NewDiversifier: h.NewDiversifier,
+ }
+
+ dataBz, err := suite.chainA.Codec.Marshal(data)
+ suite.Require().NoError(err)
+
+ // generate invalid signature
+ signBytes := &solomachine.SignBytes{
+ Sequence: cs.Sequence,
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte("invalid signature data"),
+ Data: dataBz,
+ }
+
+ signBz, err := suite.chainA.Codec.Marshal(signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(signBz)
+ suite.Require().NoError(err)
+ h.Signature = sig
+
+ clientState = cs
+ clientMsg = h
+
+ },
+ false,
+ },
+ {
+ "signature signs over old pubkey",
+ func() {
+ // store in temp before assinging to interface type
+ cs := sm.ClientState()
+ oldPubKey := sm.PublicKey
+ h := sm.CreateHeader(sm.Diversifier)
+
+ // generate invalid signature
+ data := append(sdk.Uint64ToBigEndian(cs.Sequence), oldPubKey.Bytes()...)
+ sig := sm.GenerateSignature(data)
+ h.Signature = sig
+
+ clientState = cs
+ clientMsg = h
+ },
+ false,
+ },
+ {
+ "consensus state public key is nil - header",
+ func() {
+ clientState.ConsensusState.PublicKey = nil
+ clientMsg = sm.CreateHeader(sm.Diversifier)
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+ clientState = sm.ClientState()
+
+ // setup test
+ tc.setup()
+
+ err := clientState.VerifyClientMessage(suite.chainA.GetContext(), suite.chainA.Codec, suite.store, clientMsg)
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+ }
+}
+
+func (suite *SoloMachineTestSuite) TestVerifyClientMessageMisbehaviour() {
+ var (
+ clientMsg exported.ClientMessage
+ clientState *solomachine.ClientState
+ )
+
+ // test singlesig and multisig public keys
+ for _, sm := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
+
+ testCases := []struct {
+ name string
+ setup func()
+ expPass bool
+ }{
+ {
+ "successful misbehaviour",
+ func() {
+ clientMsg = sm.CreateMisbehaviour()
+ },
+ true,
+ },
+ {
+ "old misbehaviour is successful (timestamp is less than current consensus state)",
+ func() {
+ clientState = sm.ClientState()
+ sm.Time = sm.Time - 5
+ clientMsg = sm.CreateMisbehaviour()
+ }, true,
+ },
+ {
+ "invalid client message type",
+ func() {
+ clientMsg = &ibctm.Header{}
+ },
+ false,
+ },
+ {
+ "consensus state pubkey is nil",
+ func() {
+ clientState.ConsensusState.PublicKey = nil
+ clientMsg = sm.CreateMisbehaviour()
+ },
+ false,
+ },
+ {
+ "invalid SignatureOne SignatureData",
+ func() {
+ m := sm.CreateMisbehaviour()
+
+ m.SignatureOne.Signature = suite.GetInvalidProof()
+ clientMsg = m
+ }, false,
+ },
+ {
+ "invalid SignatureTwo SignatureData",
+ func() {
+ m := sm.CreateMisbehaviour()
+
+ m.SignatureTwo.Signature = suite.GetInvalidProof()
+ clientMsg = m
+ }, false,
+ },
+ {
+ "invalid SignatureOne timestamp",
+ func() {
+ m := sm.CreateMisbehaviour()
+
+ m.SignatureOne.Timestamp = 1000000000000
+ clientMsg = m
+ }, false,
+ },
+ {
+ "invalid SignatureTwo timestamp",
+ func() {
+ m := sm.CreateMisbehaviour()
+
+ m.SignatureTwo.Timestamp = 1000000000000
+ clientMsg = m
+ }, false,
+ },
+ {
+ "invalid first signature data",
+ func() {
+ // store in temp before assigning to interface type
+ m := sm.CreateMisbehaviour()
+
+ msg := []byte("DATA ONE")
+ signBytes := &solomachine.SignBytes{
+ Sequence: sm.Sequence + 1,
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte("invalid signature data"),
+ Data: msg,
+ }
+
+ data, err := suite.chainA.Codec.Marshal(signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(data)
+
+ m.SignatureOne.Signature = sig
+ m.SignatureOne.Data = msg
+ clientMsg = m
+ },
+ false,
+ },
+ {
+ "invalid second signature data",
+ func() {
+ // store in temp before assigning to interface type
+ m := sm.CreateMisbehaviour()
+
+ msg := []byte("DATA TWO")
+ signBytes := &solomachine.SignBytes{
+ Sequence: sm.Sequence + 1,
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte("invalid signature data"),
+ Data: msg,
+ }
+
+ data, err := suite.chainA.Codec.Marshal(signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(data)
+
+ m.SignatureTwo.Signature = sig
+ m.SignatureTwo.Data = msg
+ clientMsg = m
+ },
+ false,
+ },
+ {
+ "wrong pubkey generates first signature",
+ func() {
+ badMisbehaviour := sm.CreateMisbehaviour()
+
+ // update public key to a new one
+ sm.CreateHeader(sm.Diversifier)
+ m := sm.CreateMisbehaviour()
+
+ // set SignatureOne to use the wrong signature
+ m.SignatureOne = badMisbehaviour.SignatureOne
+ clientMsg = m
+ }, false,
+ },
+ {
+ "wrong pubkey generates second signature",
+ func() {
+ badMisbehaviour := sm.CreateMisbehaviour()
+
+ // update public key to a new one
+ sm.CreateHeader(sm.Diversifier)
+ m := sm.CreateMisbehaviour()
+
+ // set SignatureTwo to use the wrong signature
+ m.SignatureTwo = badMisbehaviour.SignatureTwo
+ clientMsg = m
+ }, false,
+ },
+ {
+ "signatures sign over different sequence",
+ func() {
+
+ // store in temp before assigning to interface type
+ m := sm.CreateMisbehaviour()
+
+ // Signature One
+ msg := []byte("DATA ONE")
+ // sequence used is plus 1
+ signBytes := &solomachine.SignBytes{
+ Sequence: sm.Sequence + 1,
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte("invalid signature data"),
+ Data: msg,
+ }
+
+ data, err := suite.chainA.Codec.Marshal(signBytes)
+ suite.Require().NoError(err)
+
+ sig := sm.GenerateSignature(data)
+
+ m.SignatureOne.Signature = sig
+ m.SignatureOne.Data = msg
+
+ // Signature Two
+ msg = []byte("DATA TWO")
+ // sequence used is minus 1
+
+ signBytes = &solomachine.SignBytes{
+ Sequence: sm.Sequence - 1,
+ Timestamp: sm.Time,
+ Diversifier: sm.Diversifier,
+ Path: []byte("invalid signature data"),
+ Data: msg,
+ }
+ data, err = suite.chainA.Codec.Marshal(signBytes)
+ suite.Require().NoError(err)
+
+ sig = sm.GenerateSignature(data)
+
+ m.SignatureTwo.Signature = sig
+ m.SignatureTwo.Data = msg
+
+ clientMsg = m
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+ clientState = sm.ClientState()
+
+ // setup test
+ tc.setup()
+
+ err := clientState.VerifyClientMessage(suite.chainA.GetContext(), suite.chainA.Codec, suite.store, clientMsg)
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+ }
+}
+
+func (suite *SoloMachineTestSuite) TestUpdateState() {
+ var (
+ clientState exported.ClientState
+ clientMsg exported.ClientMessage
+ )
+
+ // test singlesig and multisig public keys
+ for _, sm := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
+
+ testCases := []struct {
+ name string
+ setup func()
+ expPass bool
+ }{
+ {
+ "successful update",
+ func() {
+ clientState = sm.ClientState()
+ clientMsg = sm.CreateHeader(sm.Diversifier)
+ },
+ true,
+ },
+ {
+ "invalid type misbehaviour",
+ func() {
+ clientState = sm.ClientState()
+ clientMsg = sm.CreateMisbehaviour()
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+ tc.setup() // setup test
+
+ if tc.expPass {
+ consensusHeights := clientState.UpdateState(suite.chainA.GetContext(), suite.chainA.Codec, suite.store, clientMsg)
+
+ clientStateBz := suite.store.Get(host.ClientStateKey())
+ suite.Require().NotEmpty(clientStateBz)
+
+ newClientState := clienttypes.MustUnmarshalClientState(suite.chainA.Codec, clientStateBz)
+
+ suite.Require().Len(consensusHeights, 1)
+ suite.Require().Equal(uint64(0), consensusHeights[0].GetRevisionNumber())
+ suite.Require().Equal(newClientState.(*solomachine.ClientState).Sequence, consensusHeights[0].GetRevisionHeight())
+
+ suite.Require().False(newClientState.(*solomachine.ClientState).IsFrozen)
+ suite.Require().Equal(clientMsg.(*solomachine.Header).Sequence+1, newClientState.(*solomachine.ClientState).Sequence)
+ suite.Require().Equal(clientMsg.(*solomachine.Header).NewPublicKey, newClientState.(*solomachine.ClientState).ConsensusState.PublicKey)
+ suite.Require().Equal(clientMsg.(*solomachine.Header).NewDiversifier, newClientState.(*solomachine.ClientState).ConsensusState.Diversifier)
+ suite.Require().Equal(clientMsg.(*solomachine.Header).Timestamp, newClientState.(*solomachine.ClientState).ConsensusState.Timestamp)
+ } else {
+ suite.Require().Panics(func() {
+ clientState.UpdateState(suite.chainA.GetContext(), suite.chainA.Codec, suite.store, clientMsg)
+ })
+ }
+
+ })
+ }
+ }
+}
+
+func (suite *SoloMachineTestSuite) TestCheckForMisbehaviour() {
+ var (
+ clientMsg exported.ClientMessage
+ )
+
+ // test singlesig and multisig public keys
+ for _, sm := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
+ testCases := []struct {
+ name string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "success",
+ func() {
+ clientMsg = sm.CreateMisbehaviour()
+ },
+ true,
+ },
+ {
+ "normal header returns false",
+ func() {
+ clientMsg = sm.CreateHeader(sm.Diversifier)
+ },
+ false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+ clientState := sm.ClientState()
+
+ tc.malleate()
+
+ foundMisbehaviour := clientState.CheckForMisbehaviour(suite.chainA.GetContext(), suite.chainA.Codec, suite.store, clientMsg)
+
+ if tc.expPass {
+ suite.Require().True(foundMisbehaviour)
+ } else {
+ suite.Require().False(foundMisbehaviour)
+ }
+
+ })
+ }
+ }
+}
+
+func (suite *SoloMachineTestSuite) TestUpdateStateOnMisbehaviour() {
+ // test singlesig and multisig public keys
+ for _, sm := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} {
+ testCases := []struct {
+ name string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "success",
+ func() {},
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+ clientState := sm.ClientState()
+
+ tc.malleate()
+
+ clientState.UpdateStateOnMisbehaviour(suite.chainA.GetContext(), suite.chainA.Codec, suite.store, nil)
+
+ if tc.expPass {
+ clientStateBz := suite.store.Get(host.ClientStateKey())
+ suite.Require().NotEmpty(clientStateBz)
+
+ newClientState := clienttypes.MustUnmarshalClientState(suite.chainA.Codec, clientStateBz)
+
+ suite.Require().True(newClientState.(*solomachine.ClientState).IsFrozen)
+ }
+ })
+ }
+ }
+}
diff --git a/modules/light-clients/07-tendermint/client_state.go b/modules/light-clients/07-tendermint/client_state.go
new file mode 100644
index 00000000000..0c3715e4db1
--- /dev/null
+++ b/modules/light-clients/07-tendermint/client_state.go
@@ -0,0 +1,335 @@
+package tendermint
+
+import (
+ "strings"
+ "time"
+
+ ics23 "github.com/confio/ics23/go"
+ "github.com/cosmos/cosmos-sdk/codec"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
+ "github.com/tendermint/tendermint/light"
+ tmtypes "github.com/tendermint/tendermint/types"
+
+ clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
+ commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
+ "github.com/cosmos/ibc-go/v5/modules/core/exported"
+)
+
+var _ exported.ClientState = (*ClientState)(nil)
+
+// NewClientState creates a new ClientState instance
+func NewClientState(
+ chainID string, trustLevel Fraction,
+ trustingPeriod, ubdPeriod, maxClockDrift time.Duration,
+ latestHeight clienttypes.Height, specs []*ics23.ProofSpec,
+ upgradePath []string, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour bool,
+) *ClientState {
+ return &ClientState{
+ ChainId: chainID,
+ TrustLevel: trustLevel,
+ TrustingPeriod: trustingPeriod,
+ UnbondingPeriod: ubdPeriod,
+ MaxClockDrift: maxClockDrift,
+ LatestHeight: latestHeight,
+ FrozenHeight: clienttypes.ZeroHeight(),
+ ProofSpecs: specs,
+ UpgradePath: upgradePath,
+ AllowUpdateAfterExpiry: allowUpdateAfterExpiry,
+ AllowUpdateAfterMisbehaviour: allowUpdateAfterMisbehaviour,
+ }
+}
+
+// GetChainID returns the chain-id
+func (cs ClientState) GetChainID() string {
+ return cs.ChainId
+}
+
+// ClientType is tendermint.
+func (cs ClientState) ClientType() string {
+ return exported.Tendermint
+}
+
+// GetLatestHeight returns latest block height.
+func (cs ClientState) GetLatestHeight() exported.Height {
+ return cs.LatestHeight
+}
+
+// GetTimestampAtHeight returns the timestamp in nanoseconds of the consensus state at the given height.
+func (cs ClientState) GetTimestampAtHeight(
+ ctx sdk.Context,
+ clientStore sdk.KVStore,
+ cdc codec.BinaryCodec,
+ height exported.Height,
+) (uint64, error) {
+ // get consensus state at height from clientStore to check for expiry
+ consState, found := GetConsensusState(clientStore, cdc, height)
+ if !found {
+ return 0, sdkerrors.Wrapf(clienttypes.ErrConsensusStateNotFound, "height (%s)", height)
+ }
+ return consState.GetTimestamp(), nil
+}
+
+// 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.BinaryCodec,
+) exported.Status {
+ if !cs.FrozenHeight.IsZero() {
+ return exported.Frozen
+ }
+
+ // get latest consensus state from clientStore to check for expiry
+ consState, found := GetConsensusState(clientStore, cdc, cs.GetLatestHeight())
+ if !found {
+ // if the client state does not have an associated consensus state for its latest height
+ // then it must be expired
+ return exported.Expired
+ }
+
+ if cs.IsExpired(consState.Timestamp, ctx.BlockTime()) {
+ return exported.Expired
+ }
+
+ return exported.Active
+}
+
+// IsExpired returns whether or not the client has passed the trusting period since the last
+// update (in which case no headers are considered valid).
+func (cs ClientState) IsExpired(latestTimestamp, now time.Time) bool {
+ expirationTime := latestTimestamp.Add(cs.TrustingPeriod)
+ return !expirationTime.After(now)
+}
+
+// Validate performs a basic validation of the client state fields.
+func (cs ClientState) Validate() error {
+ if strings.TrimSpace(cs.ChainId) == "" {
+ return sdkerrors.Wrap(ErrInvalidChainID, "chain id cannot be empty string")
+ }
+
+ // NOTE: the value of tmtypes.MaxChainIDLen may change in the future.
+ // If this occurs, the code here must account for potential difference
+ // between the tendermint version being run by the counterparty chain
+ // and the tendermint version used by this light client.
+ // https://github.com/cosmos/ibc-go/issues/177
+ if len(cs.ChainId) > tmtypes.MaxChainIDLen {
+ return sdkerrors.Wrapf(ErrInvalidChainID, "chainID is too long; got: %d, max: %d", len(cs.ChainId), tmtypes.MaxChainIDLen)
+ }
+
+ if err := light.ValidateTrustLevel(cs.TrustLevel.ToTendermint()); err != nil {
+ return err
+ }
+ if cs.TrustingPeriod == 0 {
+ return sdkerrors.Wrap(ErrInvalidTrustingPeriod, "trusting period cannot be zero")
+ }
+ if cs.UnbondingPeriod == 0 {
+ return sdkerrors.Wrap(ErrInvalidUnbondingPeriod, "unbonding period cannot be zero")
+ }
+ if cs.MaxClockDrift == 0 {
+ return sdkerrors.Wrap(ErrInvalidMaxClockDrift, "max clock drift cannot be zero")
+ }
+
+ // the latest height revision number must match the chain id revision number
+ if cs.LatestHeight.RevisionNumber != clienttypes.ParseChainID(cs.ChainId) {
+ return sdkerrors.Wrapf(ErrInvalidHeaderHeight,
+ "latest height revision number must match chain id revision number (%d != %d)", cs.LatestHeight.RevisionNumber, clienttypes.ParseChainID(cs.ChainId))
+ }
+ if cs.LatestHeight.RevisionHeight == 0 {
+ return sdkerrors.Wrapf(ErrInvalidHeaderHeight, "tendermint client's latest height revision height cannot be zero")
+ }
+ if cs.TrustingPeriod >= cs.UnbondingPeriod {
+ return sdkerrors.Wrapf(
+ ErrInvalidTrustingPeriod,
+ "trusting period (%s) should be < unbonding period (%s)", cs.TrustingPeriod, cs.UnbondingPeriod,
+ )
+ }
+
+ if cs.ProofSpecs == nil {
+ return sdkerrors.Wrap(ErrInvalidProofSpecs, "proof specs cannot be nil for tm client")
+ }
+ for i, spec := range cs.ProofSpecs {
+ if spec == nil {
+ return sdkerrors.Wrapf(ErrInvalidProofSpecs, "proof spec cannot be nil at index: %d", i)
+ }
+ }
+ // UpgradePath may be empty, but if it isn't, each key must be non-empty
+ for i, k := range cs.UpgradePath {
+ if strings.TrimSpace(k) == "" {
+ return sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "key in upgrade path at index %d cannot be empty", i)
+ }
+ }
+
+ return nil
+}
+
+// GetProofSpecs returns the format the client expects for proof verification
+// as a string array specifying the proof type for each position in chained proof
+func (cs ClientState) GetProofSpecs() []*ics23.ProofSpec {
+ return cs.ProofSpecs
+}
+
+// ZeroCustomFields returns a ClientState that is a copy of the current ClientState
+// with all client customizable fields zeroed out
+func (cs ClientState) ZeroCustomFields() exported.ClientState {
+ // copy over all chain-specified fields
+ // and leave custom fields empty
+ return &ClientState{
+ ChainId: cs.ChainId,
+ UnbondingPeriod: cs.UnbondingPeriod,
+ LatestHeight: cs.LatestHeight,
+ ProofSpecs: cs.ProofSpecs,
+ UpgradePath: cs.UpgradePath,
+ }
+}
+
+// Initialize will check that initial consensus state is a Tendermint consensus state
+// and will store ProcessedTime for initial consensus state as ctx.BlockTime()
+func (cs ClientState) Initialize(ctx sdk.Context, _ codec.BinaryCodec, clientStore sdk.KVStore, consState exported.ConsensusState) error {
+ if _, ok := consState.(*ConsensusState); !ok {
+ return sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "invalid initial consensus state. expected type: %T, got: %T",
+ &ConsensusState{}, consState)
+ }
+ // set metadata for initial consensus state.
+ setConsensusMetadata(ctx, clientStore, cs.GetLatestHeight())
+ return nil
+}
+
+// VerifyMembership is a generic proof verification method which verifies a proof of the existence of a value at a given CommitmentPath at the specified height.
+// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24).
+func (cs ClientState) VerifyMembership(
+ ctx sdk.Context,
+ clientStore sdk.KVStore,
+ cdc codec.BinaryCodec,
+ height exported.Height,
+ delayTimePeriod uint64,
+ delayBlockPeriod uint64,
+ proof []byte,
+ path []byte,
+ value []byte,
+) error {
+ if cs.GetLatestHeight().LT(height) {
+ return sdkerrors.Wrapf(
+ sdkerrors.ErrInvalidHeight,
+ "client state height < proof height (%d < %d), please ensure the client has been updated", cs.GetLatestHeight(), height,
+ )
+ }
+
+ if err := verifyDelayPeriodPassed(ctx, clientStore, height, delayTimePeriod, delayBlockPeriod); err != nil {
+ return err
+ }
+
+ var merkleProof commitmenttypes.MerkleProof
+ if err := cdc.Unmarshal(proof, &merkleProof); err != nil {
+ return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "failed to unmarshal proof into ICS 23 commitment merkle proof")
+ }
+
+ var merklePath commitmenttypes.MerklePath
+ if err := cdc.Unmarshal(path, &merklePath); err != nil {
+ return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "failed to unmarshal path into ICS 23 commitment merkle path")
+ }
+
+ consensusState, found := GetConsensusState(clientStore, cdc, height)
+ if !found {
+ return sdkerrors.Wrap(clienttypes.ErrConsensusStateNotFound, "please ensure the proof was constructed against a height that exists on the client")
+ }
+
+ if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), merklePath, value); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// VerifyNonMembership is a generic proof verification method which verifies the absence of a given CommitmentPath at a specified height.
+// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24).
+func (cs ClientState) VerifyNonMembership(
+ ctx sdk.Context,
+ clientStore sdk.KVStore,
+ cdc codec.BinaryCodec,
+ height exported.Height,
+ delayTimePeriod uint64,
+ delayBlockPeriod uint64,
+ proof []byte,
+ path []byte,
+) error {
+ if cs.GetLatestHeight().LT(height) {
+ return sdkerrors.Wrapf(
+ sdkerrors.ErrInvalidHeight,
+ "client state height < proof height (%d < %d), please ensure the client has been updated", cs.GetLatestHeight(), height,
+ )
+ }
+
+ if err := verifyDelayPeriodPassed(ctx, clientStore, height, delayTimePeriod, delayBlockPeriod); err != nil {
+ return err
+ }
+
+ var merkleProof commitmenttypes.MerkleProof
+ if err := cdc.Unmarshal(proof, &merkleProof); err != nil {
+ return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "failed to unmarshal proof into ICS 23 commitment merkle proof")
+ }
+
+ var merklePath commitmenttypes.MerklePath
+ if err := cdc.Unmarshal(path, &merklePath); err != nil {
+ return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "failed to unmarshal path into ICS 23 commitment merkle path")
+ }
+
+ consensusState, found := GetConsensusState(clientStore, cdc, height)
+ if !found {
+ return sdkerrors.Wrap(clienttypes.ErrConsensusStateNotFound, "please ensure the proof was constructed against a height that exists on the client")
+ }
+
+ if err := merkleProof.VerifyNonMembership(cs.ProofSpecs, consensusState.GetRoot(), merklePath); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// verifyDelayPeriodPassed will ensure that at least delayTimePeriod amount of time and delayBlockPeriod number of blocks have passed
+// since consensus state was submitted before allowing verification to continue.
+func verifyDelayPeriodPassed(ctx sdk.Context, store sdk.KVStore, proofHeight exported.Height, delayTimePeriod, delayBlockPeriod uint64) error {
+ if delayTimePeriod != 0 {
+ // check that executing chain's timestamp has passed consensusState's processed time + delay time period
+ processedTime, ok := GetProcessedTime(store, proofHeight)
+ if !ok {
+ return sdkerrors.Wrapf(ErrProcessedTimeNotFound, "processed time not found for height: %s", proofHeight)
+ }
+
+ currentTimestamp := uint64(ctx.BlockTime().UnixNano())
+ validTime := processedTime + delayTimePeriod
+
+ // NOTE: delay time period is inclusive, so if currentTimestamp is validTime, then we return no error
+ if currentTimestamp < validTime {
+ return sdkerrors.Wrapf(ErrDelayPeriodNotPassed, "cannot verify packet until time: %d, current time: %d",
+ validTime, currentTimestamp)
+ }
+
+ }
+
+ if delayBlockPeriod != 0 {
+ // check that executing chain's height has passed consensusState's processed height + delay block period
+ processedHeight, ok := GetProcessedHeight(store, proofHeight)
+ if !ok {
+ return sdkerrors.Wrapf(ErrProcessedHeightNotFound, "processed height not found for height: %s", proofHeight)
+ }
+
+ currentHeight := clienttypes.GetSelfHeight(ctx)
+ validHeight := clienttypes.NewHeight(processedHeight.GetRevisionNumber(), processedHeight.GetRevisionHeight()+delayBlockPeriod)
+
+ // NOTE: delay block period is inclusive, so if currentHeight is validHeight, then we return no error
+ if currentHeight.LT(validHeight) {
+ return sdkerrors.Wrapf(ErrDelayPeriodNotPassed, "cannot verify packet until height: %s, current height: %s",
+ validHeight, currentHeight)
+ }
+ }
+
+ return nil
+}
diff --git a/modules/light-clients/07-tendermint/client_state_test.go b/modules/light-clients/07-tendermint/client_state_test.go
new file mode 100644
index 00000000000..9284e44cec8
--- /dev/null
+++ b/modules/light-clients/07-tendermint/client_state_test.go
@@ -0,0 +1,700 @@
+package tendermint_test
+
+import (
+ "time"
+
+ ics23 "github.com/confio/ics23/go"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ transfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types"
+ clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
+ channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
+ commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
+ host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
+ "github.com/cosmos/ibc-go/v5/modules/core/exported"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
+ ibctesting "github.com/cosmos/ibc-go/v5/testing"
+ ibcmock "github.com/cosmos/ibc-go/v5/testing/mock"
+)
+
+const (
+ // Do not change the length of these variables
+ fiftyCharChainID = "12345678901234567890123456789012345678901234567890"
+ fiftyOneCharChainID = "123456789012345678901234567890123456789012345678901"
+)
+
+var (
+ invalidProof = []byte("invalid proof")
+)
+
+func (suite *TendermintTestSuite) TestStatus() {
+ var (
+ path *ibctesting.Path
+ clientState *ibctm.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 without consensus state", func() {
+ clientState.LatestHeight = clientState.LatestHeight.Increment().(clienttypes.Height)
+ path.EndpointA.SetClientState(clientState)
+ }, exported.Expired},
+ {"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().(*ibctm.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
+ clientState *ibctm.ClientState
+ expPass bool
+ }{
+ {
+ name: "valid client",
+ clientState: ibctm.NewClientState(chainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
+ expPass: true,
+ },
+ {
+ name: "valid client with nil upgrade path",
+ clientState: ibctm.NewClientState(chainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), nil, false, false),
+ expPass: true,
+ },
+ {
+ name: "invalid chainID",
+ clientState: ibctm.NewClientState(" ", ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
+ expPass: false,
+ },
+ {
+ // NOTE: if this test fails, the code must account for the change in chainID length across tendermint versions!
+ // Do not only fix the test, fix the code!
+ // https://github.com/cosmos/ibc-go/issues/177
+ name: "valid chainID - chainID validation failed for chainID of length 50! ",
+ clientState: ibctm.NewClientState(fiftyCharChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
+ expPass: true,
+ },
+ {
+ // NOTE: if this test fails, the code must account for the change in chainID length across tendermint versions!
+ // Do not only fix the test, fix the code!
+ // https://github.com/cosmos/ibc-go/issues/177
+ name: "invalid chainID - chainID validation did not fail for chainID of length 51! ",
+ clientState: ibctm.NewClientState(fiftyOneCharChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
+ expPass: false,
+ },
+ {
+ name: "invalid trust level",
+ clientState: ibctm.NewClientState(chainID, ibctm.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
+ expPass: false,
+ },
+ {
+ name: "invalid trusting period",
+ clientState: ibctm.NewClientState(chainID, ibctm.DefaultTrustLevel, 0, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
+ expPass: false,
+ },
+ {
+ name: "invalid unbonding period",
+ clientState: ibctm.NewClientState(chainID, ibctm.DefaultTrustLevel, trustingPeriod, 0, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
+ expPass: false,
+ },
+ {
+ name: "invalid max clock drift",
+ clientState: ibctm.NewClientState(chainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, 0, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
+ expPass: false,
+ },
+ {
+ name: "invalid revision number",
+ clientState: ibctm.NewClientState(chainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(1, 1), commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
+ expPass: false,
+ },
+ {
+ name: "invalid revision height",
+ clientState: ibctm.NewClientState(chainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.ZeroHeight(), commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
+ expPass: false,
+ },
+ {
+ name: "trusting period not less than unbonding period",
+ clientState: ibctm.NewClientState(chainID, ibctm.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
+ expPass: false,
+ },
+ {
+ name: "proof specs is nil",
+ clientState: ibctm.NewClientState(chainID, ibctm.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, nil, upgradePath, false, false),
+ expPass: false,
+ },
+ {
+ name: "proof specs contains nil",
+ clientState: ibctm.NewClientState(chainID, ibctm.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, []*ics23.ProofSpec{ics23.TendermintSpec, nil}, upgradePath, false, false),
+ expPass: false,
+ },
+ }
+
+ for _, tc := range testCases {
+ err := tc.clientState.Validate()
+ if tc.expPass {
+ suite.Require().NoError(err, tc.name)
+ } else {
+ suite.Require().Error(err, tc.name)
+ }
+ }
+}
+
+func (suite *TendermintTestSuite) TestInitialize() {
+
+ testCases := []struct {
+ name string
+ consensusState exported.ConsensusState
+ expPass bool
+ }{
+ {
+ name: "valid consensus",
+ consensusState: &ibctm.ConsensusState{},
+ expPass: true,
+ },
+ {
+ name: "invalid consensus: consensus state is solomachine consensus",
+ consensusState: ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2).ConsensusState(),
+ expPass: false,
+ },
+ }
+
+ path := ibctesting.NewPath(suite.chainA, suite.chainB)
+ err := path.EndpointA.CreateClient()
+ suite.Require().NoError(err)
+
+ clientState := suite.chainA.GetClientState(path.EndpointA.ClientID)
+ store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
+
+ for _, tc := range testCases {
+ err := clientState.Initialize(suite.chainA.GetContext(), suite.chainA.Codec, store, tc.consensusState)
+ if tc.expPass {
+ suite.Require().NoError(err, "valid case returned an error")
+ } else {
+ suite.Require().Error(err, "invalid case didn't return an error")
+ }
+ }
+}
+
+func (suite *TendermintTestSuite) TestVerifyMembership() {
+ var (
+ testingpath *ibctesting.Path
+ delayTimePeriod uint64
+ delayBlockPeriod uint64
+ proofHeight exported.Height
+ proof []byte
+ path []byte
+ value []byte
+ )
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "successful ClientState verification",
+ func() {
+ // default proof construction uses ClientState
+ },
+ true,
+ },
+ {
+ "successful ConsensusState verification", func() {
+ key := host.FullConsensusStateKey(testingpath.EndpointB.ClientID, testingpath.EndpointB.GetClientState().GetLatestHeight())
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err := commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainB.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, proofHeight = suite.chainB.QueryProof(key)
+
+ consensusState := testingpath.EndpointB.GetConsensusState(testingpath.EndpointB.GetClientState().GetLatestHeight()).(*ibctm.ConsensusState)
+ value, err = suite.chainB.Codec.MarshalInterface(consensusState)
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ {
+ "successful Connection verification", func() {
+ key := host.ConnectionKey(testingpath.EndpointB.ConnectionID)
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err := commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainB.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, proofHeight = suite.chainB.QueryProof(key)
+
+ connection := testingpath.EndpointB.GetConnection()
+ value, err = suite.chainB.Codec.Marshal(&connection)
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ {
+ "successful Channel verification", func() {
+ key := host.ChannelKey(testingpath.EndpointB.ChannelConfig.PortID, testingpath.EndpointB.ChannelID)
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err := commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainB.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, proofHeight = suite.chainB.QueryProof(key)
+
+ channel := testingpath.EndpointB.GetChannel()
+ value, err = suite.chainB.Codec.Marshal(&channel)
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ {
+ "successful PacketCommitment verification", func() {
+ // send from chainB to chainA since we are proving chainB sent a packet
+ packet := channeltypes.NewPacket(ibctesting.MockPacketData, 1, testingpath.EndpointB.ChannelConfig.PortID, testingpath.EndpointB.ChannelID, testingpath.EndpointA.ChannelConfig.PortID, testingpath.EndpointA.ChannelID, clienttypes.NewHeight(1, 100), 0)
+ err := testingpath.EndpointB.SendPacket(packet)
+ suite.Require().NoError(err)
+
+ // make packet commitment proof
+ key := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainB.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, proofHeight = testingpath.EndpointB.QueryProof(key)
+
+ value = channeltypes.CommitPacket(suite.chainA.App.GetIBCKeeper().Codec(), packet)
+ }, true,
+ },
+ {
+ "successful Acknowledgement verification", func() {
+ // send from chainA to chainB since we are proving chainB wrote an acknowledgement
+ packet := channeltypes.NewPacket(ibctesting.MockPacketData, 1, testingpath.EndpointA.ChannelConfig.PortID, testingpath.EndpointA.ChannelID, testingpath.EndpointB.ChannelConfig.PortID, testingpath.EndpointB.ChannelID, clienttypes.NewHeight(1, 100), 0)
+ err := testingpath.EndpointA.SendPacket(packet)
+ suite.Require().NoError(err)
+
+ // write receipt and ack
+ err = testingpath.EndpointB.RecvPacket(packet)
+ suite.Require().NoError(err)
+
+ key := host.PacketAcknowledgementKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainB.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, proofHeight = testingpath.EndpointB.QueryProof(key)
+
+ value = channeltypes.CommitAcknowledgement(ibcmock.MockAcknowledgement.Acknowledgement())
+ },
+ true,
+ },
+ {
+ "successful NextSequenceRecv verification", func() {
+ // send from chainA to chainB since we are proving chainB incremented the sequence recv
+ packet := channeltypes.NewPacket(ibctesting.MockPacketData, 1, testingpath.EndpointA.ChannelConfig.PortID, testingpath.EndpointA.ChannelID, testingpath.EndpointB.ChannelConfig.PortID, testingpath.EndpointB.ChannelID, clienttypes.NewHeight(1, 100), 0)
+
+ // send packet
+ err := testingpath.EndpointA.SendPacket(packet)
+ suite.Require().NoError(err)
+
+ // next seq recv incremented
+ err = testingpath.EndpointB.RecvPacket(packet)
+ suite.Require().NoError(err)
+
+ key := host.NextSequenceRecvKey(packet.GetSourcePort(), packet.GetSourceChannel())
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainB.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, proofHeight = testingpath.EndpointB.QueryProof(key)
+
+ value = sdk.Uint64ToBigEndian(packet.GetSequence() + 1)
+ },
+ true,
+ },
+ {
+ "successful verification outside IBC store", func() {
+ key := transfertypes.PortKey
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err := commitmenttypes.ApplyPrefix(commitmenttypes.NewMerklePrefix([]byte(transfertypes.StoreKey)), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainB.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ clientState := testingpath.EndpointA.GetClientState()
+ proof, proofHeight = suite.chainB.QueryProofForStore(transfertypes.StoreKey, key, int64(clientState.GetLatestHeight().GetRevisionHeight()))
+
+ value = []byte(suite.chainB.GetSimApp().TransferKeeper.GetPort(suite.chainB.GetContext()))
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ {
+ "delay time period has passed", func() {
+ delayTimePeriod = uint64(time.Second.Nanoseconds())
+ },
+ true,
+ },
+ {
+ "delay time period has not passed", func() {
+ delayTimePeriod = uint64(time.Hour.Nanoseconds())
+ },
+ false,
+ },
+ {
+ "delay block period has passed", func() {
+ delayBlockPeriod = 1
+ },
+ true,
+ },
+ {
+ "delay block period has not passed", func() {
+ delayBlockPeriod = 1000
+ },
+ false,
+ },
+ {
+ "latest client height < height", func() {
+ proofHeight = testingpath.EndpointA.GetClientState().GetLatestHeight().Increment()
+ }, false,
+ },
+ {
+ "failed to unmarshal merkle path", func() {
+ path = []byte("invalid merkle path")
+ }, false,
+ },
+ {
+ "failed to unmarshal merkle proof", func() {
+ proof = invalidProof
+ }, false,
+ },
+ {
+ "consensus state not found", func() {
+ proofHeight = clienttypes.ZeroHeight()
+ }, false,
+ },
+ {
+ "proof verification failed", func() {
+ // change the value being proved
+ value = []byte("invalid value")
+ }, false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+ suite.SetupTest() // reset
+ testingpath = ibctesting.NewPath(suite.chainA, suite.chainB)
+ testingpath.SetChannelOrdered()
+ suite.coordinator.Setup(testingpath)
+
+ // reset time and block delays to 0, malleate may change to a specific non-zero value.
+ delayTimePeriod = 0
+ delayBlockPeriod = 0
+
+ // create default proof, merklePath, and value which passes
+ // may be overwritten by malleate()
+ key := host.FullClientStateKey(testingpath.EndpointB.ClientID)
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err := commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, proofHeight = suite.chainB.QueryProof(key)
+
+ clientState := testingpath.EndpointB.GetClientState().(*ibctm.ClientState)
+ value, err = suite.chainB.Codec.MarshalInterface(clientState)
+ suite.Require().NoError(err)
+
+ tc.malleate() // make changes as necessary
+
+ clientState = testingpath.EndpointA.GetClientState().(*ibctm.ClientState)
+
+ ctx := suite.chainA.GetContext()
+ store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, testingpath.EndpointA.ClientID)
+
+ err = clientState.VerifyMembership(
+ ctx, store, suite.chainA.Codec, proofHeight, delayTimePeriod, delayBlockPeriod,
+ proof, path, value,
+ )
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+}
+
+func (suite *TendermintTestSuite) TestVerifyNonMembership() {
+ var (
+ testingpath *ibctesting.Path
+ delayTimePeriod uint64
+ delayBlockPeriod uint64
+ proofHeight exported.Height
+ proof []byte
+ path []byte
+ invalidClientID = "09-tendermint"
+ invalidConnectionID = "connection-100"
+ invalidChannelID = "channel-800"
+ invalidPortID = "invalid-port"
+ )
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "successful ClientState verification of non membership",
+ func() {
+ // default proof construction uses ClientState
+ },
+ true,
+ },
+ {
+ "successful ConsensusState verification of non membership", func() {
+ key := host.FullConsensusStateKey(invalidClientID, testingpath.EndpointB.GetClientState().GetLatestHeight())
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err := commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainB.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, proofHeight = suite.chainB.QueryProof(key)
+ },
+ true,
+ },
+ {
+ "successful Connection verification of non membership", func() {
+ key := host.ConnectionKey(invalidConnectionID)
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err := commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainB.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, proofHeight = suite.chainB.QueryProof(key)
+ },
+ true,
+ },
+ {
+ "successful Channel verification of non membership", func() {
+ key := host.ChannelKey(testingpath.EndpointB.ChannelConfig.PortID, invalidChannelID)
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err := commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainB.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, proofHeight = suite.chainB.QueryProof(key)
+ },
+ true,
+ },
+ {
+ "successful PacketCommitment verification of non membership", func() {
+ // make packet commitment proof
+ key := host.PacketCommitmentKey(invalidPortID, invalidChannelID, 1)
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err := commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainB.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, proofHeight = testingpath.EndpointB.QueryProof(key)
+ }, true,
+ },
+ {
+ "successful Acknowledgement verification of non membership", func() {
+ key := host.PacketAcknowledgementKey(invalidPortID, invalidChannelID, 1)
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err := commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainB.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, proofHeight = testingpath.EndpointB.QueryProof(key)
+ },
+ true,
+ },
+ {
+ "successful NextSequenceRecv verification of non membership", func() {
+ key := host.NextSequenceRecvKey(invalidPortID, invalidChannelID)
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err := commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainB.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, proofHeight = testingpath.EndpointB.QueryProof(key)
+ },
+ true,
+ },
+ {
+ "successful verification of non membership outside IBC store", func() {
+ key := []byte{0x08}
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err := commitmenttypes.ApplyPrefix(commitmenttypes.NewMerklePrefix([]byte(transfertypes.StoreKey)), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainB.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ clientState := testingpath.EndpointA.GetClientState()
+ proof, proofHeight = suite.chainB.QueryProofForStore(transfertypes.StoreKey, key, int64(clientState.GetLatestHeight().GetRevisionHeight()))
+ },
+ true,
+ },
+ {
+ "delay time period has passed", func() {
+ delayTimePeriod = uint64(time.Second.Nanoseconds())
+ },
+ true,
+ },
+ {
+ "delay time period has not passed", func() {
+ delayTimePeriod = uint64(time.Hour.Nanoseconds())
+ },
+ false,
+ },
+ {
+ "delay block period has passed", func() {
+ delayBlockPeriod = 1
+ },
+ true,
+ },
+ {
+ "delay block period has not passed", func() {
+ delayBlockPeriod = 1000
+ },
+ false,
+ },
+ {
+ "latest client height < height", func() {
+ proofHeight = testingpath.EndpointA.GetClientState().GetLatestHeight().Increment()
+ }, false,
+ },
+ {
+ "failed to unmarshal merkle path", func() {
+ path = []byte("invalid merkle path")
+ }, false,
+ },
+ {
+ "failed to unmarshal merkle proof", func() {
+ proof = invalidProof
+ }, false,
+ },
+ {
+ "consensus state not found", func() {
+ proofHeight = clienttypes.ZeroHeight()
+ }, false,
+ },
+ {
+ "verify non membership fails as path exists", func() {
+ // change the value being proved
+ key := host.FullClientStateKey(testingpath.EndpointB.ClientID)
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err := commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, proofHeight = suite.chainB.QueryProof(key)
+ }, false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+ suite.SetupTest() // reset
+ testingpath = ibctesting.NewPath(suite.chainA, suite.chainB)
+ testingpath.SetChannelOrdered()
+ suite.coordinator.Setup(testingpath)
+
+ // reset time and block delays to 0, malleate may change to a specific non-zero value.
+ delayTimePeriod = 0
+ delayBlockPeriod = 0
+
+ // create default proof, merklePath, and value which passes
+ // may be overwritten by malleate()
+ key := host.FullClientStateKey("invalid-client-id")
+
+ merklePath := commitmenttypes.NewMerklePath(string(key))
+ merklePath, err := commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath)
+ suite.Require().NoError(err)
+
+ path, err = suite.chainA.Codec.Marshal(&merklePath)
+ suite.Require().NoError(err)
+
+ proof, proofHeight = suite.chainB.QueryProof(key)
+
+ tc.malleate() // make changes as necessary
+
+ clientState := testingpath.EndpointA.GetClientState().(*ibctm.ClientState)
+
+ ctx := suite.chainA.GetContext()
+ store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, testingpath.EndpointA.ClientID)
+
+ err = clientState.VerifyNonMembership(
+ ctx, store, suite.chainA.Codec, proofHeight, delayTimePeriod, delayBlockPeriod,
+ proof, path,
+ )
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+}
diff --git a/modules/light-clients/07-tendermint/types/codec.go b/modules/light-clients/07-tendermint/codec.go
similarity index 87%
rename from modules/light-clients/07-tendermint/types/codec.go
rename to modules/light-clients/07-tendermint/codec.go
index bf25097b4af..5e98991f24e 100644
--- a/modules/light-clients/07-tendermint/types/codec.go
+++ b/modules/light-clients/07-tendermint/codec.go
@@ -1,4 +1,4 @@
-package types
+package tendermint
import (
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
@@ -18,11 +18,11 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
&ConsensusState{},
)
registry.RegisterImplementations(
- (*exported.Header)(nil),
+ (*exported.ClientMessage)(nil),
&Header{},
)
registry.RegisterImplementations(
- (*exported.Misbehaviour)(nil),
+ (*exported.ClientMessage)(nil),
&Misbehaviour{},
)
}
diff --git a/modules/light-clients/07-tendermint/types/consensus_state.go b/modules/light-clients/07-tendermint/consensus_state.go
similarity index 99%
rename from modules/light-clients/07-tendermint/types/consensus_state.go
rename to modules/light-clients/07-tendermint/consensus_state.go
index 7a2a32d2789..ce0e3006afe 100644
--- a/modules/light-clients/07-tendermint/types/consensus_state.go
+++ b/modules/light-clients/07-tendermint/consensus_state.go
@@ -1,4 +1,4 @@
-package types
+package tendermint
import (
"time"
diff --git a/modules/light-clients/07-tendermint/types/consensus_state_test.go b/modules/light-clients/07-tendermint/consensus_state_test.go
similarity index 73%
rename from modules/light-clients/07-tendermint/types/consensus_state_test.go
rename to modules/light-clients/07-tendermint/consensus_state_test.go
index d4b24ddb510..b20b86fed4d 100644
--- a/modules/light-clients/07-tendermint/types/consensus_state_test.go
+++ b/modules/light-clients/07-tendermint/consensus_state_test.go
@@ -1,58 +1,49 @@
-package types_test
+package tendermint_test
import (
"time"
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
)
func (suite *TendermintTestSuite) TestConsensusStateValidateBasic() {
testCases := []struct {
msg string
- consensusState *types.ConsensusState
+ consensusState *ibctm.ConsensusState
expectPass bool
}{
- {
- "success",
- &types.ConsensusState{
+ {"success",
+ &ibctm.ConsensusState{
Timestamp: suite.now,
Root: commitmenttypes.NewMerkleRoot([]byte("app_hash")),
NextValidatorsHash: suite.valsHash,
},
- true,
- },
- {
- "success with sentinel",
- &types.ConsensusState{
+ true},
+ {"success with sentinel",
+ &ibctm.ConsensusState{
Timestamp: suite.now,
- Root: commitmenttypes.NewMerkleRoot([]byte(types.SentinelRoot)),
+ Root: commitmenttypes.NewMerkleRoot([]byte(ibctm.SentinelRoot)),
NextValidatorsHash: suite.valsHash,
},
- true,
- },
- {
- "root is nil",
- &types.ConsensusState{
+ true},
+ {"root is nil",
+ &ibctm.ConsensusState{
Timestamp: suite.now,
Root: commitmenttypes.MerkleRoot{},
NextValidatorsHash: suite.valsHash,
},
- false,
- },
- {
- "root is empty",
- &types.ConsensusState{
+ false},
+ {"root is empty",
+ &ibctm.ConsensusState{
Timestamp: suite.now,
Root: commitmenttypes.MerkleRoot{},
NextValidatorsHash: suite.valsHash,
},
- false,
- },
- {
- "nextvalshash is invalid",
- &types.ConsensusState{
+ false},
+ {"nextvalshash is invalid",
+ &ibctm.ConsensusState{
Timestamp: suite.now,
Root: commitmenttypes.NewMerkleRoot([]byte("app_hash")),
NextValidatorsHash: []byte("hi"),
@@ -60,9 +51,8 @@ func (suite *TendermintTestSuite) TestConsensusStateValidateBasic() {
false,
},
- {
- "timestamp is zero",
- &types.ConsensusState{
+ {"timestamp is zero",
+ &ibctm.ConsensusState{
Timestamp: time.Time{},
Root: commitmenttypes.NewMerkleRoot([]byte("app_hash")),
NextValidatorsHash: suite.valsHash,
diff --git a/modules/light-clients/07-tendermint/types/errors.go b/modules/light-clients/07-tendermint/errors.go
similarity index 98%
rename from modules/light-clients/07-tendermint/types/errors.go
rename to modules/light-clients/07-tendermint/errors.go
index 7b087e41af5..2839beb5291 100644
--- a/modules/light-clients/07-tendermint/types/errors.go
+++ b/modules/light-clients/07-tendermint/errors.go
@@ -1,4 +1,4 @@
-package types
+package tendermint
import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
diff --git a/modules/light-clients/07-tendermint/types/fraction.go b/modules/light-clients/07-tendermint/fraction.go
similarity index 97%
rename from modules/light-clients/07-tendermint/types/fraction.go
rename to modules/light-clients/07-tendermint/fraction.go
index e445f19ba6f..772c6d9c171 100644
--- a/modules/light-clients/07-tendermint/types/fraction.go
+++ b/modules/light-clients/07-tendermint/fraction.go
@@ -1,4 +1,4 @@
-package types
+package tendermint
import (
tmmath "github.com/tendermint/tendermint/libs/math"
diff --git a/modules/light-clients/07-tendermint/types/genesis.go b/modules/light-clients/07-tendermint/genesis.go
similarity index 97%
rename from modules/light-clients/07-tendermint/types/genesis.go
rename to modules/light-clients/07-tendermint/genesis.go
index 8f9a8731a80..ab9159a00a8 100644
--- a/modules/light-clients/07-tendermint/types/genesis.go
+++ b/modules/light-clients/07-tendermint/genesis.go
@@ -1,4 +1,4 @@
-package types
+package tendermint
import (
sdk "github.com/cosmos/cosmos-sdk/types"
diff --git a/modules/light-clients/07-tendermint/types/genesis_test.go b/modules/light-clients/07-tendermint/genesis_test.go
similarity index 77%
rename from modules/light-clients/07-tendermint/types/genesis_test.go
rename to modules/light-clients/07-tendermint/genesis_test.go
index 86a601d1f60..517147a8dc1 100644
--- a/modules/light-clients/07-tendermint/types/genesis_test.go
+++ b/modules/light-clients/07-tendermint/genesis_test.go
@@ -1,10 +1,10 @@
-package types_test
+package tendermint_test
import (
sdk "github.com/cosmos/cosmos-sdk/types"
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -19,26 +19,26 @@ func (suite *TendermintTestSuite) TestExportMetadata() {
clientState := path.EndpointA.GetClientState()
height := clientState.GetLatestHeight()
- initIteration := types.GetIterationKey(clientStore, height)
+ initIteration := ibctm.GetIterationKey(clientStore, height)
suite.Require().NotEqual(0, len(initIteration))
- initProcessedTime, found := types.GetProcessedTime(clientStore, height)
+ initProcessedTime, found := ibctm.GetProcessedTime(clientStore, height)
suite.Require().True(found)
- initProcessedHeight, found := types.GetProcessedHeight(clientStore, height)
+ initProcessedHeight, found := ibctm.GetProcessedHeight(clientStore, height)
suite.Require().True(found)
gm := clientState.ExportMetadata(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID))
suite.Require().NotNil(gm, "client with metadata returned nil exported metadata")
suite.Require().Len(gm, 3, "exported metadata has unexpected length")
- suite.Require().Equal(types.ProcessedHeightKey(height), gm[0].GetKey(), "metadata has unexpected key")
+ suite.Require().Equal(ibctm.ProcessedHeightKey(height), gm[0].GetKey(), "metadata has unexpected key")
actualProcessedHeight, err := clienttypes.ParseHeight(string(gm[0].GetValue()))
suite.Require().NoError(err)
suite.Require().Equal(initProcessedHeight, actualProcessedHeight, "metadata has unexpected value")
- suite.Require().Equal(types.ProcessedTimeKey(height), gm[1].GetKey(), "metadata has unexpected key")
+ suite.Require().Equal(ibctm.ProcessedTimeKey(height), gm[1].GetKey(), "metadata has unexpected key")
suite.Require().Equal(initProcessedTime, sdk.BigEndianToUint64(gm[1].GetValue()), "metadata has unexpected value")
- suite.Require().Equal(types.IterationKey(height), gm[2].GetKey(), "metadata has unexpected key")
+ suite.Require().Equal(ibctm.IterationKey(height), gm[2].GetKey(), "metadata has unexpected key")
suite.Require().Equal(initIteration, gm[2].GetValue(), "metadata has unexpected value")
// test updating client and exporting metadata
@@ -48,11 +48,11 @@ func (suite *TendermintTestSuite) TestExportMetadata() {
clientState = path.EndpointA.GetClientState()
updateHeight := clientState.GetLatestHeight()
- iteration := types.GetIterationKey(clientStore, updateHeight)
+ iteration := ibctm.GetIterationKey(clientStore, updateHeight)
suite.Require().NotEqual(0, len(initIteration))
- processedTime, found := types.GetProcessedTime(clientStore, updateHeight)
+ processedTime, found := ibctm.GetProcessedTime(clientStore, updateHeight)
suite.Require().True(found)
- processedHeight, found := types.GetProcessedHeight(clientStore, updateHeight)
+ processedHeight, found := ibctm.GetProcessedHeight(clientStore, updateHeight)
suite.Require().True(found)
gm = clientState.ExportMetadata(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID))
@@ -63,27 +63,27 @@ func (suite *TendermintTestSuite) TestExportMetadata() {
// initProcessedHeight, initProcessedTime, processedHeight, processedTime, initIteration, iteration
// check init processed height and time
- suite.Require().Equal(types.ProcessedHeightKey(height), gm[0].GetKey(), "metadata has unexpected key")
+ suite.Require().Equal(ibctm.ProcessedHeightKey(height), gm[0].GetKey(), "metadata has unexpected key")
actualProcessedHeight, err = clienttypes.ParseHeight(string(gm[0].GetValue()))
suite.Require().NoError(err)
suite.Require().Equal(initProcessedHeight, actualProcessedHeight, "metadata has unexpected value")
- suite.Require().Equal(types.ProcessedTimeKey(height), gm[1].GetKey(), "metadata has unexpected key")
+ suite.Require().Equal(ibctm.ProcessedTimeKey(height), gm[1].GetKey(), "metadata has unexpected key")
suite.Require().Equal(initProcessedTime, sdk.BigEndianToUint64(gm[1].GetValue()), "metadata has unexpected value")
// check processed height and time after update
- suite.Require().Equal(types.ProcessedHeightKey(updateHeight), gm[2].GetKey(), "metadata has unexpected key")
+ suite.Require().Equal(ibctm.ProcessedHeightKey(updateHeight), gm[2].GetKey(), "metadata has unexpected key")
actualProcessedHeight, err = clienttypes.ParseHeight(string(gm[2].GetValue()))
suite.Require().NoError(err)
suite.Require().Equal(processedHeight, actualProcessedHeight, "metadata has unexpected value")
- suite.Require().Equal(types.ProcessedTimeKey(updateHeight), gm[3].GetKey(), "metadata has unexpected key")
+ suite.Require().Equal(ibctm.ProcessedTimeKey(updateHeight), gm[3].GetKey(), "metadata has unexpected key")
suite.Require().Equal(processedTime, sdk.BigEndianToUint64(gm[3].GetValue()), "metadata has unexpected value")
// check iteration keys
- suite.Require().Equal(types.IterationKey(height), gm[4].GetKey(), "metadata has unexpected key")
+ suite.Require().Equal(ibctm.IterationKey(height), gm[4].GetKey(), "metadata has unexpected key")
suite.Require().Equal(initIteration, gm[4].GetValue(), "metadata has unexpected value")
- suite.Require().Equal(types.IterationKey(updateHeight), gm[5].GetKey(), "metadata has unexpected key")
+ suite.Require().Equal(ibctm.IterationKey(updateHeight), gm[5].GetKey(), "metadata has unexpected key")
suite.Require().Equal(iteration, gm[5].GetValue(), "metadata has unexpected value")
}
diff --git a/modules/light-clients/07-tendermint/types/header.go b/modules/light-clients/07-tendermint/header.go
similarity index 97%
rename from modules/light-clients/07-tendermint/types/header.go
rename to modules/light-clients/07-tendermint/header.go
index 2da01504710..9fc00198245 100644
--- a/modules/light-clients/07-tendermint/types/header.go
+++ b/modules/light-clients/07-tendermint/header.go
@@ -1,4 +1,4 @@
-package types
+package tendermint
import (
"bytes"
@@ -12,7 +12,7 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/exported"
)
-var _ exported.Header = &Header{}
+var _ exported.ClientMessage = &Header{}
// ConsensusState returns the updated consensus state associated with the header
func (h Header) ConsensusState() *ConsensusState {
diff --git a/modules/light-clients/07-tendermint/types/header_test.go b/modules/light-clients/07-tendermint/header_test.go
similarity index 94%
rename from modules/light-clients/07-tendermint/types/header_test.go
rename to modules/light-clients/07-tendermint/header_test.go
index 933ae8d9d70..8e916177877 100644
--- a/modules/light-clients/07-tendermint/types/header_test.go
+++ b/modules/light-clients/07-tendermint/header_test.go
@@ -1,4 +1,4 @@
-package types_test
+package tendermint_test
import (
"time"
@@ -7,7 +7,7 @@ import (
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
)
func (suite *TendermintTestSuite) TestGetHeight() {
@@ -21,7 +21,7 @@ func (suite *TendermintTestSuite) TestGetTime() {
}
func (suite *TendermintTestSuite) TestHeaderValidateBasic() {
- var header *types.Header
+ var header *ibctm.Header
testCases := []struct {
name string
malleate func()
diff --git a/modules/light-clients/07-tendermint/types/misbehaviour.go b/modules/light-clients/07-tendermint/misbehaviour.go
similarity index 95%
rename from modules/light-clients/07-tendermint/types/misbehaviour.go
rename to modules/light-clients/07-tendermint/misbehaviour.go
index a15699767f3..3fc237621ab 100644
--- a/modules/light-clients/07-tendermint/types/misbehaviour.go
+++ b/modules/light-clients/07-tendermint/misbehaviour.go
@@ -1,4 +1,4 @@
-package types
+package tendermint
import (
"time"
@@ -12,7 +12,7 @@ import (
"github.com/cosmos/ibc-go/v5/modules/core/exported"
)
-var _ exported.Misbehaviour = &Misbehaviour{}
+var _ exported.ClientMessage = &Misbehaviour{}
// FrozenHeight is same for all misbehaviour
var FrozenHeight = clienttypes.NewHeight(0, 1)
@@ -31,11 +31,6 @@ func (misbehaviour Misbehaviour) ClientType() string {
return exported.Tendermint
}
-// GetClientID returns the ID of the client that committed a misbehaviour.
-func (misbehaviour Misbehaviour) GetClientID() string {
- return misbehaviour.ClientId
-}
-
// GetTime returns the timestamp at which misbehaviour occurred. It uses the
// maximum value from both headers to prevent producing an invalid header outside
// of the misbehaviour age range.
@@ -130,3 +125,9 @@ func validCommit(chainID string, blockID tmtypes.BlockID, commit *tmproto.Commit
return nil
}
+
+// TODO: Remove GetHeight()
+// GetHeight implements the curret exported.Header interface, to be updated
+func (misbehaviour Misbehaviour) GetHeight() exported.Height {
+ return nil
+}
diff --git a/modules/light-clients/07-tendermint/types/misbehaviour_handle.go b/modules/light-clients/07-tendermint/misbehaviour_handle.go
similarity index 61%
rename from modules/light-clients/07-tendermint/types/misbehaviour_handle.go
rename to modules/light-clients/07-tendermint/misbehaviour_handle.go
index 17883824cb6..0417dd4da17 100644
--- a/modules/light-clients/07-tendermint/types/misbehaviour_handle.go
+++ b/modules/light-clients/07-tendermint/misbehaviour_handle.go
@@ -1,4 +1,4 @@
-package types
+package tendermint
import (
"bytes"
@@ -10,10 +10,9 @@ import (
tmtypes "github.com/tendermint/tendermint/types"
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
)
-// CheckMisbehaviourAndUpdateState determines whether or not two conflicting
+// verifyMisbehaviour determines whether or not two conflicting
// headers at the same height would have convinced the light client.
//
// NOTE: consensusState1 is the trusted consensus state that corresponds to the TrustedHeight
@@ -21,57 +20,42 @@ import (
// Similarly, consensusState2 is the trusted consensus state that corresponds
// to misbehaviour.Header2
// Misbehaviour sets frozen height to {0, 1} since it is only used as a boolean value (zero or non-zero).
-func (cs ClientState) CheckMisbehaviourAndUpdateState(
- ctx sdk.Context,
- cdc codec.BinaryCodec,
- clientStore sdk.KVStore,
- misbehaviour exported.Misbehaviour,
-) (exported.ClientState, error) {
- tmMisbehaviour, ok := misbehaviour.(*Misbehaviour)
- if !ok {
- return nil, sdkerrors.Wrapf(clienttypes.ErrInvalidClientType, "expected type %T, got %T", misbehaviour, &Misbehaviour{})
- }
-
- // The status of the client is checked in 02-client
-
+func (cs *ClientState) verifyMisbehaviour(ctx sdk.Context, clientStore sdk.KVStore, cdc codec.BinaryCodec, misbehaviour *Misbehaviour) error {
// if heights are equal check that this is valid misbehaviour of a fork
// otherwise if heights are unequal check that this is valid misbehavior of BFT time violation
- if tmMisbehaviour.Header1.GetHeight().EQ(tmMisbehaviour.Header2.GetHeight()) {
- blockID1, err := tmtypes.BlockIDFromProto(&tmMisbehaviour.Header1.SignedHeader.Commit.BlockID)
+ if misbehaviour.Header1.GetHeight().EQ(misbehaviour.Header2.GetHeight()) {
+ blockID1, err := tmtypes.BlockIDFromProto(&misbehaviour.Header1.SignedHeader.Commit.BlockID)
if err != nil {
- return nil, sdkerrors.Wrap(err, "invalid block ID from header 1 in misbehaviour")
+ return sdkerrors.Wrap(err, "invalid block ID from header 1 in misbehaviour")
}
- blockID2, err := tmtypes.BlockIDFromProto(&tmMisbehaviour.Header2.SignedHeader.Commit.BlockID)
+
+ blockID2, err := tmtypes.BlockIDFromProto(&misbehaviour.Header2.SignedHeader.Commit.BlockID)
if err != nil {
- return nil, sdkerrors.Wrap(err, "invalid block ID from header 2 in misbehaviour")
+ return sdkerrors.Wrap(err, "invalid block ID from header 2 in misbehaviour")
}
// Ensure that Commit Hashes are different
if bytes.Equal(blockID1.Hash, blockID2.Hash) {
- return nil, sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "headers block hashes are equal")
+ return sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "headers block hashes are equal")
}
- } else if tmMisbehaviour.Header1.SignedHeader.Header.Time.After(tmMisbehaviour.Header2.SignedHeader.Header.Time) {
+ } else if misbehaviour.Header1.SignedHeader.Header.Time.After(misbehaviour.Header2.SignedHeader.Header.Time) {
// Header1 is at greater height than Header2, therefore Header1 time must be less than or equal to
// Header2 time in order to be valid misbehaviour (violation of monotonic time).
- return nil, sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "headers are not at same height and are monotonically increasing")
+ return sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "headers are not at same height and are monotonically increasing")
}
// Regardless of the type of misbehaviour, ensure that both headers are valid and would have been accepted by light-client
// Retrieve trusted consensus states for each Header in misbehaviour
- // and unmarshal from clientStore
-
- // Get consensus bytes from clientStore
- tmConsensusState1, err := GetConsensusState(clientStore, cdc, tmMisbehaviour.Header1.TrustedHeight)
- if err != nil {
- return nil, sdkerrors.Wrapf(err, "could not get trusted consensus state from clientStore for Header1 at TrustedHeight: %s", tmMisbehaviour.Header1)
+ tmConsensusState1, found := GetConsensusState(clientStore, cdc, misbehaviour.Header1.TrustedHeight)
+ if !found {
+ return sdkerrors.Wrapf(clienttypes.ErrConsensusStateNotFound, "could not get trusted consensus state from clientStore for Header1 at TrustedHeight: %s", misbehaviour.Header1.TrustedHeight)
}
- // Get consensus bytes from clientStore
- tmConsensusState2, err := GetConsensusState(clientStore, cdc, tmMisbehaviour.Header2.TrustedHeight)
- if err != nil {
- return nil, sdkerrors.Wrapf(err, "could not get trusted consensus state from clientStore for Header2 at TrustedHeight: %s", tmMisbehaviour.Header2)
+ tmConsensusState2, found := GetConsensusState(clientStore, cdc, misbehaviour.Header2.TrustedHeight)
+ if !found {
+ return sdkerrors.Wrapf(clienttypes.ErrConsensusStateNotFound, "could not get trusted consensus state from clientStore for Header2 at TrustedHeight: %s", misbehaviour.Header2.TrustedHeight)
}
// Check the validity of the two conflicting headers against their respective
@@ -80,19 +64,17 @@ func (cs ClientState) CheckMisbehaviourAndUpdateState(
// misbehaviour.ValidateBasic by the client keeper and msg.ValidateBasic
// by the base application.
if err := checkMisbehaviourHeader(
- &cs, tmConsensusState1, tmMisbehaviour.Header1, ctx.BlockTime(),
+ cs, tmConsensusState1, misbehaviour.Header1, ctx.BlockTime(),
); err != nil {
- return nil, sdkerrors.Wrap(err, "verifying Header1 in Misbehaviour failed")
+ return sdkerrors.Wrap(err, "verifying Header1 in Misbehaviour failed")
}
if err := checkMisbehaviourHeader(
- &cs, tmConsensusState2, tmMisbehaviour.Header2, ctx.BlockTime(),
+ cs, tmConsensusState2, misbehaviour.Header2, ctx.BlockTime(),
); err != nil {
- return nil, sdkerrors.Wrap(err, "verifying Header2 in Misbehaviour failed")
+ return sdkerrors.Wrap(err, "verifying Header2 in Misbehaviour failed")
}
- cs.FrozenHeight = FrozenHeight
-
- return &cs, nil
+ return nil
}
// checkMisbehaviourHeader checks that a Header in Misbehaviour is valid misbehaviour given
@@ -127,6 +109,8 @@ func checkMisbehaviourHeader(
chainID := clientState.GetChainID()
// If chainID is in revision format, then set revision number of chainID with the revision number
// of the misbehaviour header
+ // NOTE: misbehaviour verification is not supported for chains which upgrade to a new chainID without
+ // strictly following the chainID revision format
if clienttypes.IsRevisionFormat(chainID) {
chainID, _ = clienttypes.SetRevisionNumber(chainID, header.GetHeight().GetRevisionNumber())
}
diff --git a/modules/light-clients/07-tendermint/misbehaviour_handle_test.go b/modules/light-clients/07-tendermint/misbehaviour_handle_test.go
new file mode 100644
index 00000000000..7b42d6ab19a
--- /dev/null
+++ b/modules/light-clients/07-tendermint/misbehaviour_handle_test.go
@@ -0,0 +1,717 @@
+package tendermint_test
+
+import (
+ "fmt"
+ "strings"
+ "time"
+
+ tmtypes "github.com/tendermint/tendermint/types"
+
+ clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
+ "github.com/cosmos/ibc-go/v5/modules/core/exported"
+ smtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
+ ibctesting "github.com/cosmos/ibc-go/v5/testing"
+ ibctestingmock "github.com/cosmos/ibc-go/v5/testing/mock"
+)
+
+func (suite *TendermintTestSuite) TestVerifyMisbehaviour() {
+ // Setup different validators and signers for testing different types of updates
+ altPrivVal := ibctestingmock.NewPV()
+ altPubKey, err := altPrivVal.GetPubKey()
+ suite.Require().NoError(err)
+
+ // create modified heights to use for test-cases
+ altVal := tmtypes.NewValidator(altPubKey, 100)
+
+ // Create alternative validator set with only altVal, invalid update (too much change in valSet)
+ altValSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{altVal})
+ altSigners := getAltSigners(altVal, altPrivVal)
+
+ var (
+ path *ibctesting.Path
+ misbehaviour exported.ClientMessage
+ )
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "valid fork misbehaviour", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ },
+ true,
+ },
+ {
+ "valid time misbehaviour", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+3, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ },
+ true,
+ },
+ {
+ "valid time misbehaviour, header 1 time stricly less than header 2 time", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+3, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Hour), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ },
+ true,
+ },
+ {
+ "valid misbehavior at height greater than last consensusState", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+1, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+1, trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ }, true,
+ },
+ {
+ "valid misbehaviour with different trusted heights", func() {
+ trustedHeight1 := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals1, found := suite.chainB.GetValsAtHeight(int64(trustedHeight1.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ trustedHeight2 := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals2, found := suite.chainB.GetValsAtHeight(int64(trustedHeight2.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight1, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals1, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight2, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals2, suite.chainB.Signers),
+ }
+
+ },
+ true,
+ },
+ {
+
+ "valid misbehaviour at a previous revision", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+
+ // increment revision number
+ err = path.EndpointB.UpgradeChain()
+ suite.Require().NoError(err)
+ },
+ true,
+ },
+ {
+ "valid misbehaviour at a future revision", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ futureRevision := fmt.Sprintf("%s-%d", strings.TrimSuffix(suite.chainB.ChainID, fmt.Sprintf("-%d", clienttypes.ParseChainID(suite.chainB.ChainID))), height.GetRevisionNumber()+1)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(futureRevision, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(futureRevision, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ },
+ true,
+ },
+ {
+ "valid misbehaviour with trusted heights at a previous revision", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ // increment revision of chainID
+ err = path.EndpointB.UpgradeChain()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ },
+ true,
+ },
+ {
+ "consensus state's valset hash different from misbehaviour should still pass", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ // Create bothValSet with both suite validator and altVal
+ bothValSet := tmtypes.NewValidatorSet(append(suite.chainB.Vals.Validators, altValSet.Proposer))
+ bothSigners := suite.chainB.Signers
+ bothSigners[altValSet.Proposer.Address.String()] = altPrivVal
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), bothValSet, suite.chainB.NextVals, trustedVals, bothSigners),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, bothValSet, suite.chainB.NextVals, trustedVals, bothSigners),
+ }
+ }, true,
+ },
+ {
+ "invalid fork misbehaviour: identical headers", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviourHeader := suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers)
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: misbehaviourHeader,
+ Header2: misbehaviourHeader,
+ }
+ }, false,
+ },
+ {
+ "invalid time misbehaviour: monotonically increasing time", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+3, trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ }, false,
+ },
+ {
+ "invalid misbehaviour: misbehaviour from different chain", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader("evmos", int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader("evmos", int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+
+ }, false,
+ },
+ {
+ "misbehaviour trusted validators does not match validator hash in trusted consensus state", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, altValSet, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, altValSet, suite.chainB.Signers),
+ }
+ }, false,
+ },
+ {
+ "trusted consensus state does not exist", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight.Increment().(clienttypes.Height), suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ }, false,
+ },
+ {
+ "invalid tendermint misbehaviour", func() {
+ misbehaviour = &smtypes.Misbehaviour{}
+ }, false,
+ },
+ {
+ "trusting period expired", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ suite.chainA.ExpireClient(path.EndpointA.ClientConfig.(*ibctesting.TendermintConfig).TrustingPeriod)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ }, false,
+ },
+ {
+ "header 1 valset has too much change", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), altValSet, suite.chainB.NextVals, trustedVals, altSigners),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ }, false,
+ },
+ {
+ "header 2 valset has too much change", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, altValSet, suite.chainB.NextVals, trustedVals, altSigners),
+ }
+ }, false,
+ },
+ {
+ "both header 1 and header 2 valsets have too much change", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), altValSet, suite.chainB.NextVals, trustedVals, altSigners),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, altValSet, suite.chainB.NextVals, trustedVals, altSigners),
+ }
+ }, false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+ suite.SetupTest()
+ path = ibctesting.NewPath(suite.chainA, suite.chainB)
+
+ err := path.EndpointA.CreateClient()
+ suite.Require().NoError(err)
+
+ tc.malleate()
+
+ clientState := path.EndpointA.GetClientState()
+ clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
+
+ err = clientState.VerifyClientMessage(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, misbehaviour)
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+}
+
+// test both fork and time misbehaviour for chainIDs not in the revision format
+// this function is separate as it must use a global variable in the testing package
+// to initialize chains not in the revision format
+func (suite *TendermintTestSuite) TestVerifyMisbehaviourNonRevisionChainID() {
+ // NOTE: chains set to non revision format
+ ibctesting.ChainIDSuffix = ""
+
+ // Setup different validators and signers for testing different types of updates
+ altPrivVal := ibctestingmock.NewPV()
+ altPubKey, err := altPrivVal.GetPubKey()
+ suite.Require().NoError(err)
+
+ // create modified heights to use for test-cases
+ altVal := tmtypes.NewValidator(altPubKey, 100)
+
+ // Create alternative validator set with only altVal, invalid update (too much change in valSet)
+ altValSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{altVal})
+ altSigners := getAltSigners(altVal, altPrivVal)
+
+ var (
+ path *ibctesting.Path
+ misbehaviour exported.ClientMessage
+ )
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "valid fork misbehaviour", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ },
+ true,
+ },
+ {
+ "valid time misbehaviour", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+3, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ },
+ true,
+ },
+ {
+ "valid time misbehaviour, header 1 time stricly less than header 2 time", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+3, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Hour), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ },
+ true,
+ },
+ {
+ "valid misbehavior at height greater than last consensusState", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+1, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+1, trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ }, true,
+ },
+ {
+ "valid misbehaviour with different trusted heights", func() {
+ trustedHeight1 := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals1, found := suite.chainB.GetValsAtHeight(int64(trustedHeight1.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ trustedHeight2 := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals2, found := suite.chainB.GetValsAtHeight(int64(trustedHeight2.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight1, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals1, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight2, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals2, suite.chainB.Signers),
+ }
+
+ },
+ true,
+ },
+ {
+ "consensus state's valset hash different from misbehaviour should still pass", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ // Create bothValSet with both suite validator and altVal
+ bothValSet := tmtypes.NewValidatorSet(append(suite.chainB.Vals.Validators, altValSet.Proposer))
+ bothSigners := suite.chainB.Signers
+ bothSigners[altValSet.Proposer.Address.String()] = altPrivVal
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), bothValSet, suite.chainB.NextVals, trustedVals, bothSigners),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, bothValSet, suite.chainB.NextVals, trustedVals, bothSigners),
+ }
+ }, true,
+ },
+ {
+ "invalid fork misbehaviour: identical headers", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviourHeader := suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers)
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: misbehaviourHeader,
+ Header2: misbehaviourHeader,
+ }
+ }, false,
+ },
+ {
+ "invalid time misbehaviour: monotonically increasing time", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+3, trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ }, false,
+ },
+ {
+ "invalid misbehaviour: misbehaviour from different chain", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader("evmos", int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader("evmos", int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+
+ }, false,
+ },
+ {
+ "misbehaviour trusted validators does not match validator hash in trusted consensus state", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, altValSet, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, altValSet, suite.chainB.Signers),
+ }
+ }, false,
+ },
+ {
+ "trusted consensus state does not exist", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight.Increment().(clienttypes.Height), suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ }, false,
+ },
+ {
+ "invalid tendermint misbehaviour", func() {
+ misbehaviour = &smtypes.Misbehaviour{}
+ }, false,
+ },
+ {
+ "trusting period expired", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ suite.chainA.ExpireClient(path.EndpointA.ClientConfig.(*ibctesting.TendermintConfig).TrustingPeriod)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ }, false,
+ },
+ {
+ "header 1 valset has too much change", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), altValSet, suite.chainB.NextVals, trustedVals, altSigners),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ }
+ }, false,
+ },
+ {
+ "header 2 valset has too much change", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, altValSet, suite.chainB.NextVals, trustedVals, altSigners),
+ }
+ }, false,
+ },
+ {
+ "both header 1 and header 2 valsets have too much change", func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ height := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ misbehaviour = &ibctm.Misbehaviour{
+ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time.Add(time.Minute), altValSet, suite.chainB.NextVals, trustedVals, altSigners),
+ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, altValSet, suite.chainB.NextVals, trustedVals, altSigners),
+ }
+ }, false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+ suite.SetupTest()
+ path = ibctesting.NewPath(suite.chainA, suite.chainB)
+
+ err := path.EndpointA.CreateClient()
+ suite.Require().NoError(err)
+
+ tc.malleate()
+
+ clientState := path.EndpointA.GetClientState()
+ clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
+
+ err = clientState.VerifyClientMessage(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, misbehaviour)
+
+ if tc.expPass {
+ suite.Require().NoError(err)
+ } else {
+ suite.Require().Error(err)
+ }
+ })
+ }
+
+ // NOTE: reset chain creation to revision format
+ ibctesting.ChainIDSuffix = "-1"
+}
diff --git a/modules/light-clients/07-tendermint/types/misbehaviour_test.go b/modules/light-clients/07-tendermint/misbehaviour_test.go
similarity index 82%
rename from modules/light-clients/07-tendermint/types/misbehaviour_test.go
rename to modules/light-clients/07-tendermint/misbehaviour_test.go
index 0731cd25489..979b5d1c203 100644
--- a/modules/light-clients/07-tendermint/types/misbehaviour_test.go
+++ b/modules/light-clients/07-tendermint/misbehaviour_test.go
@@ -1,4 +1,4 @@
-package types_test
+package tendermint_test
import (
"time"
@@ -9,7 +9,7 @@ import (
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
ibctestingmock "github.com/cosmos/ibc-go/v5/testing/mock"
)
@@ -17,14 +17,13 @@ import (
func (suite *TendermintTestSuite) TestMisbehaviour() {
heightMinus1 := clienttypes.NewHeight(0, height.RevisionHeight-1)
- misbehaviour := &types.Misbehaviour{
+ misbehaviour := &ibctm.Misbehaviour{
Header1: suite.header,
Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, suite.valSet, suite.valSet, suite.valSet, suite.signers),
ClientId: clientID,
}
suite.Require().Equal(exported.Tendermint, misbehaviour.ClientType())
- suite.Require().Equal(clientID, misbehaviour.GetClientID())
}
func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
@@ -48,130 +47,130 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
testCases := []struct {
name string
- misbehaviour *types.Misbehaviour
- malleateMisbehaviour func(misbehaviour *types.Misbehaviour) error
+ misbehaviour *ibctm.Misbehaviour
+ malleateMisbehaviour func(misbehaviour *ibctm.Misbehaviour) error
expPass bool
}{
{
"valid fork misbehaviour, two headers at same height have different time",
- &types.Misbehaviour{
+ &ibctm.Misbehaviour{
Header1: suite.header,
Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now.Add(time.Minute), suite.valSet, suite.valSet, suite.valSet, suite.signers),
ClientId: clientID,
},
- func(misbehaviour *types.Misbehaviour) error { return nil },
+ func(misbehaviour *ibctm.Misbehaviour) error { return nil },
true,
},
{
"valid time misbehaviour, both headers at different heights are at same time",
- &types.Misbehaviour{
+ &ibctm.Misbehaviour{
Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+5), heightMinus1, suite.now, suite.valSet, suite.valSet, suite.valSet, suite.signers),
Header2: suite.header,
ClientId: clientID,
},
- func(misbehaviour *types.Misbehaviour) error { return nil },
+ func(misbehaviour *ibctm.Misbehaviour) error { return nil },
true,
},
{
"misbehaviour Header1 is nil",
- types.NewMisbehaviour(clientID, nil, suite.header),
- func(m *types.Misbehaviour) error { return nil },
+ ibctm.NewMisbehaviour(clientID, nil, suite.header),
+ func(m *ibctm.Misbehaviour) error { return nil },
false,
},
{
"misbehaviour Header2 is nil",
- types.NewMisbehaviour(clientID, suite.header, nil),
- func(m *types.Misbehaviour) error { return nil },
+ ibctm.NewMisbehaviour(clientID, suite.header, nil),
+ func(m *ibctm.Misbehaviour) error { return nil },
false,
},
{
"valid misbehaviour with different trusted headers",
- &types.Misbehaviour{
+ &ibctm.Misbehaviour{
Header1: suite.header,
Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), clienttypes.NewHeight(0, height.RevisionHeight-3), suite.now.Add(time.Minute), suite.valSet, suite.valSet, bothValSet, suite.signers),
ClientId: clientID,
},
- func(misbehaviour *types.Misbehaviour) error { return nil },
+ func(misbehaviour *ibctm.Misbehaviour) error { return nil },
true,
},
{
"trusted height is 0 in Header1",
- &types.Misbehaviour{
+ &ibctm.Misbehaviour{
Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), clienttypes.ZeroHeight(), suite.now.Add(time.Minute), suite.valSet, suite.valSet, suite.valSet, suite.signers),
Header2: suite.header,
ClientId: clientID,
},
- func(misbehaviour *types.Misbehaviour) error { return nil },
+ func(misbehaviour *ibctm.Misbehaviour) error { return nil },
false,
},
{
"trusted height is 0 in Header2",
- &types.Misbehaviour{
+ &ibctm.Misbehaviour{
Header1: suite.header,
Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), clienttypes.ZeroHeight(), suite.now.Add(time.Minute), suite.valSet, suite.valSet, suite.valSet, suite.signers),
ClientId: clientID,
},
- func(misbehaviour *types.Misbehaviour) error { return nil },
+ func(misbehaviour *ibctm.Misbehaviour) error { return nil },
false,
},
{
"trusted valset is nil in Header1",
- &types.Misbehaviour{
+ &ibctm.Misbehaviour{
Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now.Add(time.Minute), suite.valSet, suite.valSet, nil, suite.signers),
Header2: suite.header,
ClientId: clientID,
},
- func(misbehaviour *types.Misbehaviour) error { return nil },
+ func(misbehaviour *ibctm.Misbehaviour) error { return nil },
false,
},
{
"trusted valset is nil in Header2",
- &types.Misbehaviour{
+ &ibctm.Misbehaviour{
Header1: suite.header,
Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now.Add(time.Minute), suite.valSet, suite.valSet, nil, suite.signers),
ClientId: clientID,
},
- func(misbehaviour *types.Misbehaviour) error { return nil },
+ func(misbehaviour *ibctm.Misbehaviour) error { return nil },
false,
},
{
"invalid client ID ",
- &types.Misbehaviour{
+ &ibctm.Misbehaviour{
Header1: suite.header,
Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, suite.valSet, suite.valSet, suite.valSet, suite.signers),
ClientId: "GAIA",
},
- func(misbehaviour *types.Misbehaviour) error { return nil },
+ func(misbehaviour *ibctm.Misbehaviour) error { return nil },
false,
},
{
"chainIDs do not match",
- &types.Misbehaviour{
+ &ibctm.Misbehaviour{
Header1: suite.header,
Header2: suite.chainA.CreateTMClientHeader("ethermint", int64(height.RevisionHeight), heightMinus1, suite.now, suite.valSet, suite.valSet, suite.valSet, suite.signers),
ClientId: clientID,
},
- func(misbehaviour *types.Misbehaviour) error { return nil },
+ func(misbehaviour *ibctm.Misbehaviour) error { return nil },
false,
},
{
"header2 height is greater",
- &types.Misbehaviour{
+ &ibctm.Misbehaviour{
Header1: suite.header,
Header2: suite.chainA.CreateTMClientHeader(chainID, 6, clienttypes.NewHeight(0, height.RevisionHeight+1), suite.now, suite.valSet, suite.valSet, suite.valSet, suite.signers),
ClientId: clientID,
},
- func(misbehaviour *types.Misbehaviour) error { return nil },
+ func(misbehaviour *ibctm.Misbehaviour) error { return nil },
false,
},
{
"header 1 doesn't have 2/3 majority",
- &types.Misbehaviour{
+ &ibctm.Misbehaviour{
Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, bothValSet, bothValSet, suite.valSet, bothSigners),
Header2: suite.header,
ClientId: clientID,
},
- func(misbehaviour *types.Misbehaviour) error {
+ func(misbehaviour *ibctm.Misbehaviour) error {
// voteSet contains only altVal which is less than 2/3 of total power (height/1height)
wrongVoteSet := tmtypes.NewVoteSet(chainID, int64(misbehaviour.Header1.GetHeight().GetRevisionHeight()), 1, tmproto.PrecommitType, altValSet)
blockID, err := tmtypes.BlockIDFromProto(&misbehaviour.Header1.Commit.BlockID)
@@ -187,12 +186,12 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
},
{
"header 2 doesn't have 2/3 majority",
- &types.Misbehaviour{
+ &ibctm.Misbehaviour{
Header1: suite.header,
Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, bothValSet, bothValSet, suite.valSet, bothSigners),
ClientId: clientID,
},
- func(misbehaviour *types.Misbehaviour) error {
+ func(misbehaviour *ibctm.Misbehaviour) error {
// voteSet contains only altVal which is less than 2/3 of total power (height/1height)
wrongVoteSet := tmtypes.NewVoteSet(chainID, int64(misbehaviour.Header2.GetHeight().GetRevisionHeight()), 1, tmproto.PrecommitType, altValSet)
blockID, err := tmtypes.BlockIDFromProto(&misbehaviour.Header2.Commit.BlockID)
@@ -208,12 +207,12 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
},
{
"validators sign off on wrong commit",
- &types.Misbehaviour{
+ &ibctm.Misbehaviour{
Header1: suite.header,
Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, bothValSet, bothValSet, suite.valSet, bothSigners),
ClientId: clientID,
},
- func(misbehaviour *types.Misbehaviour) error {
+ func(misbehaviour *ibctm.Misbehaviour) error {
tmBlockID := ibctesting.MakeBlockID(tmhash.Sum([]byte("other_hash")), 3, tmhash.Sum([]byte("other_partset")))
misbehaviour.Header2.Commit.BlockID = tmBlockID.ToProto()
return nil
diff --git a/modules/light-clients/07-tendermint/module.go b/modules/light-clients/07-tendermint/module.go
index 532f3158f44..935bf34cafd 100644
--- a/modules/light-clients/07-tendermint/module.go
+++ b/modules/light-clients/07-tendermint/module.go
@@ -1,10 +1,6 @@
package tendermint
-import (
- "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
-)
-
// Name returns the IBC client name
func Name() string {
- return types.SubModuleName
+ return SubModuleName
}
diff --git a/modules/light-clients/07-tendermint/types/proposal_handle.go b/modules/light-clients/07-tendermint/proposal_handle.go
similarity index 78%
rename from modules/light-clients/07-tendermint/types/proposal_handle.go
rename to modules/light-clients/07-tendermint/proposal_handle.go
index 9a75c5f9b9f..39700ed3418 100644
--- a/modules/light-clients/07-tendermint/types/proposal_handle.go
+++ b/modules/light-clients/07-tendermint/proposal_handle.go
@@ -1,4 +1,4 @@
-package types
+package tendermint
import (
"reflect"
@@ -27,16 +27,14 @@ import (
func (cs ClientState) CheckSubstituteAndUpdateState(
ctx sdk.Context, cdc codec.BinaryCodec, subjectClientStore,
substituteClientStore sdk.KVStore, substituteClient exported.ClientState,
-) (exported.ClientState, error) {
+) error {
substituteClientState, ok := substituteClient.(*ClientState)
if !ok {
- return nil, sdkerrors.Wrapf(
- clienttypes.ErrInvalidClient, "expected type %T, got %T", &ClientState{}, substituteClient,
- )
+ return sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "expected type %T, got %T", &ClientState{}, substituteClient)
}
if !IsMatchingClientState(cs, *substituteClientState) {
- return nil, sdkerrors.Wrap(clienttypes.ErrInvalidSubstitute, "subject client state does not match substitute client state")
+ return sdkerrors.Wrap(clienttypes.ErrInvalidSubstitute, "subject client state does not match substitute client state")
}
if cs.Status(ctx, subjectClientStore, cdc) == exported.Frozen {
@@ -48,22 +46,22 @@ func (cs ClientState) CheckSubstituteAndUpdateState(
// starting from initial height and ending on the latest height (inclusive)
height := substituteClientState.GetLatestHeight()
- consensusState, err := GetConsensusState(substituteClientStore, cdc, height)
- if err != nil {
- return nil, sdkerrors.Wrap(err, "unable to retrieve latest consensus state for substitute client")
+ consensusState, found := GetConsensusState(substituteClientStore, cdc, height)
+ if !found {
+ return sdkerrors.Wrap(clienttypes.ErrConsensusStateNotFound, "unable to retrieve latest consensus state for substitute client")
}
- SetConsensusState(subjectClientStore, cdc, consensusState, height)
+ setConsensusState(subjectClientStore, cdc, consensusState, height)
// set metadata stored for the substitute consensus state
processedHeight, found := GetProcessedHeight(substituteClientStore, height)
if !found {
- return nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "unable to retrieve processed height for substitute client latest height")
+ return sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "unable to retrieve processed height for substitute client latest height")
}
processedTime, found := GetProcessedTime(substituteClientStore, height)
if !found {
- return nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "unable to retrieve processed time for substitute client latest height")
+ return sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "unable to retrieve processed time for substitute client latest height")
}
setConsensusMetadataWithValues(subjectClientStore, height, processedHeight, processedTime)
@@ -76,8 +74,9 @@ func (cs ClientState) CheckSubstituteAndUpdateState(
// no validation is necessary since the substitute is verified to be Active
// in 02-client.
+ setClientState(subjectClientStore, cdc, &cs)
- return &cs, nil
+ return nil
}
// IsMatchingClientState returns true if all the client state parameters match
diff --git a/modules/light-clients/07-tendermint/types/proposal_handle_test.go b/modules/light-clients/07-tendermint/proposal_handle_test.go
similarity index 83%
rename from modules/light-clients/07-tendermint/types/proposal_handle_test.go
rename to modules/light-clients/07-tendermint/proposal_handle_test.go
index 62e65e05053..3d7e5e3e688 100644
--- a/modules/light-clients/07-tendermint/types/proposal_handle_test.go
+++ b/modules/light-clients/07-tendermint/proposal_handle_test.go
@@ -1,11 +1,11 @@
-package types_test
+package tendermint_test
import (
"time"
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -28,7 +28,7 @@ func (suite *TendermintTestSuite) TestCheckSubstituteUpdateStateBasic() {
{
"non-matching substitute", func() {
suite.coordinator.SetupClients(substitutePath)
- substituteClientState, ok := suite.chainA.GetClientState(substitutePath.EndpointA.ClientID).(*types.ClientState)
+ substituteClientState, ok := suite.chainA.GetClientState(substitutePath.EndpointA.ClientID).(*ibctm.ClientState)
suite.Require().True(ok)
// change trusting period so that test should fail
substituteClientState.TrustingPeriod = time.Hour * 24 * 7
@@ -48,7 +48,7 @@ func (suite *TendermintTestSuite) TestCheckSubstituteUpdateStateBasic() {
substitutePath = ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupClients(subjectPath)
- subjectClientState := suite.chainA.GetClientState(subjectPath.EndpointA.ClientID).(*types.ClientState)
+ subjectClientState := suite.chainA.GetClientState(subjectPath.EndpointA.ClientID).(*ibctm.ClientState)
// expire subject client
suite.coordinator.IncrementTimeBy(subjectClientState.TrustingPeriod)
@@ -59,9 +59,8 @@ func (suite *TendermintTestSuite) TestCheckSubstituteUpdateStateBasic() {
subjectClientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), subjectPath.EndpointA.ClientID)
substituteClientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), substitutePath.EndpointA.ClientID)
- updatedClient, err := subjectClientState.CheckSubstituteAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), subjectClientStore, substituteClientStore, substituteClientState)
+ err := subjectClientState.CheckSubstituteAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), subjectClientStore, substituteClientStore, substituteClientState)
suite.Require().Error(err)
- suite.Require().Nil(updatedClient)
})
}
}
@@ -120,7 +119,7 @@ func (suite *TendermintTestSuite) TestCheckSubstituteAndUpdateState() {
// construct subject using test case parameters
subjectPath := ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupClients(subjectPath)
- subjectClientState := suite.chainA.GetClientState(subjectPath.EndpointA.ClientID).(*types.ClientState)
+ subjectClientState := suite.chainA.GetClientState(subjectPath.EndpointA.ClientID).(*ibctm.ClientState)
// apply freezing or expiry as determined by the test case
if tc.FreezeClient {
@@ -140,7 +139,7 @@ func (suite *TendermintTestSuite) TestCheckSubstituteAndUpdateState() {
substitutePath := ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupClients(substitutePath)
- substituteClientState := suite.chainA.GetClientState(substitutePath.EndpointA.ClientID).(*types.ClientState)
+ substituteClientState := suite.chainA.GetClientState(substitutePath.EndpointA.ClientID).(*ibctm.ClientState)
// update trusting period of substitute client state
substituteClientState.TrustingPeriod = time.Hour * 24 * 7
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), substitutePath.EndpointA.ClientID, substituteClientState)
@@ -154,7 +153,7 @@ func (suite *TendermintTestSuite) TestCheckSubstituteAndUpdateState() {
}
// get updated substitute
- substituteClientState = suite.chainA.GetClientState(substitutePath.EndpointA.ClientID).(*types.ClientState)
+ substituteClientState = suite.chainA.GetClientState(substitutePath.EndpointA.ClientID).(*ibctm.ClientState)
// test that subject gets updated chain-id
newChainID := "new-chain-id"
@@ -164,39 +163,40 @@ func (suite *TendermintTestSuite) TestCheckSubstituteAndUpdateState() {
substituteClientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), substitutePath.EndpointA.ClientID)
expectedConsState := substitutePath.EndpointA.GetConsensusState(substituteClientState.GetLatestHeight())
- expectedProcessedTime, found := types.GetProcessedTime(substituteClientStore, substituteClientState.GetLatestHeight())
+ expectedProcessedTime, found := ibctm.GetProcessedTime(substituteClientStore, substituteClientState.GetLatestHeight())
suite.Require().True(found)
- expectedProcessedHeight, found := types.GetProcessedTime(substituteClientStore, substituteClientState.GetLatestHeight())
+ expectedProcessedHeight, found := ibctm.GetProcessedTime(substituteClientStore, substituteClientState.GetLatestHeight())
suite.Require().True(found)
- expectedIterationKey := types.GetIterationKey(substituteClientStore, substituteClientState.GetLatestHeight())
+ expectedIterationKey := ibctm.GetIterationKey(substituteClientStore, substituteClientState.GetLatestHeight())
- updatedClient, err := subjectClientState.CheckSubstituteAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), subjectClientStore, substituteClientStore, substituteClientState)
+ err := subjectClientState.CheckSubstituteAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), subjectClientStore, substituteClientStore, substituteClientState)
if tc.expPass {
suite.Require().NoError(err)
- suite.Require().Equal(clienttypes.ZeroHeight(), updatedClient.(*types.ClientState).FrozenHeight)
+
+ updatedClient := subjectPath.EndpointA.GetClientState()
+ suite.Require().Equal(clienttypes.ZeroHeight(), updatedClient.(*ibctm.ClientState).FrozenHeight)
subjectClientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), subjectPath.EndpointA.ClientID)
// check that the correct consensus state was copied over
suite.Require().Equal(substituteClientState.GetLatestHeight(), updatedClient.GetLatestHeight())
subjectConsState := subjectPath.EndpointA.GetConsensusState(updatedClient.GetLatestHeight())
- subjectProcessedTime, found := types.GetProcessedTime(subjectClientStore, updatedClient.GetLatestHeight())
+ subjectProcessedTime, found := ibctm.GetProcessedTime(subjectClientStore, updatedClient.GetLatestHeight())
suite.Require().True(found)
- subjectProcessedHeight, found := types.GetProcessedTime(substituteClientStore, updatedClient.GetLatestHeight())
+ subjectProcessedHeight, found := ibctm.GetProcessedTime(substituteClientStore, updatedClient.GetLatestHeight())
suite.Require().True(found)
- subjectIterationKey := types.GetIterationKey(substituteClientStore, updatedClient.GetLatestHeight())
+ subjectIterationKey := ibctm.GetIterationKey(substituteClientStore, updatedClient.GetLatestHeight())
suite.Require().Equal(expectedConsState, subjectConsState)
suite.Require().Equal(expectedProcessedTime, subjectProcessedTime)
suite.Require().Equal(expectedProcessedHeight, subjectProcessedHeight)
suite.Require().Equal(expectedIterationKey, subjectIterationKey)
- suite.Require().Equal(newChainID, updatedClient.(*types.ClientState).ChainId)
- suite.Require().Equal(time.Hour*24*7, updatedClient.(*types.ClientState).TrustingPeriod)
+ suite.Require().Equal(newChainID, updatedClient.(*ibctm.ClientState).ChainId)
+ suite.Require().Equal(time.Hour*24*7, updatedClient.(*ibctm.ClientState).TrustingPeriod)
} else {
suite.Require().Error(err)
- suite.Require().Nil(updatedClient)
}
})
}
@@ -205,7 +205,7 @@ func (suite *TendermintTestSuite) TestCheckSubstituteAndUpdateState() {
func (suite *TendermintTestSuite) TestIsMatchingClientState() {
var (
subjectPath, substitutePath *ibctesting.Path
- subjectClientState, substituteClientState *types.ClientState
+ subjectClientState, substituteClientState *ibctm.ClientState
)
testCases := []struct {
@@ -215,8 +215,8 @@ func (suite *TendermintTestSuite) TestIsMatchingClientState() {
}{
{
"matching clients", func() {
- subjectClientState = suite.chainA.GetClientState(subjectPath.EndpointA.ClientID).(*types.ClientState)
- substituteClientState = suite.chainA.GetClientState(substitutePath.EndpointA.ClientID).(*types.ClientState)
+ subjectClientState = suite.chainA.GetClientState(subjectPath.EndpointA.ClientID).(*ibctm.ClientState)
+ substituteClientState = suite.chainA.GetClientState(substitutePath.EndpointA.ClientID).(*ibctm.ClientState)
}, true,
},
{
@@ -245,8 +245,8 @@ func (suite *TendermintTestSuite) TestIsMatchingClientState() {
},
{
"not matching, trust level is different", func() {
- subjectClientState.TrustLevel = types.Fraction{2, 3}
- substituteClientState.TrustLevel = types.Fraction{1, 3}
+ subjectClientState.TrustLevel = ibctm.Fraction{2, 3}
+ substituteClientState.TrustLevel = ibctm.Fraction{1, 3}
}, false,
},
}
@@ -264,7 +264,7 @@ func (suite *TendermintTestSuite) TestIsMatchingClientState() {
tc.malleate()
- suite.Require().Equal(tc.expPass, types.IsMatchingClientState(*subjectClientState, *substituteClientState))
+ suite.Require().Equal(tc.expPass, ibctm.IsMatchingClientState(*subjectClientState, *substituteClientState))
})
}
}
diff --git a/modules/light-clients/07-tendermint/types/store.go b/modules/light-clients/07-tendermint/store.go
similarity index 91%
rename from modules/light-clients/07-tendermint/types/store.go
rename to modules/light-clients/07-tendermint/store.go
index 301918c6bdf..e8824d06e1d 100644
--- a/modules/light-clients/07-tendermint/types/store.go
+++ b/modules/light-clients/07-tendermint/store.go
@@ -1,4 +1,4 @@
-package types
+package tendermint
import (
"bytes"
@@ -8,7 +8,6 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
- sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
@@ -43,38 +42,30 @@ var (
KeyIteration = []byte("/iterationKey")
)
-// SetConsensusState stores the consensus state at the given height.
-func SetConsensusState(clientStore sdk.KVStore, cdc codec.BinaryCodec, consensusState *ConsensusState, height exported.Height) {
+// setClientState stores the client state
+func setClientState(clientStore sdk.KVStore, cdc codec.BinaryCodec, clientState *ClientState) {
+ key := host.ClientStateKey()
+ val := clienttypes.MustMarshalClientState(cdc, clientState)
+ clientStore.Set(key, val)
+}
+
+// setConsensusState stores the consensus state at the given height.
+func setConsensusState(clientStore sdk.KVStore, cdc codec.BinaryCodec, consensusState *ConsensusState, height exported.Height) {
key := host.ConsensusStateKey(height)
val := clienttypes.MustMarshalConsensusState(cdc, consensusState)
clientStore.Set(key, val)
}
-// GetConsensusState retrieves the consensus state from the client prefixed
-// 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) {
+// GetConsensusState retrieves the consensus state from the client prefixed store.
+// If the ConsensusState does not exist in state for the provided height a nil value and false boolean flag is returned
+func GetConsensusState(store sdk.KVStore, cdc codec.BinaryCodec, height exported.Height) (*ConsensusState, bool) {
bz := store.Get(host.ConsensusStateKey(height))
if bz == nil {
- return nil, sdkerrors.Wrapf(
- clienttypes.ErrConsensusStateNotFound,
- "consensus state does not exist for height %s", height,
- )
- }
-
- consensusStateI, err := clienttypes.UnmarshalConsensusState(cdc, bz)
- if err != nil {
- return nil, sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "unmarshal error: %v", err)
- }
-
- consensusState, ok := consensusStateI.(*ConsensusState)
- if !ok {
- return nil, sdkerrors.Wrapf(
- clienttypes.ErrInvalidConsensus,
- "invalid consensus type %T, expected %T", consensusState, &ConsensusState{},
- )
+ return nil, false
}
- return consensusState, nil
+ consensusStateI := clienttypes.MustUnmarshalConsensusState(cdc, bz)
+ return consensusStateI.(*ConsensusState), true
}
// deleteConsensusState deletes the consensus state at the given height
@@ -224,7 +215,7 @@ func GetHeightFromIterationKey(iterKey []byte) exported.Height {
// IterateConsensusStateAscending iterates through the consensus states in ascending order. It calls the provided
// callback on each height, until stop=true is returned.
-func IterateConsensusStateAscending(clientStore sdk.KVStore, cb func(height exported.Height) (stop bool)) error {
+func IterateConsensusStateAscending(clientStore sdk.KVStore, cb func(height exported.Height) (stop bool)) {
iterator := sdk.KVStorePrefixIterator(clientStore, []byte(KeyIterateConsensusStatePrefix))
defer iterator.Close()
@@ -232,10 +223,9 @@ func IterateConsensusStateAscending(clientStore sdk.KVStore, cb func(height expo
iterKey := iterator.Key()
height := GetHeightFromIterationKey(iterKey)
if cb(height) {
- return nil
+ break
}
}
- return nil
}
// GetNextConsensusState returns the lowest consensus state that is larger than the given height.
@@ -287,13 +277,12 @@ func GetPreviousConsensusState(clientStore sdk.KVStore, cdc codec.BinaryCodec, h
func PruneAllExpiredConsensusStates(
ctx sdk.Context, clientStore sdk.KVStore,
cdc codec.BinaryCodec, clientState *ClientState,
-) (err error) {
+) {
var heights []exported.Height
pruneCb := func(height exported.Height) bool {
- consState, err := GetConsensusState(clientStore, cdc, height)
- // this error should never occur
- if err != nil {
+ consState, found := GetConsensusState(clientStore, cdc, height)
+ if !found { // consensus state should always be found
return true
}
@@ -304,17 +293,12 @@ func PruneAllExpiredConsensusStates(
return false
}
- err = IterateConsensusStateAscending(clientStore, pruneCb)
- if err != nil {
- return err
- }
+ IterateConsensusStateAscending(clientStore, pruneCb)
for _, height := range heights {
deleteConsensusState(clientStore, height)
deleteConsensusMetadata(clientStore, height)
}
-
- return nil
}
// Helper function for GetNextConsensusState and GetPreviousConsensusState
diff --git a/modules/light-clients/07-tendermint/types/store_test.go b/modules/light-clients/07-tendermint/store_test.go
similarity index 60%
rename from modules/light-clients/07-tendermint/types/store_test.go
rename to modules/light-clients/07-tendermint/store_test.go
index a482fad007e..851a39c1945 100644
--- a/modules/light-clients/07-tendermint/types/store_test.go
+++ b/modules/light-clients/07-tendermint/store_test.go
@@ -1,4 +1,4 @@
-package types_test
+package tendermint_test
import (
"math"
@@ -8,8 +8,8 @@ import (
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- solomachinetypes "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ solomachine "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
+ tendermint "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
@@ -23,31 +23,32 @@ func (suite *TendermintTestSuite) TestGetConsensusState() {
name string
malleate func()
expPass bool
+ expPanic bool
}{
{
- "success", func() {}, true,
+ "success", func() {}, true, false,
},
{
"consensus state not found", func() {
// use height with no consensus state set
height = height.(clienttypes.Height).Increment()
- }, false,
+ }, false, false,
},
{
"not a consensus state interface", func() {
// marshal an empty client state and set as consensus state
store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
- clientStateBz := suite.chainA.App.GetIBCKeeper().ClientKeeper.MustMarshalClientState(&types.ClientState{})
+ clientStateBz := suite.chainA.App.GetIBCKeeper().ClientKeeper.MustMarshalClientState(&tendermint.ClientState{})
store.Set(host.ConsensusStateKey(height), clientStateBz)
- }, false,
+ }, false, true,
},
{
"invalid consensus state (solomachine)", func() {
// marshal and set solomachine consensus state
store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
- consensusStateBz := suite.chainA.App.GetIBCKeeper().ClientKeeper.MustMarshalConsensusState(&solomachinetypes.ConsensusState{})
+ consensusStateBz := suite.chainA.App.GetIBCKeeper().ClientKeeper.MustMarshalConsensusState(&solomachine.ConsensusState{})
store.Set(host.ConsensusStateKey(height), consensusStateBz)
- }, false,
+ }, false, true,
},
}
@@ -64,16 +65,26 @@ func (suite *TendermintTestSuite) TestGetConsensusState() {
tc.malleate() // change vars as necessary
+ if tc.expPanic {
+ suite.Require().Panics(func() {
+ store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
+ tendermint.GetConsensusState(store, suite.chainA.Codec, height)
+ })
+
+ return
+ }
+
store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
- consensusState, err := types.GetConsensusState(store, suite.chainA.Codec, height)
+ consensusState, found := tendermint.GetConsensusState(store, suite.chainA.Codec, height)
if tc.expPass {
- suite.Require().NoError(err)
+ suite.Require().True(found)
+
expConsensusState, found := suite.chainA.GetConsensusState(path.EndpointA.ClientID, height)
suite.Require().True(found)
suite.Require().Equal(expConsensusState, consensusState)
} else {
- suite.Require().Error(err)
+ suite.Require().False(found)
suite.Require().Nil(consensusState)
}
})
@@ -96,7 +107,7 @@ func (suite *TendermintTestSuite) TestGetProcessedTime() {
height := clientState.GetLatestHeight()
store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
- actualTime, ok := types.GetProcessedTime(store, height)
+ actualTime, ok := tendermint.GetProcessedTime(store, height)
suite.Require().True(ok, "could not retrieve processed time for stored consensus state")
suite.Require().Equal(uint64(expectedTime.UnixNano()), actualTime, "retrieved processed time is not expected value")
@@ -112,12 +123,12 @@ func (suite *TendermintTestSuite) TestGetProcessedTime() {
height = clientState.GetLatestHeight()
store = suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
- actualTime, ok = types.GetProcessedTime(store, height)
+ actualTime, ok = tendermint.GetProcessedTime(store, height)
suite.Require().True(ok, "could not retrieve processed time for stored consensus state")
suite.Require().Equal(uint64(expectedTime.UnixNano()), actualTime, "retrieved processed time is not expected value")
// try to get processed time for height that doesn't exist in store
- _, ok = types.GetProcessedTime(store, clienttypes.NewHeight(1, 1))
+ _, ok = tendermint.GetProcessedTime(store, clienttypes.NewHeight(1, 1))
suite.Require().False(ok, "retrieved processed time for a non-existent consensus state")
}
@@ -129,8 +140,8 @@ func (suite *TendermintTestSuite) TestIterationKey() {
clienttypes.NewHeight(math.MaxUint64, math.MaxUint64),
}
for _, h := range testHeights {
- k := types.IterationKey(h)
- retrievedHeight := types.GetHeightFromIterationKey(k)
+ k := tendermint.IterationKey(h)
+ retrievedHeight := tendermint.GetHeightFromIterationKey(k)
suite.Require().Equal(h, retrievedHeight, "retrieving height from iteration key failed")
}
}
@@ -139,16 +150,16 @@ func (suite *TendermintTestSuite) TestIterateConsensusStates() {
nextValsHash := []byte("nextVals")
// Set iteration keys and consensus states
- types.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), clienttypes.NewHeight(0, 1))
- suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), "testClient", clienttypes.NewHeight(0, 1), types.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("hash0-1")), nextValsHash))
- types.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), clienttypes.NewHeight(4, 9))
- suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), "testClient", clienttypes.NewHeight(4, 9), types.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("hash4-9")), nextValsHash))
- types.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), clienttypes.NewHeight(0, 10))
- suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), "testClient", clienttypes.NewHeight(0, 10), types.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("hash0-10")), nextValsHash))
- types.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), clienttypes.NewHeight(0, 4))
- suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), "testClient", clienttypes.NewHeight(0, 4), types.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("hash0-4")), nextValsHash))
- types.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), clienttypes.NewHeight(40, 1))
- suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), "testClient", clienttypes.NewHeight(40, 1), types.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("hash40-1")), nextValsHash))
+ tendermint.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), clienttypes.NewHeight(0, 1))
+ suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), "testClient", clienttypes.NewHeight(0, 1), tendermint.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("hash0-1")), nextValsHash))
+ tendermint.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), clienttypes.NewHeight(4, 9))
+ suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), "testClient", clienttypes.NewHeight(4, 9), tendermint.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("hash4-9")), nextValsHash))
+ tendermint.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), clienttypes.NewHeight(0, 10))
+ suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), "testClient", clienttypes.NewHeight(0, 10), tendermint.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("hash0-10")), nextValsHash))
+ tendermint.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), clienttypes.NewHeight(0, 4))
+ suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), "testClient", clienttypes.NewHeight(0, 4), tendermint.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("hash0-4")), nextValsHash))
+ tendermint.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), clienttypes.NewHeight(40, 1))
+ suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), "testClient", clienttypes.NewHeight(40, 1), tendermint.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("hash40-1")), nextValsHash))
var testArr []string
cb := func(height exported.Height) bool {
@@ -156,39 +167,39 @@ func (suite *TendermintTestSuite) TestIterateConsensusStates() {
return false
}
- types.IterateConsensusStateAscending(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), cb)
+ tendermint.IterateConsensusStateAscending(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), cb)
expectedArr := []string{"0-1", "0-4", "0-10", "4-9", "40-1"}
suite.Require().Equal(expectedArr, testArr)
}
func (suite *TendermintTestSuite) TestGetNeighboringConsensusStates() {
nextValsHash := []byte("nextVals")
- cs01 := types.NewConsensusState(time.Now().UTC(), commitmenttypes.NewMerkleRoot([]byte("hash0-1")), nextValsHash)
- cs04 := types.NewConsensusState(time.Now().UTC(), commitmenttypes.NewMerkleRoot([]byte("hash0-4")), nextValsHash)
- cs49 := types.NewConsensusState(time.Now().UTC(), commitmenttypes.NewMerkleRoot([]byte("hash4-9")), nextValsHash)
+ cs01 := tendermint.NewConsensusState(time.Now().UTC(), commitmenttypes.NewMerkleRoot([]byte("hash0-1")), nextValsHash)
+ cs04 := tendermint.NewConsensusState(time.Now().UTC(), commitmenttypes.NewMerkleRoot([]byte("hash0-4")), nextValsHash)
+ cs49 := tendermint.NewConsensusState(time.Now().UTC(), commitmenttypes.NewMerkleRoot([]byte("hash4-9")), nextValsHash)
height01 := clienttypes.NewHeight(0, 1)
height04 := clienttypes.NewHeight(0, 4)
height49 := clienttypes.NewHeight(4, 9)
// Set iteration keys and consensus states
- types.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), height01)
+ tendermint.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), height01)
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), "testClient", height01, cs01)
- types.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), height04)
+ tendermint.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), height04)
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), "testClient", height04, cs04)
- types.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), height49)
+ tendermint.SetIterationKey(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), height49)
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), "testClient", height49, cs49)
- prevCs01, ok := types.GetPreviousConsensusState(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), suite.chainA.Codec, height01)
+ prevCs01, ok := tendermint.GetPreviousConsensusState(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), suite.chainA.Codec, height01)
suite.Require().Nil(prevCs01, "consensus state exists before lowest consensus state")
suite.Require().False(ok)
- prevCs49, ok := types.GetPreviousConsensusState(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), suite.chainA.Codec, height49)
+ prevCs49, ok := tendermint.GetPreviousConsensusState(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), suite.chainA.Codec, height49)
suite.Require().Equal(cs04, prevCs49, "previous consensus state is not returned correctly")
suite.Require().True(ok)
- nextCs01, ok := types.GetNextConsensusState(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), suite.chainA.Codec, height01)
+ nextCs01, ok := tendermint.GetNextConsensusState(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), suite.chainA.Codec, height01)
suite.Require().Equal(cs04, nextCs01, "next consensus state not returned correctly")
suite.Require().True(ok)
- nextCs49, ok := types.GetNextConsensusState(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), suite.chainA.Codec, height49)
+ nextCs49, ok := tendermint.GetNextConsensusState(suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), "testClient"), suite.chainA.Codec, height49)
suite.Require().Nil(nextCs49, "next consensus state exists after highest consensus state")
suite.Require().False(ok)
}
diff --git a/modules/light-clients/07-tendermint/types/tendermint.pb.go b/modules/light-clients/07-tendermint/tendermint.pb.go
similarity index 87%
rename from modules/light-clients/07-tendermint/types/tendermint.pb.go
rename to modules/light-clients/07-tendermint/tendermint.pb.go
index 2df221d3d39..46a11f4537f 100644
--- a/modules/light-clients/07-tendermint/types/tendermint.pb.go
+++ b/modules/light-clients/07-tendermint/tendermint.pb.go
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: ibc/lightclients/tendermint/v1/tendermint.proto
-package types
+package tendermint
import (
fmt "fmt"
@@ -144,7 +144,8 @@ var xxx_messageInfo_ConsensusState proto.InternalMessageInfo
// Misbehaviour is a wrapper over two conflicting Headers
// that implements Misbehaviour interface expected by ICS-02
type Misbehaviour struct {
- ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"`
+ // ClientID is deprecated
+ ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` // Deprecated: Do not use.
Header1 *Header `protobuf:"bytes,2,opt,name=header_1,json=header1,proto3" json:"header_1,omitempty" yaml:"header_1"`
Header2 *Header `protobuf:"bytes,3,opt,name=header_2,json=header2,proto3" json:"header_2,omitempty" yaml:"header_2"`
}
@@ -322,75 +323,75 @@ func init() {
}
var fileDescriptor_c6d6cf2b288949be = []byte{
- // 1082 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xcf, 0x6f, 0xe3, 0xc4,
- 0x17, 0x6f, 0xda, 0x7e, 0xb7, 0xc9, 0x24, 0xdd, 0xf6, 0x6b, 0x4a, 0x37, 0x2d, 0xdd, 0x38, 0x32,
- 0x52, 0xc9, 0x81, 0xda, 0x24, 0x0b, 0x42, 0xaa, 0xb8, 0xe0, 0xee, 0xa2, 0x16, 0xb1, 0x52, 0xe5,
- 0xf2, 0x43, 0x42, 0x42, 0x66, 0x62, 0x4f, 0x92, 0xd1, 0xda, 0x1e, 0xcb, 0x33, 0x09, 0x2d, 0x7f,
- 0x01, 0x1c, 0x90, 0xf6, 0x88, 0x38, 0x71, 0xe0, 0x8f, 0xd9, 0x63, 0x8f, 0x9c, 0x0c, 0x6a, 0xaf,
- 0x9c, 0x72, 0xe4, 0x84, 0xe6, 0x87, 0xed, 0x69, 0xb6, 0x4b, 0xb5, 0x5c, 0xa2, 0x79, 0xef, 0x7d,
- 0xde, 0xe7, 0x93, 0x79, 0xf3, 0xe6, 0x8d, 0x81, 0x83, 0x87, 0x81, 0x13, 0xe1, 0xf1, 0x84, 0x05,
- 0x11, 0x46, 0x09, 0xa3, 0x0e, 0x43, 0x49, 0x88, 0xb2, 0x18, 0x27, 0xcc, 0x99, 0xf5, 0x35, 0xcb,
- 0x4e, 0x33, 0xc2, 0x88, 0xd1, 0xc1, 0xc3, 0xc0, 0xd6, 0x13, 0x6c, 0x0d, 0x32, 0xeb, 0xef, 0x76,
- 0xb5, 0x7c, 0x76, 0x91, 0x22, 0xea, 0xcc, 0x60, 0x84, 0x43, 0xc8, 0x48, 0x26, 0x19, 0x76, 0xf7,
- 0x5e, 0x42, 0x88, 0x5f, 0x15, 0x6d, 0xa5, 0x19, 0x21, 0xa3, 0xc2, 0xea, 0x8c, 0x09, 0x19, 0x47,
- 0xc8, 0x11, 0xd6, 0x70, 0x3a, 0x72, 0xc2, 0x69, 0x06, 0x19, 0x26, 0x89, 0x8a, 0x9b, 0x8b, 0x71,
- 0x86, 0x63, 0x44, 0x19, 0x8c, 0xd3, 0x02, 0xc0, 0xf7, 0x17, 0x90, 0x0c, 0x39, 0xf2, 0xef, 0xf2,
- 0x3d, 0xc9, 0x95, 0x02, 0xbc, 0x53, 0x01, 0x48, 0x1c, 0x63, 0x16, 0x17, 0xa0, 0xd2, 0x52, 0xc0,
- 0xad, 0x31, 0x19, 0x13, 0xb1, 0x74, 0xf8, 0x4a, 0x7a, 0xad, 0xbf, 0xd6, 0x40, 0xf3, 0x48, 0xf0,
- 0x9d, 0x31, 0xc8, 0x90, 0xb1, 0x03, 0xea, 0xc1, 0x04, 0xe2, 0xc4, 0xc7, 0x61, 0xbb, 0xd6, 0xad,
- 0xf5, 0x1a, 0xde, 0x9a, 0xb0, 0x4f, 0x42, 0x03, 0x81, 0x26, 0xcb, 0xa6, 0x94, 0xf9, 0x11, 0x9a,
- 0xa1, 0xa8, 0xbd, 0xdc, 0xad, 0xf5, 0x9a, 0x83, 0x9e, 0xfd, 0xef, 0xf5, 0xb4, 0x3f, 0xc9, 0x60,
- 0xc0, 0x37, 0xec, 0xee, 0xbe, 0xc8, 0xcd, 0xa5, 0x79, 0x6e, 0x1a, 0x17, 0x30, 0x8e, 0x0e, 0x2d,
- 0x8d, 0xca, 0xf2, 0x80, 0xb0, 0x3e, 0xe3, 0x86, 0x31, 0x02, 0x1b, 0xc2, 0xc2, 0xc9, 0xd8, 0x4f,
- 0x51, 0x86, 0x49, 0xd8, 0x5e, 0x11, 0x52, 0x3b, 0xb6, 0x2c, 0x96, 0x5d, 0x14, 0xcb, 0x7e, 0xac,
- 0x8a, 0xe9, 0x5a, 0x8a, 0x7b, 0x5b, 0xe3, 0xae, 0xf2, 0xad, 0x9f, 0xff, 0x30, 0x6b, 0xde, 0xfd,
- 0xc2, 0x7b, 0x2a, 0x9c, 0x06, 0x06, 0x9b, 0xd3, 0x64, 0x48, 0x92, 0x50, 0x13, 0x5a, 0xbd, 0x4b,
- 0xe8, 0x6d, 0x25, 0xf4, 0x40, 0x0a, 0x2d, 0x12, 0x48, 0xa5, 0x8d, 0xd2, 0xad, 0xa4, 0x10, 0xd8,
- 0x88, 0xe1, 0xb9, 0x1f, 0x44, 0x24, 0x78, 0xe6, 0x87, 0x19, 0x1e, 0xb1, 0xf6, 0xff, 0x5e, 0x73,
- 0x4b, 0x0b, 0xf9, 0x52, 0x68, 0x3d, 0x86, 0xe7, 0x47, 0xdc, 0xf9, 0x98, 0xfb, 0x8c, 0x6f, 0xc0,
- 0xfa, 0x28, 0x23, 0xdf, 0xa3, 0xc4, 0x9f, 0x20, 0x7e, 0x20, 0xed, 0x7b, 0x42, 0x64, 0x57, 0x1c,
- 0x11, 0x6f, 0x11, 0x5b, 0x75, 0xce, 0xac, 0x6f, 0x1f, 0x0b, 0x84, 0xbb, 0xa7, 0x54, 0xb6, 0xa4,
- 0xca, 0x8d, 0x74, 0xcb, 0x6b, 0x49, 0x5b, 0x62, 0x39, 0x7d, 0x04, 0x19, 0xa2, 0xac, 0xa0, 0x5f,
- 0x7b, 0x5d, 0xfa, 0x1b, 0xe9, 0x96, 0xd7, 0x92, 0xb6, 0xa2, 0x3f, 0x01, 0x4d, 0x71, 0x75, 0x7c,
- 0x9a, 0xa2, 0x80, 0xb6, 0xeb, 0xdd, 0x95, 0x5e, 0x73, 0xb0, 0x69, 0xe3, 0x80, 0x0e, 0x1e, 0xd9,
- 0xa7, 0x3c, 0x72, 0x96, 0xa2, 0xc0, 0xdd, 0xae, 0x5a, 0x48, 0x83, 0x5b, 0x1e, 0x48, 0x0b, 0x08,
- 0x35, 0x0e, 0x41, 0x6b, 0x9a, 0x8e, 0x33, 0x18, 0x22, 0x3f, 0x85, 0x6c, 0xd2, 0x6e, 0x74, 0x57,
- 0x7a, 0x0d, 0xf7, 0xc1, 0x3c, 0x37, 0xdf, 0x50, 0xe7, 0xa6, 0x45, 0x2d, 0xaf, 0xa9, 0xcc, 0x53,
- 0xc8, 0x26, 0x06, 0x04, 0x3b, 0x30, 0x8a, 0xc8, 0x77, 0xfe, 0x34, 0x0d, 0x21, 0x43, 0x3e, 0x1c,
- 0x31, 0x94, 0xf9, 0xe8, 0x3c, 0xc5, 0xd9, 0x45, 0x1b, 0x74, 0x6b, 0xbd, 0xba, 0xbb, 0x3f, 0xcf,
- 0xcd, 0xae, 0x24, 0x7a, 0x25, 0xd4, 0x6a, 0xd7, 0xbc, 0x6d, 0x11, 0xfd, 0x42, 0x04, 0x3f, 0xe6,
- 0xb1, 0x27, 0x22, 0x64, 0x50, 0x60, 0xde, 0x92, 0x17, 0x63, 0x3a, 0x44, 0x13, 0x38, 0xc3, 0x64,
- 0x9a, 0xb5, 0x9b, 0x42, 0xe8, 0xdd, 0x79, 0x6e, 0xee, 0xbf, 0x52, 0x48, 0x4f, 0xe0, 0x72, 0x7b,
- 0x8b, 0x72, 0x4f, 0x35, 0xc0, 0xe1, 0xea, 0x0f, 0xbf, 0x9a, 0x4b, 0xd6, 0x6f, 0xcb, 0xe0, 0xfe,
- 0x11, 0x49, 0x28, 0x4a, 0xe8, 0x94, 0xca, 0x1b, 0xef, 0x82, 0x46, 0x39, 0x74, 0xc4, 0x95, 0xe7,
- 0x47, 0xba, 0xd8, 0x96, 0x9f, 0x17, 0x08, 0xb7, 0xce, 0x8f, 0xf4, 0x39, 0xef, 0xbe, 0x2a, 0xcd,
- 0xf8, 0x08, 0xac, 0x66, 0x84, 0x30, 0x35, 0x13, 0x2c, 0xad, 0x23, 0xaa, 0x29, 0x34, 0xeb, 0xdb,
- 0x4f, 0x51, 0xf6, 0x2c, 0x42, 0x1e, 0x21, 0xcc, 0x5d, 0xe5, 0x34, 0x9e, 0xc8, 0x32, 0x7e, 0xac,
- 0x81, 0xad, 0x04, 0x9d, 0x33, 0xbf, 0x9c, 0xb4, 0xd4, 0x9f, 0x40, 0x3a, 0x11, 0xf7, 0xbe, 0xe5,
- 0x7e, 0x35, 0xcf, 0xcd, 0xb7, 0x64, 0x15, 0x6e, 0x43, 0x59, 0x7f, 0xe7, 0xe6, 0xfb, 0x63, 0xcc,
- 0x26, 0xd3, 0x21, 0x97, 0xd3, 0xe7, 0xbf, 0xb6, 0x8c, 0xf0, 0x90, 0x3a, 0xc3, 0x0b, 0x86, 0xa8,
- 0x7d, 0x8c, 0xce, 0x5d, 0xbe, 0xf0, 0x0c, 0x4e, 0xf7, 0x65, 0xc9, 0x76, 0x0c, 0xe9, 0x44, 0x95,
- 0xe9, 0xa7, 0x65, 0xd0, 0xd2, 0xab, 0x67, 0xf4, 0x41, 0x43, 0x36, 0x77, 0x39, 0x17, 0xdd, 0xad,
- 0x79, 0x6e, 0x6e, 0xca, 0xbf, 0x55, 0x86, 0x2c, 0xaf, 0x2e, 0xd7, 0x27, 0xa1, 0x01, 0x41, 0x7d,
- 0x82, 0x60, 0x88, 0x32, 0xbf, 0xaf, 0xea, 0xb2, 0x7f, 0xd7, 0xac, 0x3c, 0x16, 0x78, 0xb7, 0x73,
- 0x95, 0x9b, 0x6b, 0x72, 0xdd, 0x9f, 0xe7, 0xe6, 0x86, 0x14, 0x29, 0xc8, 0x2c, 0x6f, 0x4d, 0x2e,
- 0xfb, 0x9a, 0xc4, 0x40, 0xcd, 0xc8, 0xff, 0x20, 0x31, 0x78, 0x49, 0x62, 0x50, 0x4a, 0x0c, 0x54,
- 0x3d, 0x7e, 0x59, 0x01, 0xf7, 0x24, 0xda, 0x80, 0x60, 0x9d, 0xe2, 0x71, 0x82, 0x42, 0x5f, 0x42,
- 0x54, 0xcb, 0x74, 0x74, 0x1d, 0xf9, 0x1e, 0x9e, 0x09, 0x98, 0x12, 0xdc, 0xbb, 0xcc, 0xcd, 0x5a,
- 0x35, 0x09, 0x6e, 0x50, 0x58, 0x5e, 0x8b, 0x6a, 0x58, 0x3e, 0x68, 0xca, 0x33, 0xf6, 0x29, 0x2a,
- 0xda, 0xea, 0x16, 0x89, 0xf2, 0xf0, 0xce, 0x10, 0x73, 0xdb, 0x15, 0xfd, 0x8d, 0x74, 0xcb, 0x6b,
- 0xcd, 0x34, 0x9c, 0xf1, 0x2d, 0x90, 0x4f, 0x81, 0xd0, 0x17, 0x83, 0x6c, 0xe5, 0xce, 0x41, 0xf6,
- 0x50, 0x0d, 0xb2, 0x37, 0xb5, 0x07, 0xa6, 0xcc, 0xb7, 0xbc, 0x75, 0xe5, 0x50, 0xa3, 0x2c, 0x02,
- 0x46, 0x81, 0xa8, 0x9a, 0x55, 0x3d, 0x2e, 0x77, 0xed, 0xe2, 0xe1, 0x3c, 0x37, 0x77, 0x6e, 0xaa,
- 0x54, 0x1c, 0x96, 0xf7, 0x7f, 0xe5, 0xac, 0xda, 0xd6, 0xfa, 0x14, 0xd4, 0x8b, 0x47, 0xd6, 0xd8,
- 0x03, 0x8d, 0x64, 0x1a, 0xa3, 0x8c, 0x47, 0xc4, 0xc9, 0xac, 0x7a, 0x95, 0xc3, 0xe8, 0x82, 0x66,
- 0x88, 0x12, 0x12, 0xe3, 0x44, 0xc4, 0x97, 0x45, 0x5c, 0x77, 0xb9, 0xfe, 0x8b, 0xab, 0x4e, 0xed,
- 0xf2, 0xaa, 0x53, 0xfb, 0xf3, 0xaa, 0x53, 0x7b, 0x7e, 0xdd, 0x59, 0xba, 0xbc, 0xee, 0x2c, 0xfd,
- 0x7e, 0xdd, 0x59, 0xfa, 0xfa, 0x89, 0x76, 0xc5, 0x02, 0x42, 0x63, 0x42, 0xf9, 0xa7, 0xd7, 0xc1,
- 0x98, 0x38, 0xb3, 0x0f, 0x9c, 0x98, 0x84, 0xd3, 0x08, 0x51, 0xf9, 0x21, 0x76, 0x50, 0x7c, 0x89,
- 0xbd, 0xf7, 0xe1, 0xc1, 0xe2, 0xa7, 0xd2, 0xf0, 0x9e, 0x18, 0x29, 0x8f, 0xfe, 0x09, 0x00, 0x00,
- 0xff, 0xff, 0x98, 0x6c, 0x12, 0x96, 0xb8, 0x09, 0x00, 0x00,
+ // 1080 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xcf, 0x6f, 0xe3, 0x44,
+ 0x14, 0x6e, 0xda, 0xb2, 0x4d, 0x26, 0xe9, 0xb6, 0x98, 0xd2, 0x4d, 0x4b, 0x37, 0x8e, 0x8c, 0x54,
+ 0x72, 0xa0, 0x36, 0x49, 0x41, 0x48, 0x85, 0x0b, 0xee, 0x82, 0xda, 0x15, 0x2b, 0x55, 0x2e, 0x3f,
+ 0x24, 0x24, 0x64, 0x26, 0xf6, 0x24, 0x19, 0xad, 0xed, 0xb1, 0x3c, 0x93, 0xd0, 0xf2, 0x17, 0xc0,
+ 0x89, 0x3d, 0x22, 0x4e, 0x1c, 0xf8, 0x63, 0xf6, 0xd8, 0x23, 0x27, 0x83, 0xda, 0x2b, 0xa7, 0x1c,
+ 0x39, 0xa1, 0xf9, 0x61, 0x7b, 0xda, 0xed, 0x52, 0x2d, 0x97, 0x68, 0xde, 0x7b, 0xdf, 0xfb, 0xbe,
+ 0xcc, 0xbc, 0x37, 0x6f, 0x0c, 0x1c, 0x3c, 0x0c, 0x9c, 0x08, 0x8f, 0x27, 0x2c, 0x88, 0x30, 0x4a,
+ 0x18, 0x75, 0x18, 0x4a, 0x42, 0x94, 0xc5, 0x38, 0x61, 0xce, 0xac, 0xaf, 0x59, 0x76, 0x9a, 0x11,
+ 0x46, 0x8c, 0x0e, 0x1e, 0x06, 0xb6, 0x9e, 0x60, 0x6b, 0x90, 0x59, 0x7f, 0xbb, 0xab, 0xe5, 0xb3,
+ 0xf3, 0x14, 0x51, 0x67, 0x06, 0x23, 0x1c, 0x42, 0x46, 0x32, 0xc9, 0xb0, 0xbd, 0xf3, 0x02, 0x42,
+ 0xfc, 0xaa, 0x68, 0x2b, 0xcd, 0x08, 0x19, 0x15, 0x56, 0x67, 0x4c, 0xc8, 0x38, 0x42, 0x8e, 0xb0,
+ 0x86, 0xd3, 0x91, 0x13, 0x4e, 0x33, 0xc8, 0x30, 0x49, 0x54, 0xdc, 0xbc, 0x19, 0x67, 0x38, 0x46,
+ 0x94, 0xc1, 0x38, 0x2d, 0x00, 0x7c, 0x7f, 0x01, 0xc9, 0x90, 0x23, 0xff, 0x2e, 0xdf, 0x93, 0x5c,
+ 0x29, 0xc0, 0x3b, 0x15, 0x80, 0xc4, 0x31, 0x66, 0x71, 0x01, 0x2a, 0x2d, 0x05, 0xdc, 0x18, 0x93,
+ 0x31, 0x11, 0x4b, 0x87, 0xaf, 0xa4, 0xd7, 0xfa, 0x7b, 0x05, 0x34, 0x0f, 0x05, 0xdf, 0x29, 0x83,
+ 0x0c, 0x19, 0x5b, 0xa0, 0x1e, 0x4c, 0x20, 0x4e, 0x7c, 0x1c, 0xb6, 0x6b, 0xdd, 0x5a, 0xaf, 0xe1,
+ 0xad, 0x08, 0xfb, 0x38, 0x34, 0x10, 0x68, 0xb2, 0x6c, 0x4a, 0x99, 0x1f, 0xa1, 0x19, 0x8a, 0xda,
+ 0x8b, 0xdd, 0x5a, 0xaf, 0x39, 0xe8, 0xd9, 0xff, 0x7d, 0x9e, 0xf6, 0x67, 0x19, 0x0c, 0xf8, 0x86,
+ 0xdd, 0xed, 0xe7, 0xb9, 0xb9, 0x30, 0xcf, 0x4d, 0xe3, 0x1c, 0xc6, 0xd1, 0x81, 0xa5, 0x51, 0x59,
+ 0x1e, 0x10, 0xd6, 0xe7, 0xdc, 0x30, 0x46, 0x60, 0x4d, 0x58, 0x38, 0x19, 0xfb, 0x29, 0xca, 0x30,
+ 0x09, 0xdb, 0x4b, 0x42, 0x6a, 0xcb, 0x96, 0x87, 0x65, 0x17, 0x87, 0x65, 0x3f, 0x52, 0x87, 0xe9,
+ 0x5a, 0x8a, 0x7b, 0x53, 0xe3, 0xae, 0xf2, 0xad, 0x5f, 0xfe, 0x34, 0x6b, 0xde, 0xfd, 0xc2, 0x7b,
+ 0x22, 0x9c, 0x06, 0x06, 0xeb, 0xd3, 0x64, 0x48, 0x92, 0x50, 0x13, 0x5a, 0xbe, 0x4b, 0xe8, 0x6d,
+ 0x25, 0xf4, 0x40, 0x0a, 0xdd, 0x24, 0x90, 0x4a, 0x6b, 0xa5, 0x5b, 0x49, 0x21, 0xb0, 0x16, 0xc3,
+ 0x33, 0x3f, 0x88, 0x48, 0xf0, 0xd4, 0x0f, 0x33, 0x3c, 0x62, 0xed, 0xd7, 0x5e, 0x71, 0x4b, 0x37,
+ 0xf2, 0xa5, 0xd0, 0x6a, 0x0c, 0xcf, 0x0e, 0xb9, 0xf3, 0x11, 0xf7, 0x19, 0xdf, 0x82, 0xd5, 0x51,
+ 0x46, 0x7e, 0x40, 0x89, 0x3f, 0x41, 0xbc, 0x20, 0xed, 0x7b, 0x42, 0x64, 0x5b, 0x94, 0x88, 0xb7,
+ 0x88, 0xad, 0x3a, 0x67, 0xd6, 0xb7, 0x8f, 0x04, 0xc2, 0xdd, 0x51, 0x2a, 0x1b, 0x52, 0xe5, 0x5a,
+ 0xba, 0xe5, 0xb5, 0xa4, 0x2d, 0xb1, 0x9c, 0x3e, 0x82, 0x0c, 0x51, 0x56, 0xd0, 0xaf, 0xbc, 0x2a,
+ 0xfd, 0xb5, 0x74, 0xcb, 0x6b, 0x49, 0x5b, 0xd1, 0x1f, 0x83, 0xa6, 0xb8, 0x3a, 0x3e, 0x4d, 0x51,
+ 0x40, 0xdb, 0xf5, 0xee, 0x52, 0xaf, 0x39, 0x58, 0xb7, 0x71, 0x40, 0x07, 0xfb, 0xf6, 0x09, 0x8f,
+ 0x9c, 0xa6, 0x28, 0x70, 0x37, 0xab, 0x16, 0xd2, 0xe0, 0x96, 0x07, 0xd2, 0x02, 0x42, 0x8d, 0x03,
+ 0xd0, 0x9a, 0xa6, 0xe3, 0x0c, 0x86, 0xc8, 0x4f, 0x21, 0x9b, 0xb4, 0x1b, 0xdd, 0xa5, 0x5e, 0xc3,
+ 0x7d, 0x30, 0xcf, 0xcd, 0x37, 0x54, 0xdd, 0xb4, 0xa8, 0xe5, 0x35, 0x95, 0x79, 0x02, 0xd9, 0xc4,
+ 0x80, 0x60, 0x0b, 0x46, 0x11, 0xf9, 0xde, 0x9f, 0xa6, 0x21, 0x64, 0xc8, 0x87, 0x23, 0x86, 0x32,
+ 0x1f, 0x9d, 0xa5, 0x38, 0x3b, 0x6f, 0x83, 0x6e, 0xad, 0x57, 0x77, 0x77, 0xe7, 0xb9, 0xd9, 0x95,
+ 0x44, 0x2f, 0x85, 0x5a, 0xed, 0x9a, 0xb7, 0x29, 0xa2, 0x5f, 0x8a, 0xe0, 0x27, 0x3c, 0xf6, 0xa9,
+ 0x08, 0x19, 0x14, 0x98, 0xb7, 0xe4, 0xc5, 0x98, 0x0e, 0xd1, 0x04, 0xce, 0x30, 0x99, 0x66, 0xed,
+ 0xa6, 0x10, 0x7a, 0x77, 0x9e, 0x9b, 0xbb, 0x2f, 0x15, 0xd2, 0x13, 0xb8, 0xdc, 0xce, 0x4d, 0xb9,
+ 0x27, 0x1a, 0xe0, 0x60, 0xf9, 0xc7, 0xdf, 0xcc, 0x05, 0xeb, 0xf7, 0x45, 0x70, 0xff, 0x90, 0x24,
+ 0x14, 0x25, 0x74, 0x4a, 0xe5, 0x8d, 0x77, 0x41, 0xa3, 0x1c, 0x3a, 0xe2, 0xca, 0xf3, 0x92, 0xde,
+ 0x6c, 0xcb, 0x2f, 0x0a, 0x84, 0x5b, 0xe7, 0x25, 0x7d, 0xc6, 0xbb, 0xaf, 0x4a, 0x33, 0x3e, 0x06,
+ 0xcb, 0x19, 0x21, 0x4c, 0xcd, 0x04, 0x4b, 0xeb, 0x88, 0x6a, 0x0a, 0xcd, 0xfa, 0xf6, 0x13, 0x94,
+ 0x3d, 0x8d, 0x90, 0x47, 0x08, 0x73, 0x97, 0x39, 0x8d, 0x27, 0xb2, 0x8c, 0x9f, 0x6a, 0x60, 0x23,
+ 0x41, 0x67, 0xcc, 0x2f, 0x27, 0x2d, 0xf5, 0x27, 0x90, 0x4e, 0xc4, 0xbd, 0x6f, 0xb9, 0x5f, 0xcf,
+ 0x73, 0xf3, 0x2d, 0x79, 0x0a, 0xb7, 0xa1, 0xac, 0x7f, 0x72, 0xf3, 0xfd, 0x31, 0x66, 0x93, 0xe9,
+ 0x90, 0xcb, 0xe9, 0xf3, 0x5f, 0x5b, 0x46, 0x78, 0x48, 0x9d, 0xe1, 0x39, 0x43, 0xd4, 0x3e, 0x42,
+ 0x67, 0x2e, 0x5f, 0x78, 0x06, 0xa7, 0xfb, 0xaa, 0x64, 0x3b, 0x82, 0x74, 0xa2, 0x8e, 0xe9, 0xe7,
+ 0x45, 0xd0, 0xd2, 0x4f, 0xcf, 0xd8, 0x07, 0x0d, 0xd9, 0xdc, 0xe5, 0x5c, 0x14, 0x8d, 0xb8, 0x2e,
+ 0xff, 0x56, 0x19, 0xe2, 0x65, 0xa8, 0x4b, 0xeb, 0x38, 0x34, 0x20, 0xa8, 0x4f, 0x10, 0x0c, 0x51,
+ 0xe6, 0xf7, 0xd5, 0xc9, 0xec, 0xde, 0x35, 0x2d, 0x8f, 0x04, 0xde, 0xed, 0x5c, 0xe6, 0xe6, 0x8a,
+ 0x5c, 0xf7, 0xe7, 0xb9, 0xb9, 0x26, 0x65, 0x0a, 0x32, 0xcb, 0x5b, 0x91, 0xcb, 0xbe, 0x26, 0x31,
+ 0x50, 0x53, 0xf2, 0x7f, 0x48, 0x0c, 0x5e, 0x90, 0x18, 0x94, 0x12, 0x03, 0x75, 0x22, 0xbf, 0x2e,
+ 0x81, 0x7b, 0x12, 0x6d, 0x40, 0xb0, 0x4a, 0xf1, 0x38, 0x41, 0xa1, 0x2f, 0x21, 0xaa, 0x69, 0x3a,
+ 0xba, 0x8e, 0x7c, 0x11, 0x4f, 0x05, 0x4c, 0x09, 0xee, 0x5c, 0xe4, 0x66, 0xad, 0x9a, 0x05, 0xd7,
+ 0x28, 0x2c, 0xaf, 0x45, 0x35, 0x2c, 0x1f, 0x35, 0x65, 0x95, 0x7d, 0x8a, 0x8a, 0xc6, 0xba, 0x45,
+ 0xa2, 0x2c, 0xdf, 0x29, 0x62, 0x6e, 0xbb, 0xa2, 0xbf, 0x96, 0x6e, 0x79, 0xad, 0x99, 0x86, 0x33,
+ 0xbe, 0x03, 0xf2, 0x31, 0x10, 0xfa, 0x62, 0x94, 0x2d, 0xdd, 0x39, 0xca, 0x1e, 0xaa, 0x51, 0xf6,
+ 0xa6, 0xf6, 0xc4, 0x94, 0xf9, 0x96, 0xb7, 0xaa, 0x1c, 0x6a, 0x98, 0x45, 0xc0, 0x28, 0x10, 0x55,
+ 0xbb, 0xaa, 0xe7, 0xe5, 0xae, 0x5d, 0x3c, 0x9c, 0xe7, 0xe6, 0xd6, 0x75, 0x95, 0x8a, 0xc3, 0xf2,
+ 0x5e, 0x57, 0xce, 0xaa, 0x71, 0xad, 0xc7, 0xa0, 0x5e, 0x3c, 0xb3, 0xc6, 0x0e, 0x68, 0x24, 0xd3,
+ 0x18, 0x65, 0x3c, 0x22, 0x2a, 0xb3, 0xec, 0x55, 0x0e, 0xa3, 0x0b, 0x9a, 0x21, 0x4a, 0x48, 0x8c,
+ 0x13, 0x11, 0x5f, 0x14, 0x71, 0xdd, 0xe5, 0x86, 0xcf, 0x2f, 0x3b, 0xb5, 0x8b, 0xcb, 0x4e, 0xed,
+ 0xaf, 0xcb, 0x4e, 0xed, 0xd9, 0x55, 0x67, 0xe1, 0xe2, 0xaa, 0xb3, 0xf0, 0xc7, 0x55, 0x67, 0xe1,
+ 0x9b, 0xc7, 0xda, 0x25, 0x0b, 0x08, 0x8d, 0x09, 0xe5, 0x1f, 0x5f, 0x7b, 0x63, 0xe2, 0xcc, 0x3e,
+ 0x70, 0x62, 0x12, 0x4e, 0x23, 0x44, 0xe5, 0xa7, 0xd8, 0x5e, 0xf1, 0x2d, 0xf6, 0xde, 0x87, 0x7b,
+ 0xd5, 0x5e, 0x3f, 0xaa, 0x96, 0xc3, 0x7b, 0x62, 0xb2, 0xec, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff,
+ 0xcc, 0x58, 0x27, 0x4c, 0xbf, 0x09, 0x00, 0x00,
}
func (m *ClientState) Marshal() (dAtA []byte, err error) {
diff --git a/modules/light-clients/07-tendermint/types/tendermint_test.go b/modules/light-clients/07-tendermint/tendermint_test.go
similarity index 96%
rename from modules/light-clients/07-tendermint/types/tendermint_test.go
rename to modules/light-clients/07-tendermint/tendermint_test.go
index d82d91e2059..7ad52f62299 100644
--- a/modules/light-clients/07-tendermint/types/tendermint_test.go
+++ b/modules/light-clients/07-tendermint/tendermint_test.go
@@ -1,4 +1,4 @@
-package types_test
+package tendermint_test
import (
"testing"
@@ -12,7 +12,7 @@ import (
tmtypes "github.com/tendermint/tendermint/types"
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
ibctestingmock "github.com/cosmos/ibc-go/v5/testing/mock"
"github.com/cosmos/ibc-go/v5/testing/simapp"
@@ -50,7 +50,7 @@ type TendermintTestSuite struct {
valSet *tmtypes.ValidatorSet
signers map[string]tmtypes.PrivValidator
valsHash tmbytes.HexBytes
- header *ibctmtypes.Header
+ header *ibctm.Header
now time.Time
headerTime time.Time
clientTime time.Time
diff --git a/modules/light-clients/07-tendermint/types/client_state.go b/modules/light-clients/07-tendermint/types/client_state.go
deleted file mode 100644
index 8db1903e76a..00000000000
--- a/modules/light-clients/07-tendermint/types/client_state.go
+++ /dev/null
@@ -1,583 +0,0 @@
-package types
-
-import (
- "strings"
- "time"
-
- ics23 "github.com/confio/ics23/go"
- "github.com/cosmos/cosmos-sdk/codec"
- sdk "github.com/cosmos/cosmos-sdk/types"
- sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
- "github.com/tendermint/tendermint/light"
- tmtypes "github.com/tendermint/tendermint/types"
-
- clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- connectiontypes "github.com/cosmos/ibc-go/v5/modules/core/03-connection/types"
- channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
- commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
- host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
-)
-
-var _ exported.ClientState = (*ClientState)(nil)
-
-// NewClientState creates a new ClientState instance
-func NewClientState(
- chainID string, trustLevel Fraction,
- trustingPeriod, ubdPeriod, maxClockDrift time.Duration,
- latestHeight clienttypes.Height, specs []*ics23.ProofSpec,
- upgradePath []string, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour bool,
-) *ClientState {
- return &ClientState{
- ChainId: chainID,
- TrustLevel: trustLevel,
- TrustingPeriod: trustingPeriod,
- UnbondingPeriod: ubdPeriod,
- MaxClockDrift: maxClockDrift,
- LatestHeight: latestHeight,
- FrozenHeight: clienttypes.ZeroHeight(),
- ProofSpecs: specs,
- UpgradePath: upgradePath,
- AllowUpdateAfterExpiry: allowUpdateAfterExpiry,
- AllowUpdateAfterMisbehaviour: allowUpdateAfterMisbehaviour,
- }
-}
-
-// GetChainID returns the chain-id
-func (cs ClientState) GetChainID() string {
- return cs.ChainId
-}
-
-// ClientType is tendermint.
-func (cs ClientState) ClientType() string {
- return exported.Tendermint
-}
-
-// GetLatestHeight returns latest block height.
-func (cs ClientState) GetLatestHeight() exported.Height {
- return cs.LatestHeight
-}
-
-// 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.BinaryCodec,
-) 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 {
- // if the client state does not have an associated consensus state for its latest height
- // then it must be expired
- return exported.Expired
- }
-
- if cs.IsExpired(consState.Timestamp, ctx.BlockTime()) {
- return exported.Expired
- }
-
- return exported.Active
-}
-
-// IsExpired returns whether or not the client has passed the trusting period since the last
-// update (in which case no headers are considered valid).
-func (cs ClientState) IsExpired(latestTimestamp, now time.Time) bool {
- expirationTime := latestTimestamp.Add(cs.TrustingPeriod)
- return !expirationTime.After(now)
-}
-
-// Validate performs a basic validation of the client state fields.
-func (cs ClientState) Validate() error {
- if strings.TrimSpace(cs.ChainId) == "" {
- return sdkerrors.Wrap(ErrInvalidChainID, "chain id cannot be empty string")
- }
-
- // NOTE: the value of tmtypes.MaxChainIDLen may change in the future.
- // If this occurs, the code here must account for potential difference
- // between the tendermint version being run by the counterparty chain
- // and the tendermint version used by this light client.
- // https://github.com/cosmos/ibc-go/issues/177
- if len(cs.ChainId) > tmtypes.MaxChainIDLen {
- return sdkerrors.Wrapf(ErrInvalidChainID, "chainID is too long; got: %d, max: %d", len(cs.ChainId), tmtypes.MaxChainIDLen)
- }
-
- if err := light.ValidateTrustLevel(cs.TrustLevel.ToTendermint()); err != nil {
- return err
- }
- if cs.TrustingPeriod == 0 {
- return sdkerrors.Wrap(ErrInvalidTrustingPeriod, "trusting period cannot be zero")
- }
- if cs.UnbondingPeriod == 0 {
- return sdkerrors.Wrap(ErrInvalidUnbondingPeriod, "unbonding period cannot be zero")
- }
- if cs.MaxClockDrift == 0 {
- return sdkerrors.Wrap(ErrInvalidMaxClockDrift, "max clock drift cannot be zero")
- }
-
- // the latest height revision number must match the chain id revision number
- if cs.LatestHeight.RevisionNumber != clienttypes.ParseChainID(cs.ChainId) {
- return sdkerrors.Wrapf(ErrInvalidHeaderHeight,
- "latest height revision number must match chain id revision number (%d != %d)", cs.LatestHeight.RevisionNumber, clienttypes.ParseChainID(cs.ChainId))
- }
- if cs.LatestHeight.RevisionHeight == 0 {
- return sdkerrors.Wrapf(ErrInvalidHeaderHeight, "tendermint client's latest height revision height cannot be zero")
- }
- if cs.TrustingPeriod >= cs.UnbondingPeriod {
- return sdkerrors.Wrapf(
- ErrInvalidTrustingPeriod,
- "trusting period (%s) should be < unbonding period (%s)", cs.TrustingPeriod, cs.UnbondingPeriod,
- )
- }
-
- if cs.ProofSpecs == nil {
- return sdkerrors.Wrap(ErrInvalidProofSpecs, "proof specs cannot be nil for tm client")
- }
- for i, spec := range cs.ProofSpecs {
- if spec == nil {
- return sdkerrors.Wrapf(ErrInvalidProofSpecs, "proof spec cannot be nil at index: %d", i)
- }
- }
- // UpgradePath may be empty, but if it isn't, each key must be non-empty
- for i, k := range cs.UpgradePath {
- if strings.TrimSpace(k) == "" {
- return sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "key in upgrade path at index %d cannot be empty", i)
- }
- }
-
- return nil
-}
-
-// GetProofSpecs returns the format the client expects for proof verification
-// as a string array specifying the proof type for each position in chained proof
-func (cs ClientState) GetProofSpecs() []*ics23.ProofSpec {
- return cs.ProofSpecs
-}
-
-// ZeroCustomFields returns a ClientState that is a copy of the current ClientState
-// with all client customizable fields zeroed out
-func (cs ClientState) ZeroCustomFields() exported.ClientState {
- // copy over all chain-specified fields
- // and leave custom fields empty
- return &ClientState{
- ChainId: cs.ChainId,
- UnbondingPeriod: cs.UnbondingPeriod,
- LatestHeight: cs.LatestHeight,
- ProofSpecs: cs.ProofSpecs,
- UpgradePath: cs.UpgradePath,
- }
-}
-
-// Initialize will check that initial consensus state is a Tendermint consensus state
-// and will store ProcessedTime for initial consensus state as ctx.BlockTime()
-func (cs ClientState) Initialize(ctx sdk.Context, _ codec.BinaryCodec, clientStore sdk.KVStore, consState exported.ConsensusState) error {
- if _, ok := consState.(*ConsensusState); !ok {
- return sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "invalid initial consensus state. expected type: %T, got: %T",
- &ConsensusState{}, consState)
- }
- // set metadata for initial consensus state.
- setConsensusMetadata(ctx, clientStore, cs.GetLatestHeight())
- return nil
-}
-
-// VerifyClientState verifies a proof of the client state of the running chain
-// stored on the target machine
-func (cs ClientState) VerifyClientState(
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- prefix exported.Prefix,
- counterpartyClientIdentifier string,
- proof []byte,
- clientState exported.ClientState,
-) error {
- merkleProof, provingConsensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- clientPrefixedPath := commitmenttypes.NewMerklePath(host.FullClientStatePath(counterpartyClientIdentifier))
- path, err := commitmenttypes.ApplyPrefix(prefix, clientPrefixedPath)
- if err != nil {
- return err
- }
-
- if clientState == nil {
- return sdkerrors.Wrap(clienttypes.ErrInvalidClient, "client state cannot be empty")
- }
-
- _, ok := clientState.(*ClientState)
- if !ok {
- return sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "invalid client type %T, expected %T", clientState, &ClientState{})
- }
-
- bz, err := cdc.MarshalInterface(clientState)
- if err != nil {
- return err
- }
-
- return merkleProof.VerifyMembership(cs.ProofSpecs, provingConsensusState.GetRoot(), path, bz)
-}
-
-// VerifyClientConsensusState verifies a proof of the consensus state of the
-// Tendermint client stored on the target machine.
-func (cs ClientState) VerifyClientConsensusState(
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- counterpartyClientIdentifier string,
- consensusHeight exported.Height,
- prefix exported.Prefix,
- proof []byte,
- consensusState exported.ConsensusState,
-) error {
- merkleProof, provingConsensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- clientPrefixedPath := commitmenttypes.NewMerklePath(host.FullConsensusStatePath(counterpartyClientIdentifier, consensusHeight))
- path, err := commitmenttypes.ApplyPrefix(prefix, clientPrefixedPath)
- if err != nil {
- return err
- }
-
- if consensusState == nil {
- return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "consensus state cannot be empty")
- }
-
- _, ok := consensusState.(*ConsensusState)
- if !ok {
- return sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "invalid consensus type %T, expected %T", consensusState, &ConsensusState{})
- }
-
- bz, err := cdc.MarshalInterface(consensusState)
- if err != nil {
- return err
- }
-
- if err := merkleProof.VerifyMembership(cs.ProofSpecs, provingConsensusState.GetRoot(), path, bz); err != nil {
- return err
- }
-
- return nil
-}
-
-// VerifyConnectionState verifies a proof of the connection state of the
-// specified connection end stored on the target machine.
-func (cs ClientState) VerifyConnectionState(
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- prefix exported.Prefix,
- proof []byte,
- connectionID string,
- connectionEnd exported.ConnectionI,
-) error {
- merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- connectionPath := commitmenttypes.NewMerklePath(host.ConnectionPath(connectionID))
- path, err := commitmenttypes.ApplyPrefix(prefix, connectionPath)
- if err != nil {
- return err
- }
-
- connection, ok := connectionEnd.(connectiontypes.ConnectionEnd)
- if !ok {
- return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "invalid connection type %T", connectionEnd)
- }
-
- bz, err := cdc.Marshal(&connection)
- if err != nil {
- return err
- }
-
- if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), path, bz); err != nil {
- return err
- }
-
- return nil
-}
-
-// VerifyChannelState verifies a proof of the channel state of the specified
-// channel end, under the specified port, stored on the target machine.
-func (cs ClientState) VerifyChannelState(
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- prefix exported.Prefix,
- proof []byte,
- portID,
- channelID string,
- channel exported.ChannelI,
-) error {
- merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- channelPath := commitmenttypes.NewMerklePath(host.ChannelPath(portID, channelID))
- path, err := commitmenttypes.ApplyPrefix(prefix, channelPath)
- if err != nil {
- return err
- }
-
- channelEnd, ok := channel.(channeltypes.Channel)
- if !ok {
- return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "invalid channel type %T", channel)
- }
-
- bz, err := cdc.Marshal(&channelEnd)
- if err != nil {
- return err
- }
-
- if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), path, bz); err != nil {
- return err
- }
-
- return nil
-}
-
-// VerifyPacketCommitment verifies a proof of an outgoing packet commitment at
-// the specified port, specified channel, and specified sequence.
-func (cs ClientState) VerifyPacketCommitment(
- ctx sdk.Context,
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- delayTimePeriod uint64,
- delayBlockPeriod uint64,
- prefix exported.Prefix,
- proof []byte,
- portID,
- channelID string,
- sequence uint64,
- commitmentBytes []byte,
-) error {
- merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- // check delay period has passed
- if err := verifyDelayPeriodPassed(ctx, store, height, delayTimePeriod, delayBlockPeriod); err != nil {
- return err
- }
-
- commitmentPath := commitmenttypes.NewMerklePath(host.PacketCommitmentPath(portID, channelID, sequence))
- path, err := commitmenttypes.ApplyPrefix(prefix, commitmentPath)
- if err != nil {
- return err
- }
-
- if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), path, commitmentBytes); err != nil {
- return err
- }
-
- return nil
-}
-
-// VerifyPacketAcknowledgement verifies a proof of an incoming packet
-// acknowledgement at the specified port, specified channel, and specified sequence.
-func (cs ClientState) VerifyPacketAcknowledgement(
- ctx sdk.Context,
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- delayTimePeriod uint64,
- delayBlockPeriod uint64,
- prefix exported.Prefix,
- proof []byte,
- portID,
- channelID string,
- sequence uint64,
- acknowledgement []byte,
-) error {
- merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- // check delay period has passed
- if err := verifyDelayPeriodPassed(ctx, store, height, delayTimePeriod, delayBlockPeriod); err != nil {
- return err
- }
-
- ackPath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementPath(portID, channelID, sequence))
- path, err := commitmenttypes.ApplyPrefix(prefix, ackPath)
- if err != nil {
- return err
- }
-
- if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), path, channeltypes.CommitAcknowledgement(acknowledgement)); err != nil {
- return err
- }
-
- return nil
-}
-
-// VerifyPacketReceiptAbsence verifies a proof of the absence of an
-// incoming packet receipt at the specified port, specified channel, and
-// specified sequence.
-func (cs ClientState) VerifyPacketReceiptAbsence(
- ctx sdk.Context,
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- delayTimePeriod uint64,
- delayBlockPeriod uint64,
- prefix exported.Prefix,
- proof []byte,
- portID,
- channelID string,
- sequence uint64,
-) error {
- merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- // check delay period has passed
- if err := verifyDelayPeriodPassed(ctx, store, height, delayTimePeriod, delayBlockPeriod); err != nil {
- return err
- }
-
- receiptPath := commitmenttypes.NewMerklePath(host.PacketReceiptPath(portID, channelID, sequence))
- path, err := commitmenttypes.ApplyPrefix(prefix, receiptPath)
- if err != nil {
- return err
- }
-
- if err := merkleProof.VerifyNonMembership(cs.ProofSpecs, consensusState.GetRoot(), path); err != nil {
- return err
- }
-
- return nil
-}
-
-// VerifyNextSequenceRecv verifies a proof of the next sequence number to be
-// received of the specified channel at the specified port.
-func (cs ClientState) VerifyNextSequenceRecv(
- ctx sdk.Context,
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- height exported.Height,
- delayTimePeriod uint64,
- delayBlockPeriod uint64,
- prefix exported.Prefix,
- proof []byte,
- portID,
- channelID string,
- nextSequenceRecv uint64,
-) error {
- merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
- if err != nil {
- return err
- }
-
- // check delay period has passed
- if err := verifyDelayPeriodPassed(ctx, store, height, delayTimePeriod, delayBlockPeriod); err != nil {
- return err
- }
-
- nextSequenceRecvPath := commitmenttypes.NewMerklePath(host.NextSequenceRecvPath(portID, channelID))
- path, err := commitmenttypes.ApplyPrefix(prefix, nextSequenceRecvPath)
- if err != nil {
- return err
- }
-
- bz := sdk.Uint64ToBigEndian(nextSequenceRecv)
-
- if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), path, bz); err != nil {
- return err
- }
-
- return nil
-}
-
-// verifyDelayPeriodPassed will ensure that at least delayTimePeriod amount of time and delayBlockPeriod number of blocks have passed
-// since consensus state was submitted before allowing verification to continue.
-func verifyDelayPeriodPassed(ctx sdk.Context, store sdk.KVStore, proofHeight exported.Height, delayTimePeriod, delayBlockPeriod uint64) error {
- // check that executing chain's timestamp has passed consensusState's processed time + delay time period
- processedTime, ok := GetProcessedTime(store, proofHeight)
- if !ok {
- return sdkerrors.Wrapf(ErrProcessedTimeNotFound, "processed time not found for height: %s", proofHeight)
- }
- currentTimestamp := uint64(ctx.BlockTime().UnixNano())
- validTime := processedTime + delayTimePeriod
- // NOTE: delay time period is inclusive, so if currentTimestamp is validTime, then we return no error
- if currentTimestamp < validTime {
- return sdkerrors.Wrapf(ErrDelayPeriodNotPassed, "cannot verify packet until time: %d, current time: %d",
- validTime, currentTimestamp)
- }
- // check that executing chain's height has passed consensusState's processed height + delay block period
- processedHeight, ok := GetProcessedHeight(store, proofHeight)
- if !ok {
- return sdkerrors.Wrapf(ErrProcessedHeightNotFound, "processed height not found for height: %s", proofHeight)
- }
- currentHeight := clienttypes.GetSelfHeight(ctx)
- validHeight := clienttypes.NewHeight(processedHeight.GetRevisionNumber(), processedHeight.GetRevisionHeight()+delayBlockPeriod)
- // NOTE: delay block period is inclusive, so if currentHeight is validHeight, then we return no error
- if currentHeight.LT(validHeight) {
- return sdkerrors.Wrapf(ErrDelayPeriodNotPassed, "cannot verify packet until height: %s, current height: %s",
- validHeight, currentHeight)
- }
- return nil
-}
-
-// produceVerificationArgs perfoms the basic checks on the arguments that are
-// shared between the verification functions and returns the unmarshalled
-// merkle proof, the consensus state and an error if one occurred.
-func produceVerificationArgs(
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- cs ClientState,
- height exported.Height,
- prefix exported.Prefix,
- proof []byte,
-) (merkleProof commitmenttypes.MerkleProof, consensusState *ConsensusState, err error) {
- if cs.GetLatestHeight().LT(height) {
- return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrapf(
- sdkerrors.ErrInvalidHeight,
- "client state height < proof height (%d < %d), please ensure the client has been updated", cs.GetLatestHeight(), height,
- )
- }
-
- if prefix == nil {
- return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrap(commitmenttypes.ErrInvalidPrefix, "prefix cannot be empty")
- }
-
- _, ok := prefix.(*commitmenttypes.MerklePrefix)
- if !ok {
- return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrapf(commitmenttypes.ErrInvalidPrefix, "invalid prefix type %T, expected *MerklePrefix", prefix)
- }
-
- if proof == nil {
- return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "proof cannot be empty")
- }
-
- if err = cdc.Unmarshal(proof, &merkleProof); err != nil {
- return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "failed to unmarshal proof into commitment merkle proof")
- }
-
- consensusState, err = GetConsensusState(store, cdc, height)
- if err != nil {
- return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrap(err, "please ensure the proof was constructed against a height that exists on the client")
- }
-
- return merkleProof, consensusState, nil
-}
diff --git a/modules/light-clients/07-tendermint/types/client_state_test.go b/modules/light-clients/07-tendermint/types/client_state_test.go
deleted file mode 100644
index 9c9a781fdb3..00000000000
--- a/modules/light-clients/07-tendermint/types/client_state_test.go
+++ /dev/null
@@ -1,880 +0,0 @@
-package types_test
-
-import (
- "time"
-
- ics23 "github.com/confio/ics23/go"
-
- clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
- commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
- host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
- ibctesting "github.com/cosmos/ibc-go/v5/testing"
- ibcmock "github.com/cosmos/ibc-go/v5/testing/mock"
-)
-
-const (
- testClientID = "clientidone"
- testConnectionID = "connectionid"
- testPortID = "testportid"
- testChannelID = "testchannelid"
- testSequence = 1
-
- // Do not change the length of these variables
- fiftyCharChainID = "12345678901234567890123456789012345678901234567890"
- fiftyOneCharChainID = "123456789012345678901234567890123456789012345678901"
-)
-
-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 without consensus state", func() {
- clientState.LatestHeight = clientState.LatestHeight.Increment().(clienttypes.Height)
- path.EndpointA.SetClientState(clientState)
- }, exported.Expired},
- {"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
- clientState *types.ClientState
- expPass bool
- }{
- {
- name: "valid client",
- clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- expPass: true,
- },
- {
- name: "valid client with nil upgrade path",
- clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), nil, false, false),
- expPass: true,
- },
- {
- name: "invalid chainID",
- clientState: types.NewClientState(" ", types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- expPass: false,
- },
- {
- // NOTE: if this test fails, the code must account for the change in chainID length across tendermint versions!
- // Do not only fix the test, fix the code!
- // https://github.com/cosmos/ibc-go/issues/177
- name: "valid chainID - chainID validation failed for chainID of length 50! ",
- clientState: types.NewClientState(fiftyCharChainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- expPass: true,
- },
- {
- // NOTE: if this test fails, the code must account for the change in chainID length across tendermint versions!
- // Do not only fix the test, fix the code!
- // https://github.com/cosmos/ibc-go/issues/177
- name: "invalid chainID - chainID validation did not fail for chainID of length 51! ",
- clientState: types.NewClientState(fiftyOneCharChainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- expPass: false,
- },
- {
- name: "invalid trust level",
- clientState: types.NewClientState(chainID, types.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- expPass: false,
- },
- {
- name: "invalid trusting period",
- clientState: types.NewClientState(chainID, types.DefaultTrustLevel, 0, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- expPass: false,
- },
- {
- name: "invalid unbonding period",
- clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, 0, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- expPass: false,
- },
- {
- name: "invalid max clock drift",
- clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, 0, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- expPass: false,
- },
- {
- name: "invalid revision number",
- clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(1, 1), commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- expPass: false,
- },
- {
- name: "invalid revision height",
- clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.ZeroHeight(), commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- expPass: false,
- },
- {
- name: "trusting period not less than unbonding period",
- clientState: types.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- expPass: false,
- },
- {
- name: "proof specs is nil",
- clientState: types.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, nil, upgradePath, false, false),
- expPass: false,
- },
- {
- name: "proof specs contains nil",
- clientState: types.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, []*ics23.ProofSpec{ics23.TendermintSpec, nil}, upgradePath, false, false),
- expPass: false,
- },
- }
-
- for _, tc := range testCases {
- err := tc.clientState.Validate()
- if tc.expPass {
- suite.Require().NoError(err, tc.name)
- } else {
- suite.Require().Error(err, tc.name)
- }
- }
-}
-
-func (suite *TendermintTestSuite) TestInitialize() {
- testCases := []struct {
- name string
- consensusState exported.ConsensusState
- expPass bool
- }{
- {
- name: "valid consensus",
- consensusState: &types.ConsensusState{},
- expPass: true,
- },
- {
- name: "invalid consensus: consensus state is solomachine consensus",
- consensusState: ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2).ConsensusState(),
- expPass: false,
- },
- }
-
- path := ibctesting.NewPath(suite.chainA, suite.chainB)
- err := path.EndpointA.CreateClient()
- suite.Require().NoError(err)
-
- clientState := suite.chainA.GetClientState(path.EndpointA.ClientID)
- store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
-
- for _, tc := range testCases {
- err := clientState.Initialize(suite.chainA.GetContext(), suite.chainA.Codec, store, tc.consensusState)
- if tc.expPass {
- suite.Require().NoError(err, "valid case returned an error")
- } else {
- suite.Require().Error(err, "invalid case didn't return an error")
- }
- }
-}
-
-func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
- testCases := []struct {
- name string
- clientState *types.ClientState
- consensusState *types.ConsensusState
- prefix commitmenttypes.MerklePrefix
- proof []byte
- expPass bool
- }{
- // FIXME: uncomment
- // {
- // name: "successful verification",
- // clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
- // consensusState: types.ConsensusState{
- // Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
- // },
- // prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
- // expPass: true,
- // },
- {
- name: "ApplyPrefix failed",
- clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- consensusState: &types.ConsensusState{
- Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
- },
- prefix: commitmenttypes.MerklePrefix{},
- expPass: false,
- },
- {
- name: "latest client height < height",
- clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- 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),
- consensusState: &types.ConsensusState{
- Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
- NextValidatorsHash: suite.valsHash,
- },
- prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
- proof: []byte{},
- expPass: false,
- },
- }
-
- for i, tc := range testCases {
- tc := tc
-
- err := tc.clientState.VerifyClientConsensusState(
- nil, suite.cdc, height, "chainA", tc.clientState.LatestHeight, tc.prefix, tc.proof, tc.consensusState,
- )
-
- if tc.expPass {
- suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
- } else {
- suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
- }
- }
-}
-
-// test verification of the connection on chainB being represented in the
-// light client on chainA
-func (suite *TendermintTestSuite) TestVerifyConnectionState() {
- var (
- clientState *types.ClientState
- proof []byte
- proofHeight exported.Height
- prefix commitmenttypes.MerklePrefix
- )
-
- testCases := []struct {
- name string
- malleate func()
- expPass bool
- }{
- {
- "successful verification", func() {}, true,
- },
- {
- "ApplyPrefix failed", func() {
- prefix = commitmenttypes.MerklePrefix{}
- }, false,
- },
- {
- "latest client height < height", func() {
- proofHeight = clientState.LatestHeight.Increment()
- }, false,
- },
- {
- "proof verification failed", func() {
- proof = invalidProof
- }, false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- suite.SetupTest() // reset
-
- // setup testing conditions
- path := ibctesting.NewPath(suite.chainA, suite.chainB)
- suite.coordinator.Setup(path)
- connection := path.EndpointB.GetConnection()
-
- var ok bool
- clientStateI := suite.chainA.GetClientState(path.EndpointA.ClientID)
- clientState, ok = clientStateI.(*types.ClientState)
- suite.Require().True(ok)
-
- prefix = suite.chainB.GetPrefix()
-
- // make connection proof
- connectionKey := host.ConnectionKey(path.EndpointB.ConnectionID)
- proof, proofHeight = suite.chainB.QueryProof(connectionKey)
-
- tc.malleate() // make changes as necessary
-
- store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
-
- err := clientState.VerifyConnectionState(
- store, suite.chainA.Codec, proofHeight, &prefix, proof, path.EndpointB.ConnectionID, connection,
- )
-
- if tc.expPass {
- suite.Require().NoError(err)
- } else {
- suite.Require().Error(err)
- }
- })
- }
-}
-
-// test verification of the channel on chainB being represented in the light
-// client on chainA
-func (suite *TendermintTestSuite) TestVerifyChannelState() {
- var (
- clientState *types.ClientState
- proof []byte
- proofHeight exported.Height
- prefix commitmenttypes.MerklePrefix
- )
-
- testCases := []struct {
- name string
- malleate func()
- expPass bool
- }{
- {
- "successful verification", func() {}, true,
- },
- {
- "ApplyPrefix failed", func() {
- prefix = commitmenttypes.MerklePrefix{}
- }, false,
- },
- {
- "latest client height < height", func() {
- proofHeight = clientState.LatestHeight.Increment()
- }, false,
- },
- {
- "proof verification failed", func() {
- proof = invalidProof
- }, false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- suite.SetupTest() // reset
-
- // setup testing conditions
- path := ibctesting.NewPath(suite.chainA, suite.chainB)
- suite.coordinator.Setup(path)
- channel := path.EndpointB.GetChannel()
-
- var ok bool
- clientStateI := suite.chainA.GetClientState(path.EndpointA.ClientID)
- clientState, ok = clientStateI.(*types.ClientState)
- suite.Require().True(ok)
-
- prefix = suite.chainB.GetPrefix()
-
- // make channel proof
- channelKey := host.ChannelKey(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
- proof, proofHeight = suite.chainB.QueryProof(channelKey)
-
- tc.malleate() // make changes as necessary
-
- store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
-
- err := clientState.VerifyChannelState(
- store, suite.chainA.Codec, proofHeight, &prefix, proof,
- path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, channel,
- )
-
- if tc.expPass {
- suite.Require().NoError(err)
- } else {
- suite.Require().Error(err)
- }
- })
- }
-}
-
-// test verification of the packet commitment on chainB being represented
-// in the light client on chainA. A send from chainB to chainA is simulated.
-func (suite *TendermintTestSuite) TestVerifyPacketCommitment() {
- var (
- clientState *types.ClientState
- proof []byte
- delayTimePeriod uint64
- delayBlockPeriod uint64
- proofHeight exported.Height
- prefix commitmenttypes.MerklePrefix
- )
-
- testCases := []struct {
- name string
- malleate func()
- expPass bool
- }{
- {
- "successful verification", func() {}, true,
- },
- {
- name: "delay time period has passed",
- malleate: func() {
- delayTimePeriod = uint64(time.Second.Nanoseconds())
- },
- expPass: true,
- },
- {
- name: "delay time period has not passed",
- malleate: func() {
- delayTimePeriod = uint64(time.Hour.Nanoseconds())
- },
- expPass: false,
- },
- {
- name: "delay block period has passed",
- malleate: func() {
- delayBlockPeriod = 1
- },
- expPass: true,
- },
- {
- name: "delay block period has not passed",
- malleate: func() {
- delayBlockPeriod = 1000
- },
- expPass: false,
- },
-
- {
- "ApplyPrefix failed", func() {
- prefix = commitmenttypes.MerklePrefix{}
- }, false,
- },
- {
- "latest client height < height", func() {
- proofHeight = clientState.LatestHeight.Increment()
- }, false,
- },
- {
- "proof verification failed", func() {
- proof = invalidProof
- }, false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- suite.SetupTest() // reset
-
- // setup testing conditions
- path := ibctesting.NewPath(suite.chainA, suite.chainB)
- suite.coordinator.Setup(path)
- packet := channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, clienttypes.NewHeight(0, 100), 0)
- err := path.EndpointB.SendPacket(packet)
- suite.Require().NoError(err)
-
- var ok bool
- clientStateI := suite.chainA.GetClientState(path.EndpointA.ClientID)
- clientState, ok = clientStateI.(*types.ClientState)
- suite.Require().True(ok)
-
- prefix = suite.chainB.GetPrefix()
-
- // make packet commitment proof
- packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
- proof, proofHeight = path.EndpointB.QueryProof(packetKey)
-
- // reset time and block delays to 0, malleate may change to a specific non-zero value.
- delayTimePeriod = 0
- delayBlockPeriod = 0
- tc.malleate() // make changes as necessary
-
- ctx := suite.chainA.GetContext()
- store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, path.EndpointA.ClientID)
-
- commitment := channeltypes.CommitPacket(suite.chainA.App.GetIBCKeeper().Codec(), packet)
- err = clientState.VerifyPacketCommitment(
- ctx, store, suite.chainA.Codec, proofHeight, delayTimePeriod, delayBlockPeriod, &prefix, proof,
- packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence(), commitment,
- )
-
- if tc.expPass {
- suite.Require().NoError(err)
- } else {
- suite.Require().Error(err)
- }
- })
- }
-}
-
-// test verification of the acknowledgement on chainB being represented
-// in the light client on chainA. A send and ack from chainA to chainB
-// is simulated.
-func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() {
- var (
- clientState *types.ClientState
- proof []byte
- delayTimePeriod uint64
- delayBlockPeriod uint64
- proofHeight exported.Height
- prefix commitmenttypes.MerklePrefix
- )
-
- testCases := []struct {
- name string
- malleate func()
- expPass bool
- }{
- {
- "successful verification", func() {}, true,
- },
- {
- name: "delay time period has passed",
- malleate: func() {
- delayTimePeriod = uint64(time.Second.Nanoseconds())
- },
- expPass: true,
- },
- {
- name: "delay time period has not passed",
- malleate: func() {
- delayTimePeriod = uint64(time.Hour.Nanoseconds())
- },
- expPass: false,
- },
- {
- name: "delay block period has passed",
- malleate: func() {
- delayBlockPeriod = 1
- },
- expPass: true,
- },
- {
- name: "delay block period has not passed",
- malleate: func() {
- delayBlockPeriod = 10
- },
- expPass: false,
- },
-
- {
- "ApplyPrefix failed", func() {
- prefix = commitmenttypes.MerklePrefix{}
- }, false,
- },
- {
- "latest client height < height", func() {
- proofHeight = clientState.LatestHeight.Increment()
- }, false,
- },
- {
- "proof verification failed", func() {
- proof = invalidProof
- }, false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- suite.SetupTest() // reset
-
- // setup testing conditions
- path := ibctesting.NewPath(suite.chainA, suite.chainB)
- suite.coordinator.Setup(path)
- packet := channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(0, 100), 0)
-
- // send packet
- err := path.EndpointA.SendPacket(packet)
- suite.Require().NoError(err)
-
- // write receipt and ack
- err = path.EndpointB.RecvPacket(packet)
- suite.Require().NoError(err)
-
- var ok bool
- clientStateI := suite.chainA.GetClientState(path.EndpointA.ClientID)
- clientState, ok = clientStateI.(*types.ClientState)
- suite.Require().True(ok)
-
- prefix = suite.chainB.GetPrefix()
-
- // make packet acknowledgement proof
- acknowledgementKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
- proof, proofHeight = suite.chainB.QueryProof(acknowledgementKey)
-
- // reset time and block delays to 0, malleate may change to a specific non-zero value.
- delayTimePeriod = 0
- delayBlockPeriod = 0
- tc.malleate() // make changes as necessary
-
- ctx := suite.chainA.GetContext()
- store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, path.EndpointA.ClientID)
-
- err = clientState.VerifyPacketAcknowledgement(
- ctx, store, suite.chainA.Codec, proofHeight, delayTimePeriod, delayBlockPeriod, &prefix, proof,
- packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), ibcmock.MockAcknowledgement.Acknowledgement(),
- )
-
- if tc.expPass {
- suite.Require().NoError(err)
- } else {
- suite.Require().Error(err)
- }
- })
- }
-}
-
-// test verification of the absent acknowledgement on chainB being represented
-// in the light client on chainA. A send from chainB to chainA is simulated, but
-// no receive.
-func (suite *TendermintTestSuite) TestVerifyPacketReceiptAbsence() {
- var (
- clientState *types.ClientState
- proof []byte
- delayTimePeriod uint64
- delayBlockPeriod uint64
- proofHeight exported.Height
- prefix commitmenttypes.MerklePrefix
- )
-
- testCases := []struct {
- name string
- malleate func()
- expPass bool
- }{
- {
- "successful verification", func() {}, true,
- },
- {
- name: "delay time period has passed",
- malleate: func() {
- delayTimePeriod = uint64(time.Second.Nanoseconds())
- },
- expPass: true,
- },
- {
- name: "delay time period has not passed",
- malleate: func() {
- delayTimePeriod = uint64(time.Hour.Nanoseconds())
- },
- expPass: false,
- },
- {
- name: "delay block period has passed",
- malleate: func() {
- delayBlockPeriod = 1
- },
- expPass: true,
- },
- {
- name: "delay block period has not passed",
- malleate: func() {
- delayBlockPeriod = 10
- },
- expPass: false,
- },
-
- {
- "ApplyPrefix failed", func() {
- prefix = commitmenttypes.MerklePrefix{}
- }, false,
- },
- {
- "latest client height < height", func() {
- proofHeight = clientState.LatestHeight.Increment()
- }, false,
- },
- {
- "proof verification failed", func() {
- proof = invalidProof
- }, false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- suite.SetupTest() // reset
-
- // setup testing conditions
- path := ibctesting.NewPath(suite.chainA, suite.chainB)
- suite.coordinator.Setup(path)
- packet := channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(0, 100), 0)
-
- // send packet, but no recv
- err := path.EndpointA.SendPacket(packet)
- suite.Require().NoError(err)
-
- var ok bool
- clientStateI := suite.chainA.GetClientState(path.EndpointA.ClientID)
- clientState, ok = clientStateI.(*types.ClientState)
- suite.Require().True(ok)
-
- prefix = suite.chainB.GetPrefix()
-
- // make packet receipt absence proof
- receiptKey := host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
- proof, proofHeight = path.EndpointB.QueryProof(receiptKey)
-
- // reset time and block delays to 0, malleate may change to a specific non-zero value.
- delayTimePeriod = 0
- delayBlockPeriod = 0
- tc.malleate() // make changes as necessary
-
- ctx := suite.chainA.GetContext()
- store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, path.EndpointA.ClientID)
-
- err = clientState.VerifyPacketReceiptAbsence(
- ctx, store, suite.chainA.Codec, proofHeight, delayTimePeriod, delayBlockPeriod, &prefix, proof,
- packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(),
- )
-
- if tc.expPass {
- suite.Require().NoError(err)
- } else {
- suite.Require().Error(err)
- }
- })
- }
-}
-
-// test verification of the next receive sequence on chainB being represented
-// in the light client on chainA. A send and receive from chainB to chainA is
-// simulated.
-func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() {
- var (
- clientState *types.ClientState
- proof []byte
- delayTimePeriod uint64
- delayBlockPeriod uint64
- proofHeight exported.Height
- prefix commitmenttypes.MerklePrefix
- )
-
- testCases := []struct {
- name string
- malleate func()
- expPass bool
- }{
- {
- "successful verification", func() {}, true,
- },
- {
- name: "delay time period has passed",
- malleate: func() {
- delayTimePeriod = uint64(time.Second.Nanoseconds())
- },
- expPass: true,
- },
- {
- name: "delay time period has not passed",
- malleate: func() {
- delayTimePeriod = uint64(time.Hour.Nanoseconds())
- },
- expPass: false,
- },
- {
- name: "delay block period has passed",
- malleate: func() {
- delayBlockPeriod = 1
- },
- expPass: true,
- },
- {
- name: "delay block period has not passed",
- malleate: func() {
- delayBlockPeriod = 10
- },
- expPass: false,
- },
-
- {
- "ApplyPrefix failed", func() {
- prefix = commitmenttypes.MerklePrefix{}
- }, false,
- },
- {
- "latest client height < height", func() {
- proofHeight = clientState.LatestHeight.Increment()
- }, false,
- },
- {
- "proof verification failed", func() {
- proof = invalidProof
- }, false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- suite.SetupTest() // reset
-
- // setup testing conditions
- path := ibctesting.NewPath(suite.chainA, suite.chainB)
- path.SetChannelOrdered()
- suite.coordinator.Setup(path)
- packet := channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(0, 100), 0)
-
- // send packet
- err := path.EndpointA.SendPacket(packet)
- suite.Require().NoError(err)
-
- // next seq recv incremented
- err = path.EndpointB.RecvPacket(packet)
- suite.Require().NoError(err)
-
- var ok bool
- clientStateI := suite.chainA.GetClientState(path.EndpointA.ClientID)
- clientState, ok = clientStateI.(*types.ClientState)
- suite.Require().True(ok)
-
- prefix = suite.chainB.GetPrefix()
-
- // make next seq recv proof
- nextSeqRecvKey := host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel())
- proof, proofHeight = suite.chainB.QueryProof(nextSeqRecvKey)
-
- // reset time and block delays to 0, malleate may change to a specific non-zero value.
- delayTimePeriod = 0
- delayBlockPeriod = 0
- tc.malleate() // make changes as necessary
-
- ctx := suite.chainA.GetContext()
- store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, path.EndpointA.ClientID)
-
- err = clientState.VerifyNextSequenceRecv(
- ctx, store, suite.chainA.Codec, proofHeight, delayTimePeriod, delayBlockPeriod, &prefix, proof,
- packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()+1,
- )
-
- if tc.expPass {
- suite.Require().NoError(err)
- } else {
- suite.Require().Error(err)
- }
- })
- }
-}
diff --git a/modules/light-clients/07-tendermint/types/misbehaviour_handle_test.go b/modules/light-clients/07-tendermint/types/misbehaviour_handle_test.go
deleted file mode 100644
index 6e699dcaa49..00000000000
--- a/modules/light-clients/07-tendermint/types/misbehaviour_handle_test.go
+++ /dev/null
@@ -1,425 +0,0 @@
-package types_test
-
-import (
- "fmt"
- "time"
-
- "github.com/tendermint/tendermint/crypto/tmhash"
- tmtypes "github.com/tendermint/tendermint/types"
-
- clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
- ibctestingmock "github.com/cosmos/ibc-go/v5/testing/mock"
-)
-
-func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
- altPrivVal := ibctestingmock.NewPV()
- altPubKey, err := altPrivVal.GetPubKey()
- suite.Require().NoError(err)
-
- altVal := tmtypes.NewValidator(altPubKey, 4)
-
- // Create alternative validator set with only altVal
- altValSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{altVal})
-
- // Create bothValSet with both suite validator and altVal
- bothValSet, bothSigners := getBothSigners(suite, altVal, altPrivVal)
- bothValsHash := bothValSet.Hash()
-
- altSigners := getAltSigners(altVal, altPrivVal)
-
- heightMinus1 := clienttypes.NewHeight(height.RevisionNumber, height.RevisionHeight-1)
- heightMinus3 := clienttypes.NewHeight(height.RevisionNumber, height.RevisionHeight-3)
-
- testCases := []struct {
- name string
- clientState exported.ClientState
- consensusState1 exported.ConsensusState
- height1 clienttypes.Height
- consensusState2 exported.ConsensusState
- height2 clienttypes.Height
- misbehaviour exported.Misbehaviour
- timestamp time.Time
- expPass bool
- }{
- {
- "valid fork misbehaviour",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- true,
- },
- {
- "valid time misbehaviour",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+3), height, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- true,
- },
- {
- "valid time misbehaviour header 1 stricly less than header 2",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+3), height, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now.Add(time.Hour), bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- true,
- },
- {
- "valid misbehavior at height greater than last consensusState",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- heightMinus1,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- heightMinus1,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), heightMinus1, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), heightMinus1, suite.now.Add(time.Minute), bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- true,
- },
- {
- "valid misbehaviour with different trusted heights",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- heightMinus1,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
- heightMinus3,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), heightMinus1, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), heightMinus3, suite.now.Add(time.Minute), bothValSet, bothValSet, suite.valSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- true,
- },
- {
- "valid misbehaviour at a previous revision",
- types.NewClientState(chainIDRevision1, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(1, 1), commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- heightMinus1,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
- heightMinus3,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainIDRevision0, int64(height.RevisionHeight+1), heightMinus1, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainIDRevision0, int64(height.RevisionHeight+1), heightMinus3, suite.now.Add(time.Minute), bothValSet, bothValSet, suite.valSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- true,
- },
- {
- "valid misbehaviour at a future revision",
- types.NewClientState(chainIDRevision0, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- heightMinus1,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
- heightMinus3,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainIDRevision0, 3, heightMinus1, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainIDRevision0, 3, heightMinus3, suite.now.Add(time.Minute), bothValSet, bothValSet, suite.valSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- true,
- },
- {
- "valid misbehaviour with trusted heights at a previous revision",
- types.NewClientState(chainIDRevision1, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(1, 1), commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- heightMinus1,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
- heightMinus3,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainIDRevision1, 1, heightMinus1, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainIDRevision1, 1, heightMinus3, suite.now.Add(time.Minute), bothValSet, bothValSet, suite.valSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- true,
- },
- {
- "consensus state's valset hash different from misbehaviour should still pass",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
- height,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
- height,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now, bothValSet, bothValSet, suite.valSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now.Add(time.Minute), bothValSet, bothValSet, suite.valSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- true,
- },
- {
- "invalid fork misbehaviour: identical headers",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- false,
- },
- {
- "invalid time misbehaviour: monotonically increasing time",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+3), height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- false,
- },
- {
- "invalid misbehavior misbehaviour from different chain",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader("ethermint", int64(height.RevisionHeight+1), height, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader("ethermint", int64(height.RevisionHeight+1), height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- false,
- },
- {
- "invalid misbehavior misbehaviour with trusted height different from trusted consensus state",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- heightMinus1,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
- heightMinus3,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), heightMinus1, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now.Add(time.Minute), bothValSet, bothValSet, suite.valSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- false,
- },
- {
- "invalid misbehavior misbehaviour with trusted validators different from trusted consensus state",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- heightMinus1,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
- heightMinus3,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), heightMinus1, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), heightMinus3, suite.now.Add(time.Minute), bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- false,
- },
- {
- "already frozen client state",
- &types.ClientState{FrozenHeight: clienttypes.NewHeight(0, 1)},
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- false,
- },
- {
- "trusted consensus state does not exist",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- nil, // consensus state for trusted height - 1 does not exist in store
- clienttypes.Height{},
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), heightMinus1, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- false,
- },
- {
- "invalid tendermint misbehaviour",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- nil,
- suite.now,
- false,
- },
- {
- "provided height > header height",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), heightMinus1, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), heightMinus1, suite.now.Add(time.Minute), bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- false,
- },
- {
- "trusting period expired",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(time.Time{}, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- heightMinus1,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), heightMinus1, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: chainID,
- },
- suite.now.Add(trustingPeriod),
- false,
- },
- {
- "trusted validators is incorrect for given consensus state",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now, bothValSet, bothValSet, suite.valSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now.Add(time.Minute), bothValSet, bothValSet, suite.valSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- false,
- },
- {
- "first valset has too much change",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now, altValSet, altValSet, bothValSet, altSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothValSet, bothSigners),
- ClientId: chainID,
- },
- suite.now,
- false,
- },
- {
- "second valset has too much change",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now, bothValSet, bothValSet, bothValSet, bothSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now.Add(time.Minute), altValSet, altValSet, bothValSet, altSigners),
- ClientId: chainID,
- },
- suite.now,
- false,
- },
- {
- "both valsets have too much change",
- types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false),
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
- height,
- &types.Misbehaviour{
- Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now, altValSet, altValSet, bothValSet, altSigners),
- Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight+1), height, suite.now.Add(time.Minute), altValSet, altValSet, bothValSet, altSigners),
- ClientId: chainID,
- },
- suite.now,
- false,
- },
- }
-
- for i, tc := range testCases {
- tc := tc
- suite.Run(fmt.Sprintf("Case: %s", tc.name), func() {
- // reset suite to create fresh application state
- suite.SetupTest()
-
- // Set current timestamp in context
- ctx := suite.chainA.GetContext().WithBlockTime(tc.timestamp)
-
- // Set trusted consensus states in client store
-
- if tc.consensusState1 != nil {
- suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(ctx, clientID, tc.height1, tc.consensusState1)
- }
- if tc.consensusState2 != nil {
- suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(ctx, clientID, tc.height2, tc.consensusState2)
- }
-
- clientState, err := tc.clientState.CheckMisbehaviourAndUpdateState(
- ctx,
- suite.chainA.App.AppCodec(),
- suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, clientID), // pass in clientID prefixed clientStore
- tc.misbehaviour,
- )
-
- 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.(*types.ClientState).FrozenHeight.IsZero(), "valid test case %d failed: %s", i, tc.name)
- } else {
- suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
- suite.Require().Nil(clientState, "invalid test case %d passed: %s", i, tc.name)
- }
- })
- }
-}
diff --git a/modules/light-clients/07-tendermint/types/update_test.go b/modules/light-clients/07-tendermint/types/update_test.go
deleted file mode 100644
index aaf1936d8d7..00000000000
--- a/modules/light-clients/07-tendermint/types/update_test.go
+++ /dev/null
@@ -1,450 +0,0 @@
-package types_test
-
-import (
- "fmt"
- "time"
-
- tmtypes "github.com/tendermint/tendermint/types"
-
- clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
- types "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
- ibctesting "github.com/cosmos/ibc-go/v5/testing"
- ibctestingmock "github.com/cosmos/ibc-go/v5/testing/mock"
-)
-
-func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
- var (
- clientState *types.ClientState
- consensusState *types.ConsensusState
- consStateHeight clienttypes.Height
- newHeader *types.Header
- currentTime time.Time
- bothValSet *tmtypes.ValidatorSet
- bothSigners map[string]tmtypes.PrivValidator
- )
-
- // Setup different validators and signers for testing different types of updates
- altPrivVal := ibctestingmock.NewPV()
- altPubKey, err := altPrivVal.GetPubKey()
- suite.Require().NoError(err)
-
- revisionHeight := int64(height.RevisionHeight)
-
- // create modified heights to use for test-cases
- heightPlus1 := clienttypes.NewHeight(height.RevisionNumber, height.RevisionHeight+1)
- heightMinus1 := clienttypes.NewHeight(height.RevisionNumber, height.RevisionHeight-1)
- heightMinus3 := clienttypes.NewHeight(height.RevisionNumber, height.RevisionHeight-3)
- heightPlus5 := clienttypes.NewHeight(height.RevisionNumber, height.RevisionHeight+5)
-
- altVal := tmtypes.NewValidator(altPubKey, revisionHeight)
- // Create alternative validator set with only altVal, invalid update (too much change in valSet)
- altValSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{altVal})
- altSigners := getAltSigners(altVal, altPrivVal)
-
- testCases := []struct {
- name string
- setup func(*TendermintTestSuite)
- expFrozen bool
- expPass bool
- }{
- {
- name: "successful update with next height and same validator set",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.headerTime, suite.valSet, suite.valSet, suite.valSet, suite.signers)
- currentTime = suite.now
- },
- expFrozen: false,
- expPass: true,
- },
- {
- name: "successful update with future height and different validator set",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus5.RevisionHeight), height, suite.headerTime, bothValSet, bothValSet, suite.valSet, bothSigners)
- currentTime = suite.now
- },
- expFrozen: false,
- expPass: true,
- },
- {
- name: "successful update with next height and different validator set",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), bothValSet.Hash())
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.headerTime, bothValSet, bothValSet, bothValSet, bothSigners)
- currentTime = suite.now
- },
- expFrozen: false,
- expPass: true,
- },
- {
- name: "successful update for a previous height",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- consStateHeight = heightMinus3
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightMinus1.RevisionHeight), heightMinus3, suite.headerTime, bothValSet, bothValSet, suite.valSet, bothSigners)
- currentTime = suite.now
- },
- expFrozen: false,
- expPass: true,
- },
- {
- name: "successful update for a previous revision",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainIDRevision1, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- consStateHeight = heightMinus3
- newHeader = suite.chainA.CreateTMClientHeader(chainIDRevision0, int64(height.RevisionHeight), heightMinus3, suite.headerTime, bothValSet, bothValSet, suite.valSet, bothSigners)
- currentTime = suite.now
- },
- expPass: true,
- },
- {
- name: "successful update with identical header to a previous update",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, heightPlus1, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.headerTime, suite.valSet, suite.valSet, suite.valSet, suite.signers)
- currentTime = suite.now
- ctx := suite.chainA.GetContext().WithBlockTime(currentTime)
- // Store the header's consensus state in client store before UpdateClient call
- suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(ctx, clientID, heightPlus1, newHeader.ConsensusState())
- },
- expFrozen: false,
- expPass: true,
- },
- {
- name: "misbehaviour detection: header conflicts with existing consensus state",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, heightPlus1, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.headerTime, suite.valSet, suite.valSet, suite.valSet, suite.signers)
- currentTime = suite.now
- ctx := suite.chainA.GetContext().WithBlockTime(currentTime)
- // Change the consensus state of header and store in client store to create a conflict
- conflictConsState := newHeader.ConsensusState()
- conflictConsState.Root = commitmenttypes.NewMerkleRoot([]byte("conflicting apphash"))
- suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(ctx, clientID, heightPlus1, conflictConsState)
- },
- expFrozen: true,
- expPass: true,
- },
- {
- name: "misbehaviour detection: previous consensus state time is not before header time. time monotonicity violation",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- // create an intermediate consensus state with the same time as the newHeader to create a time violation.
- // header time is after client time
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus5.RevisionHeight), height, suite.headerTime, suite.valSet, suite.valSet, suite.valSet, suite.signers)
- currentTime = suite.now
- prevConsensusState := types.NewConsensusState(suite.headerTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- ctx := suite.chainA.GetContext().WithBlockTime(currentTime)
- suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(ctx, clientID, heightPlus1, prevConsensusState)
- clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, clientID)
- types.SetIterationKey(clientStore, heightPlus1)
- },
- expFrozen: true,
- expPass: true,
- },
- {
- name: "misbehaviour detection: next consensus state time is not after header time. time monotonicity violation",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- // create the next consensus state with the same time as the intermediate newHeader to create a time violation.
- // header time is after clientTime
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.headerTime, suite.valSet, suite.valSet, suite.valSet, suite.signers)
- currentTime = suite.now
- nextConsensusState := types.NewConsensusState(suite.headerTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- ctx := suite.chainA.GetContext().WithBlockTime(currentTime)
- suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(ctx, clientID, heightPlus5, nextConsensusState)
- clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, clientID)
- types.SetIterationKey(clientStore, heightPlus5)
- },
- expFrozen: true,
- expPass: true,
- },
- {
- name: "unsuccessful update with incorrect header chain-id",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader("ethermint", int64(heightPlus1.RevisionHeight), height, suite.headerTime, suite.valSet, suite.valSet, suite.valSet, suite.signers)
- currentTime = suite.now
- },
- expFrozen: false,
- expPass: false,
- },
- {
- name: "unsuccessful update to a future revision",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainIDRevision0, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader(chainIDRevision1, 1, height, suite.headerTime, suite.valSet, suite.valSet, suite.valSet, suite.signers)
- currentTime = suite.now
- },
- expPass: false,
- },
- {
- name: "unsuccessful update: header height revision and trusted height revision mismatch",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainIDRevision1, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(1, 1), commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader(chainIDRevision1, 3, height, suite.headerTime, suite.valSet, suite.valSet, suite.valSet, suite.signers)
- currentTime = suite.now
- },
- expFrozen: false,
- expPass: false,
- },
- {
- name: "unsuccessful update with next height: update header mismatches nextValSetHash",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.headerTime, bothValSet, bothValSet, suite.valSet, bothSigners)
- currentTime = suite.now
- },
- expFrozen: false,
- expPass: false,
- },
- {
- name: "unsuccessful update with next height: update header mismatches different nextValSetHash",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), bothValSet.Hash())
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.headerTime, suite.valSet, suite.valSet, bothValSet, suite.signers)
- currentTime = suite.now
- },
- expFrozen: false,
- expPass: false,
- },
- {
- name: "unsuccessful update with future height: too much change in validator set",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus5.RevisionHeight), height, suite.headerTime, altValSet, altValSet, suite.valSet, altSigners)
- currentTime = suite.now
- },
- expFrozen: false,
- expPass: false,
- },
- {
- name: "unsuccessful updates, passed in incorrect trusted validators for given consensus state",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus5.RevisionHeight), height, suite.headerTime, bothValSet, bothValSet, bothValSet, bothSigners)
- currentTime = suite.now
- },
- expFrozen: false,
- expPass: false,
- },
- {
- name: "unsuccessful update: trusting period has passed since last client timestamp",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.headerTime, suite.valSet, suite.valSet, suite.valSet, suite.signers)
- // make current time pass trusting period from last timestamp on clientstate
- currentTime = suite.now.Add(trustingPeriod)
- },
- expFrozen: false,
- expPass: false,
- },
- {
- name: "unsuccessful update: header timestamp is past current timestamp",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.now.Add(time.Minute), suite.valSet, suite.valSet, suite.valSet, suite.signers)
- currentTime = suite.now
- },
- expFrozen: false,
- expPass: false,
- },
- {
- name: "unsuccessful update: header timestamp is not past last client timestamp",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.clientTime, suite.valSet, suite.valSet, suite.valSet, suite.signers)
- currentTime = suite.now
- },
- expFrozen: false,
- expPass: false,
- },
- {
- name: "header basic validation failed",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.headerTime, suite.valSet, suite.valSet, suite.valSet, suite.signers)
- // cause new header to fail validatebasic by changing commit height to mismatch header height
- newHeader.SignedHeader.Commit.Height = revisionHeight - 1
- currentTime = suite.now
- },
- expFrozen: false,
- expPass: false,
- },
- {
- name: "header height < consensus height",
- setup: func(suite *TendermintTestSuite) {
- clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(height.RevisionNumber, heightPlus5.RevisionHeight), commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
- consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
- // Make new header at height less than latest client state
- newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightMinus1.RevisionHeight), height, suite.headerTime, suite.valSet, suite.valSet, suite.valSet, suite.signers)
- currentTime = suite.now
- },
- expFrozen: false,
- expPass: false,
- },
- }
-
- for i, tc := range testCases {
- tc := tc
- suite.Run(fmt.Sprintf("Case: %s", tc.name), func() {
- suite.SetupTest() // reset metadata writes
- // Create bothValSet with both suite validator and altVal. Would be valid update
- bothValSet, bothSigners = getBothSigners(suite, altVal, altPrivVal)
-
- consStateHeight = height // must be explicitly changed
- // setup test
- tc.setup(suite)
-
- // Set current timestamp in context
- ctx := suite.chainA.GetContext().WithBlockTime(currentTime)
-
- // Set trusted consensus state in client store
- suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(ctx, clientID, consStateHeight, consensusState)
-
- height := newHeader.GetHeight()
- expectedConsensus := &types.ConsensusState{
- Timestamp: newHeader.GetTime(),
- Root: commitmenttypes.NewMerkleRoot(newHeader.Header.GetAppHash()),
- NextValidatorsHash: newHeader.Header.NextValidatorsHash,
- }
-
- newClientState, consensusState, err := clientState.CheckHeaderAndUpdateState(
- ctx,
- suite.cdc,
- suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), clientID), // pass in clientID prefixed clientStore
- newHeader,
- )
-
- if tc.expPass {
- suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
-
- suite.Require().Equal(tc.expFrozen, !newClientState.(*types.ClientState).FrozenHeight.IsZero(), "client state status is unexpected after update")
-
- // further writes only happen if update is not misbehaviour
- if !tc.expFrozen {
- // Determine if clientState should be updated or not
- // TODO: check the entire Height struct once GetLatestHeight returns clienttypes.Height
- if height.GT(clientState.LatestHeight) {
- // Header Height is greater than clientState latest Height, clientState should be updated with header.GetHeight()
- suite.Require().Equal(height, newClientState.GetLatestHeight(), "clientstate height did not update")
- } else {
- // Update will add past consensus state, clientState should not be updated at all
- suite.Require().Equal(clientState.LatestHeight, newClientState.GetLatestHeight(), "client state height updated for past header")
- }
-
- suite.Require().Equal(expectedConsensus, consensusState, "valid test case %d failed: %s", i, tc.name)
- }
- } else {
- suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
- suite.Require().Nil(newClientState, "invalid test case %d passed: %s", i, tc.name)
- suite.Require().Nil(consensusState, "invalid test case %d passed: %s", i, tc.name)
- }
- })
- }
-}
-
-func (suite *TendermintTestSuite) TestPruneConsensusState() {
- // create path and setup clients
- path := ibctesting.NewPath(suite.chainA, suite.chainB)
- suite.coordinator.SetupClients(path)
-
- // get the first height as it will be pruned first.
- var pruneHeight exported.Height
- getFirstHeightCb := func(height exported.Height) bool {
- pruneHeight = height
- return true
- }
- ctx := path.EndpointA.Chain.GetContext()
- clientStore := path.EndpointA.Chain.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, path.EndpointA.ClientID)
- err := types.IterateConsensusStateAscending(clientStore, getFirstHeightCb)
- suite.Require().Nil(err)
-
- // this height will be expired but not pruned
- path.EndpointA.UpdateClient()
- expiredHeight := path.EndpointA.GetClientState().GetLatestHeight()
-
- // expected values that must still remain in store after pruning
- expectedConsState, ok := path.EndpointA.Chain.GetConsensusState(path.EndpointA.ClientID, expiredHeight)
- suite.Require().True(ok)
- ctx = path.EndpointA.Chain.GetContext()
- clientStore = path.EndpointA.Chain.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, path.EndpointA.ClientID)
- expectedProcessTime, ok := types.GetProcessedTime(clientStore, expiredHeight)
- suite.Require().True(ok)
- expectedProcessHeight, ok := types.GetProcessedHeight(clientStore, expiredHeight)
- suite.Require().True(ok)
- expectedConsKey := types.GetIterationKey(clientStore, expiredHeight)
- suite.Require().NotNil(expectedConsKey)
-
- // Increment the time by a week
- suite.coordinator.IncrementTimeBy(7 * 24 * time.Hour)
-
- // create the consensus state that can be used as trusted height for next update
- path.EndpointA.UpdateClient()
-
- // Increment the time by another week, then update the client.
- // This will cause the first two consensus states to become expired.
- suite.coordinator.IncrementTimeBy(7 * 24 * time.Hour)
- path.EndpointA.UpdateClient()
-
- ctx = path.EndpointA.Chain.GetContext()
- clientStore = path.EndpointA.Chain.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, path.EndpointA.ClientID)
-
- // check that the first expired consensus state got deleted along with all associated metadata
- consState, ok := path.EndpointA.Chain.GetConsensusState(path.EndpointA.ClientID, pruneHeight)
- suite.Require().Nil(consState, "expired consensus state not pruned")
- suite.Require().False(ok)
- // check processed time metadata is pruned
- processTime, ok := types.GetProcessedTime(clientStore, pruneHeight)
- suite.Require().Equal(uint64(0), processTime, "processed time metadata not pruned")
- suite.Require().False(ok)
- processHeight, ok := types.GetProcessedHeight(clientStore, pruneHeight)
- suite.Require().Nil(processHeight, "processed height metadata not pruned")
- suite.Require().False(ok)
-
- // check iteration key metadata is pruned
- consKey := types.GetIterationKey(clientStore, pruneHeight)
- suite.Require().Nil(consKey, "iteration key not pruned")
-
- // check that second expired consensus state doesn't get deleted
- // this ensures that there is a cap on gas cost of UpdateClient
- consState, ok = path.EndpointA.Chain.GetConsensusState(path.EndpointA.ClientID, expiredHeight)
- suite.Require().Equal(expectedConsState, consState, "consensus state incorrectly pruned")
- suite.Require().True(ok)
- // check processed time metadata is not pruned
- processTime, ok = types.GetProcessedTime(clientStore, expiredHeight)
- suite.Require().Equal(expectedProcessTime, processTime, "processed time metadata incorrectly pruned")
- suite.Require().True(ok)
-
- // check processed height metadata is not pruned
- processHeight, ok = types.GetProcessedHeight(clientStore, expiredHeight)
- suite.Require().Equal(expectedProcessHeight, processHeight, "processed height metadata incorrectly pruned")
- suite.Require().True(ok)
-
- // check iteration key metadata is not pruned
- consKey = types.GetIterationKey(clientStore, expiredHeight)
- suite.Require().Equal(expectedConsKey, consKey, "iteration key incorrectly pruned")
-}
diff --git a/modules/light-clients/07-tendermint/types/update.go b/modules/light-clients/07-tendermint/update.go
similarity index 50%
rename from modules/light-clients/07-tendermint/types/update.go
rename to modules/light-clients/07-tendermint/update.go
index 90243235a52..32b5857ad19 100644
--- a/modules/light-clients/07-tendermint/types/update.go
+++ b/modules/light-clients/07-tendermint/update.go
@@ -1,9 +1,9 @@
-package types
+package tendermint
import (
"bytes"
+ "fmt"
"reflect"
- "time"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
@@ -13,13 +13,26 @@ import (
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
+ host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
)
-// CheckHeaderAndUpdateState checks if the provided header is valid, and if valid it will:
-// create the consensus state for the header.Height
-// and update the client state if the header height is greater than the latest client state height
-// It returns an error if:
+// VerifyClientMessage checks if the clientMessage is of type Header or Misbehaviour and verifies the message
+func (cs *ClientState) VerifyClientMessage(
+ ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore,
+ clientMsg exported.ClientMessage,
+) error {
+ switch msg := clientMsg.(type) {
+ case *Header:
+ return cs.verifyHeader(ctx, clientStore, cdc, msg)
+ case *Misbehaviour:
+ return cs.verifyMisbehaviour(ctx, clientStore, cdc, msg)
+ default:
+ return clienttypes.ErrInvalidClientType
+ }
+}
+
+// verifyHeader returns an error if:
// - the client or header provided are not parseable to tendermint types
// - the header is invalid
// - header height is less than or equal to the trusted header height
@@ -27,150 +40,18 @@ import (
// - header valset commit verification fails
// - header timestamp is past the trusting period in relation to the consensus state
// - header timestamp is less than or equal to the consensus state timestamp
-//
-// UpdateClient may be used to either create a consensus state for:
-// - a future height greater than the latest client state height
-// - a past height that was skipped during bisection
-// If we are updating to a past height, a consensus state is created for that height to be persisted in client store
-// If we are updating to a future height, the consensus state is created and the client state is updated to reflect
-// the new latest height
-// UpdateClient must only be used to update within a single revision, thus header revision number and trusted height's revision
-// number must be the same. To update to a new revision, use a separate upgrade path
-// Tendermint client validity checking uses the bisection algorithm described
-// in the [Tendermint spec](https://github.com/tendermint/spec/blob/master/spec/consensus/light-client.md).
-//
-// Misbehaviour Detection:
-// UpdateClient will detect implicit misbehaviour by enforcing certain invariants on any new update call and will return a frozen client.
-// 1. Any valid update that creates a different consensus state for an already existing height is evidence of misbehaviour and will freeze client.
-// 2. Any valid update that breaks time monotonicity with respect to its neighboring consensus states is evidence of misbehaviour and will freeze client.
-// Misbehaviour sets frozen height to {0, 1} since it is only used as a boolean value (zero or non-zero).
-//
-// Pruning:
-// UpdateClient will additionally retrieve the earliest consensus state for this clientID and check if it is expired. If it is,
-// that consensus state will be pruned from store along with all associated metadata. This will prevent the client store from
-// becoming bloated with expired consensus states that can no longer be used for updates and packet verification.
-func (cs ClientState) CheckHeaderAndUpdateState(
- ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore,
- header exported.Header,
-) (exported.ClientState, exported.ConsensusState, error) {
- tmHeader, ok := header.(*Header)
- if !ok {
- return nil, nil, sdkerrors.Wrapf(
- clienttypes.ErrInvalidHeader, "expected type %T, got %T", &Header{}, header,
- )
- }
-
- // Check if the Client store already has a consensus state for the header's height
- // If the consensus state exists, and it matches the header then we return early
- // since header has already been submitted in a previous UpdateClient.
- var conflictingHeader bool
- prevConsState, _ := GetConsensusState(clientStore, cdc, header.GetHeight())
- if prevConsState != nil {
- // This header has already been submitted and the necessary state is already stored
- // in client store, thus we can return early without further validation.
- if reflect.DeepEqual(prevConsState, tmHeader.ConsensusState()) {
- return &cs, prevConsState, nil
- }
- // A consensus state already exists for this height, but it does not match the provided header.
- // Thus, we must check that this header is valid, and if so we will freeze the client.
- conflictingHeader = true
- }
-
- // get consensus state from clientStore
- trustedConsState, err := GetConsensusState(clientStore, cdc, tmHeader.TrustedHeight)
- if err != nil {
- return nil, nil, sdkerrors.Wrapf(
- err, "could not get consensus state from clientstore at TrustedHeight: %s", tmHeader.TrustedHeight,
- )
- }
-
- if err := checkValidity(&cs, trustedConsState, tmHeader, ctx.BlockTime()); err != nil {
- return nil, nil, err
- }
-
- consState := tmHeader.ConsensusState()
- // Header is different from existing consensus state and also valid, so freeze the client and return
- if conflictingHeader {
- cs.FrozenHeight = FrozenHeight
- return &cs, consState, nil
- }
- // Check that consensus state timestamps are monotonic
- prevCons, prevOk := GetPreviousConsensusState(clientStore, cdc, header.GetHeight())
- nextCons, nextOk := GetNextConsensusState(clientStore, cdc, header.GetHeight())
- // if previous consensus state exists, check consensus state time is greater than previous consensus state time
- // if previous consensus state is not before current consensus state, freeze the client and return.
- if prevOk && !prevCons.Timestamp.Before(consState.Timestamp) {
- cs.FrozenHeight = FrozenHeight
- return &cs, consState, nil
- }
- // if next consensus state exists, check consensus state time is less than next consensus state time
- // if next consensus state is not after current consensus state, freeze the client and return.
- if nextOk && !nextCons.Timestamp.After(consState.Timestamp) {
- cs.FrozenHeight = FrozenHeight
- return &cs, consState, nil
- }
-
- // Check the earliest consensus state to see if it is expired, if so then set the prune height
- // so that we can delete consensus state and all associated metadata.
- var (
- pruneHeight exported.Height
- pruneError error
- )
- pruneCb := func(height exported.Height) bool {
- consState, err := GetConsensusState(clientStore, cdc, height)
- // this error should never occur
- if err != nil {
- pruneError = err
- return true
- }
- if cs.IsExpired(consState.Timestamp, ctx.BlockTime()) {
- pruneHeight = height
- }
- return true
- }
- err = IterateConsensusStateAscending(clientStore, pruneCb)
- if err != nil {
- return nil, nil, err
- }
- if pruneError != nil {
- return nil, nil, pruneError
- }
- // if pruneHeight is set, delete consensus state and metadata
- if pruneHeight != nil {
- deleteConsensusState(clientStore, pruneHeight)
- deleteConsensusMetadata(clientStore, pruneHeight)
- }
-
- newClientState, consensusState := update(ctx, clientStore, &cs, tmHeader)
- return newClientState, consensusState, nil
-}
-
-// checkTrustedHeader checks that consensus state matches trusted fields of Header
-func checkTrustedHeader(header *Header, consState *ConsensusState) error {
- tmTrustedValidators, err := tmtypes.ValidatorSetFromProto(header.TrustedValidators)
- if err != nil {
- return sdkerrors.Wrap(err, "trusted validator set in not tendermint validator set type")
- }
+func (cs *ClientState) verifyHeader(
+ ctx sdk.Context, clientStore sdk.KVStore, cdc codec.BinaryCodec,
+ header *Header,
+) error {
+ currentTimestamp := ctx.BlockTime()
- // assert that trustedVals is NextValidators of last trusted header
- // to do this, we check that trustedVals.Hash() == consState.NextValidatorsHash
- tvalHash := tmTrustedValidators.Hash()
- if !bytes.Equal(consState.NextValidatorsHash, tvalHash) {
- return sdkerrors.Wrapf(
- ErrInvalidValidatorSet,
- "trusted validators %s, does not hash to latest trusted validators. Expected: %X, got: %X",
- header.TrustedValidators, consState.NextValidatorsHash, tvalHash,
- )
+ // Retrieve trusted consensus states for each Header in misbehaviour
+ consState, found := GetConsensusState(clientStore, cdc, header.TrustedHeight)
+ if !found {
+ return sdkerrors.Wrapf(clienttypes.ErrConsensusStateNotFound, "could not get trusted consensus state from clientStore for Header at TrustedHeight: %s", header.TrustedHeight)
}
- return nil
-}
-// checkValidity checks if the Tendermint header is valid.
-// CONTRACT: consState.Height == header.TrustedHeight
-func checkValidity(
- clientState *ClientState, consState *ConsensusState,
- header *Header, currentTimestamp time.Time,
-) error {
if err := checkTrustedHeader(header, consState); err != nil {
return err
}
@@ -208,21 +89,11 @@ func checkValidity(
)
}
- chainID := clientState.GetChainID()
- // If chainID is in revision format, then set revision number of chainID with the revision number
- // of the header we are verifying
- // This is useful if the update is at a previous revision rather than an update to the latest revision
- // of the client.
- // The chainID must be set correctly for the previous revision before attempting verification.
- // Updates for previous revisions are not supported if the chainID is not in revision format.
- if clienttypes.IsRevisionFormat(chainID) {
- chainID, _ = clienttypes.SetRevisionNumber(chainID, header.GetHeight().GetRevisionNumber())
- }
-
// Construct a trusted header using the fields in consensus state
// Only Height, Time, and NextValidatorsHash are necessary for verification
+ // NOTE: updates must be within the same revision
trustedHeader := tmtypes.Header{
- ChainID: chainID,
+ ChainID: cs.GetChainID(),
Height: int64(header.TrustedHeight.RevisionHeight),
Time: consState.Timestamp,
NextValidatorsHash: consState.NextValidatorsHash,
@@ -239,28 +110,160 @@ func checkValidity(
err = light.Verify(
&signedHeader,
tmTrustedValidators, tmSignedHeader, tmValidatorSet,
- clientState.TrustingPeriod, currentTimestamp, clientState.MaxClockDrift, clientState.TrustLevel.ToTendermint(),
+ cs.TrustingPeriod, currentTimestamp, cs.MaxClockDrift, cs.TrustLevel.ToTendermint(),
)
if err != nil {
return sdkerrors.Wrap(err, "failed to verify header")
}
+
return nil
}
-// update the consensus state from a new header and set processed time metadata
-func update(ctx sdk.Context, clientStore sdk.KVStore, clientState *ClientState, header *Header) (*ClientState, *ConsensusState) {
+// UpdateState may be used to either create a consensus state for:
+// - a future height greater than the latest client state height
+// - a past height that was skipped during bisection
+// If we are updating to a past height, a consensus state is created for that height to be persisted in client store
+// If we are updating to a future height, the consensus state is created and the client state is updated to reflect
+// the new latest height
+// A list containing the updated consensus height is returned.
+// UpdateState must only be used to update within a single revision, thus header revision number and trusted height's revision
+// number must be the same. To update to a new revision, use a separate upgrade path
+// UpdateState will prune the oldest consensus state if it is expired.
+func (cs ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg exported.ClientMessage) []exported.Height {
+ header, ok := clientMsg.(*Header)
+ if !ok {
+ panic(fmt.Errorf("expected type %T, got %T", &Header{}, clientMsg))
+ }
+
+ // check for duplicate update
+ if consensusState, _ := GetConsensusState(clientStore, cdc, header.GetHeight()); consensusState != nil {
+ // perform no-op
+ return []exported.Height{header.GetHeight()}
+ }
+
+ cs.pruneOldestConsensusState(ctx, cdc, clientStore)
+
height := header.GetHeight().(clienttypes.Height)
- if height.GT(clientState.LatestHeight) {
- clientState.LatestHeight = height
+ if height.GT(cs.LatestHeight) {
+ cs.LatestHeight = height
}
+
consensusState := &ConsensusState{
Timestamp: header.GetTime(),
Root: commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()),
NextValidatorsHash: header.Header.NextValidatorsHash,
}
- // set metadata for this consensus state
+ // set client state, consensus state and asssociated metadata
+ setClientState(clientStore, cdc, &cs)
+ setConsensusState(clientStore, cdc, consensusState, header.GetHeight())
setConsensusMetadata(ctx, clientStore, header.GetHeight())
- return clientState, consensusState
+ return []exported.Height{height}
+}
+
+// pruneOldestConsensusState will retrieve the earliest consensus state for this clientID and check if it is expired. If it is,
+// that consensus state will be pruned from store along with all associated metadata. This will prevent the client store from
+// becoming bloated with expired consensus states that can no longer be used for updates and packet verification.
+func (cs ClientState) pruneOldestConsensusState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore) {
+ // Check the earliest consensus state to see if it is expired, if so then set the prune height
+ // so that we can delete consensus state and all associated metadata.
+ var (
+ pruneHeight exported.Height
+ )
+
+ pruneCb := func(height exported.Height) bool {
+ consState, found := GetConsensusState(clientStore, cdc, height)
+ // this error should never occur
+ if !found {
+ panic(sdkerrors.Wrapf(clienttypes.ErrConsensusStateNotFound, "failed to retrieve consensus state at height: %s", height))
+ }
+
+ if cs.IsExpired(consState.Timestamp, ctx.BlockTime()) {
+ pruneHeight = height
+ }
+
+ return true
+ }
+
+ IterateConsensusStateAscending(clientStore, pruneCb)
+
+ // if pruneHeight is set, delete consensus state and metadata
+ if pruneHeight != nil {
+ deleteConsensusState(clientStore, pruneHeight)
+ deleteConsensusMetadata(clientStore, pruneHeight)
+ }
+}
+
+// CheckForMisbehaviour detects duplicate height misbehaviour and BFT time violation misbehaviour
+func (cs ClientState) CheckForMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, msg exported.ClientMessage) bool {
+ switch msg := msg.(type) {
+ case *Header:
+ tmHeader := msg
+ consState := tmHeader.ConsensusState()
+
+ // Check if the Client store already has a consensus state for the header's height
+ // If the consensus state exists, and it matches the header then we return early
+ // since header has already been submitted in a previous UpdateClient.
+ existingConsState, _ := GetConsensusState(clientStore, cdc, tmHeader.GetHeight())
+ if existingConsState != nil {
+ // This header has already been submitted and the necessary state is already stored
+ // in client store, thus we can return early without further validation.
+ if reflect.DeepEqual(existingConsState, tmHeader.ConsensusState()) { //nolint:gosimple
+ return false
+ }
+
+ // A consensus state already exists for this height, but it does not match the provided header.
+ // The assumption is that Header has already been validated. Thus we can return true as misbehaviour is present
+ return true
+ }
+
+ // Check that consensus state timestamps are monotonic
+ prevCons, prevOk := GetPreviousConsensusState(clientStore, cdc, tmHeader.GetHeight())
+ nextCons, nextOk := GetNextConsensusState(clientStore, cdc, tmHeader.GetHeight())
+ // if previous consensus state exists, check consensus state time is greater than previous consensus state time
+ // if previous consensus state is not before current consensus state return true
+ if prevOk && !prevCons.Timestamp.Before(consState.Timestamp) {
+ return true
+ }
+ // if next consensus state exists, check consensus state time is less than next consensus state time
+ // if next consensus state is not after current consensus state return true
+ if nextOk && !nextCons.Timestamp.After(consState.Timestamp) {
+ return true
+ }
+ case *Misbehaviour:
+ // The correctness of Misbehaviour ClientMessage types is ensured by calling VerifyClientMessage prior to this function
+ // Thus, here we can return true, as ClientMessage is of type Misbehaviour
+ return true
+ }
+
+ return false
+}
+
+// UpdateStateOnMisbehaviour updates state upon misbehaviour, freezing the ClientState. This method should only be called when misbehaviour is detected
+// as it does not perform any misbehaviour checks.
+func (cs ClientState) UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, _ exported.ClientMessage) {
+ cs.FrozenHeight = FrozenHeight
+
+ clientStore.Set(host.ClientStateKey(), clienttypes.MustMarshalClientState(cdc, &cs))
+}
+
+// checkTrustedHeader checks that consensus state matches trusted fields of Header
+func checkTrustedHeader(header *Header, consState *ConsensusState) error {
+ tmTrustedValidators, err := tmtypes.ValidatorSetFromProto(header.TrustedValidators)
+ if err != nil {
+ return sdkerrors.Wrap(err, "trusted validator set in not tendermint validator set type")
+ }
+
+ // assert that trustedVals is NextValidators of last trusted header
+ // to do this, we check that trustedVals.Hash() == consState.NextValidatorsHash
+ tvalHash := tmTrustedValidators.Hash()
+ if !bytes.Equal(consState.NextValidatorsHash, tvalHash) {
+ return sdkerrors.Wrapf(
+ ErrInvalidValidatorSet,
+ "trusted validators %s, does not hash to latest trusted validators. Expected: %X, got: %X",
+ header.TrustedValidators, consState.NextValidatorsHash, tvalHash,
+ )
+ }
+ return nil
}
diff --git a/modules/light-clients/07-tendermint/update_test.go b/modules/light-clients/07-tendermint/update_test.go
new file mode 100644
index 00000000000..0b5b55eb1cc
--- /dev/null
+++ b/modules/light-clients/07-tendermint/update_test.go
@@ -0,0 +1,745 @@
+package tendermint_test
+
+import (
+ "time"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ tmtypes "github.com/tendermint/tendermint/types"
+
+ clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
+ commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
+ host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
+ "github.com/cosmos/ibc-go/v5/modules/core/exported"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
+ ibctesting "github.com/cosmos/ibc-go/v5/testing"
+ ibctestingmock "github.com/cosmos/ibc-go/v5/testing/mock"
+)
+
+func (suite *TendermintTestSuite) TestVerifyHeader() {
+ var (
+ path *ibctesting.Path
+ header *ibctm.Header
+ )
+
+ // Setup different validators and signers for testing different types of updates
+ altPrivVal := ibctestingmock.NewPV()
+ altPubKey, err := altPrivVal.GetPubKey()
+ suite.Require().NoError(err)
+
+ revisionHeight := int64(height.RevisionHeight)
+
+ // create modified heights to use for test-cases
+ altVal := tmtypes.NewValidator(altPubKey, 100)
+ // Create alternative validator set with only altVal, invalid update (too much change in valSet)
+ altValSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{altVal})
+ altSigners := getAltSigners(altVal, altPrivVal)
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expPass bool
+ }{
+ {
+ name: "success",
+ malleate: func() {},
+ expPass: true,
+ },
+ {
+ name: "successful verify header for header with a previous height",
+ malleate: func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ // passing the CurrentHeader.Height as the block height as it will become a previous height once we commit N blocks
+ header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers)
+
+ // commit some blocks so that the created Header now has a previous height as the BlockHeight
+ suite.coordinator.CommitNBlocks(suite.chainB, 5)
+
+ err = path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+ },
+ expPass: true,
+ },
+ {
+ name: "successful verify header: header with future height and different validator set",
+ malleate: func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ // Create bothValSet with both suite validator and altVal
+ bothValSet := tmtypes.NewValidatorSet(append(suite.chainB.Vals.Validators, altVal))
+ bothSigners := suite.chainB.Signers
+ bothSigners[altVal.Address.String()] = altPrivVal
+
+ header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+5, trustedHeight, suite.chainB.CurrentHeader.Time, bothValSet, suite.chainB.NextVals, trustedVals, bothSigners)
+ },
+ expPass: true,
+ },
+ {
+ name: "successful verify header: header with next height and different validator set",
+ malleate: func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ // Create bothValSet with both suite validator and altVal
+ bothValSet := tmtypes.NewValidatorSet(append(suite.chainB.Vals.Validators, altVal))
+ bothSigners := suite.chainB.Signers
+ bothSigners[altVal.Address.String()] = altPrivVal
+
+ header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight, suite.chainB.CurrentHeader.Time, bothValSet, suite.chainB.NextVals, trustedVals, bothSigners)
+ },
+ expPass: true,
+ },
+ {
+ name: "unsuccessful updates, passed in incorrect trusted validators for given consensus state",
+ malleate: func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ // Create bothValSet with both suite validator and altVal
+ bothValSet := tmtypes.NewValidatorSet(append(suite.chainB.Vals.Validators, altVal))
+ bothSigners := suite.chainB.Signers
+ bothSigners[altVal.Address.String()] = altPrivVal
+
+ header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+1, trustedHeight, suite.chainB.CurrentHeader.Time, bothValSet, bothValSet, bothValSet, bothSigners)
+ },
+ expPass: false,
+ },
+ {
+ name: "unsuccessful verify header with next height: update header mismatches nextValSetHash",
+ malleate: func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ // this will err as altValSet.Hash() != consState.NextValidatorsHash
+ header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+1, trustedHeight, suite.chainB.CurrentHeader.Time, altValSet, altValSet, trustedVals, altSigners)
+ },
+ expPass: false,
+ },
+ {
+ name: "unsuccessful update with future height: too much change in validator set",
+ malleate: func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+1, trustedHeight, suite.chainB.CurrentHeader.Time, altValSet, altValSet, trustedVals, altSigners)
+ },
+ expPass: false,
+ },
+ {
+ name: "unsuccessful verify header: header height revision and trusted height revision mismatch",
+ malleate: func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ header = suite.chainB.CreateTMClientHeader(chainIDRevision1, 3, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers)
+ },
+ expPass: false,
+ },
+ {
+ name: "unsuccessful verify header: header height < consensus height",
+ malleate: func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ heightMinus1 := clienttypes.NewHeight(trustedHeight.RevisionNumber, trustedHeight.RevisionHeight-1)
+
+ // Make new header at height less than latest client state
+ header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, int64(heightMinus1.RevisionHeight), trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers)
+ },
+ expPass: false,
+ },
+ {
+ name: "unsuccessful verify header: header basic validation failed",
+ malleate: func() {
+ // cause header to fail validatebasic by changing commit height to mismatch header height
+ header.SignedHeader.Commit.Height = revisionHeight - 1
+ },
+ expPass: false,
+ },
+ {
+ name: "unsuccessful verify header: header timestamp is not past last client timestamp",
+ malleate: func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight))
+ suite.Require().True(found)
+
+ header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+1, trustedHeight, suite.chainB.CurrentHeader.Time.Add(-time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers)
+ },
+ expPass: false,
+ },
+ {
+ name: "unsuccessful verify header: header with incorrect header chain-id",
+ malleate: func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight))
+ suite.Require().True(found)
+
+ header = suite.chainB.CreateTMClientHeader(chainID, suite.chainB.CurrentHeader.Height+1, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers)
+ },
+ expPass: false,
+ },
+ {
+ name: "unsuccessful update: trusting period has passed since last client timestamp",
+ malleate: func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight))
+ suite.Require().True(found)
+
+ header = suite.chainA.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height+1, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers)
+
+ suite.chainB.ExpireClient(ibctesting.TrustingPeriod)
+ },
+ expPass: false,
+ },
+ {
+ name: "unsuccessful update for a previous revision",
+ malleate: func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ // passing the CurrentHeader.Height as the block height as it will become an update to previous revision once we upgrade the client
+ header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers)
+
+ // increment the revision of the chain
+ err = path.EndpointB.UpgradeChain()
+ suite.Require().NoError(err)
+ },
+ expPass: false,
+ },
+ {
+ name: "successful update with identical header to a previous update",
+ malleate: func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ // passing the CurrentHeader.Height as the block height as it will become a previous height once we commit N blocks
+ header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers)
+
+ // update client so the header constructed becomes a duplicate
+ err = path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+ },
+ expPass: true,
+ },
+
+ {
+ name: "unsuccessful update to a future revision",
+ malleate: func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID+"-1", suite.chainB.CurrentHeader.Height+5, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers)
+ },
+ expPass: false,
+ },
+
+ {
+ name: "unsuccessful update: header height revision and trusted height revision mismatch",
+ malleate: func() {
+ trustedHeight := path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ trustedVals, found := suite.chainB.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
+ suite.Require().True(found)
+
+ // increment the revision of the chain
+ err = path.EndpointB.UpgradeChain()
+ suite.Require().NoError(err)
+
+ header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.CurrentHeader.Height, trustedHeight, suite.chainB.CurrentHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers)
+ },
+ expPass: false,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+ suite.SetupTest()
+ path = ibctesting.NewPath(suite.chainA, suite.chainB)
+
+ err := path.EndpointA.CreateClient()
+ suite.Require().NoError(err)
+
+ // ensure counterparty state is committed
+ suite.coordinator.CommitBlock(suite.chainB)
+ header, err = path.EndpointA.Chain.ConstructUpdateTMClientHeader(path.EndpointA.Counterparty.Chain, path.EndpointA.ClientID)
+ suite.Require().NoError(err)
+
+ tc.malleate()
+
+ clientState := path.EndpointA.GetClientState()
+
+ clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
+
+ err = clientState.VerifyClientMessage(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, header)
+
+ if tc.expPass {
+ suite.Require().NoError(err, tc.name)
+ } else {
+ suite.Require().Error(err)
+ }
+ }
+}
+
+func (suite *TendermintTestSuite) TestUpdateState() {
+ var (
+ path *ibctesting.Path
+ clientMessage exported.ClientMessage
+ clientStore sdk.KVStore
+ consensusHeights []exported.Height
+ pruneHeight clienttypes.Height
+ prevClientState exported.ClientState
+ prevConsensusState exported.ConsensusState
+ )
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expResult func()
+ expPass bool
+ }{
+ {
+ "success with height later than latest height", func() {
+ tmHeader, ok := clientMessage.(*ibctm.Header)
+ suite.Require().True(ok)
+ suite.Require().True(path.EndpointA.GetClientState().GetLatestHeight().LT(tmHeader.GetHeight()))
+ },
+ func() {
+ tmHeader, ok := clientMessage.(*ibctm.Header)
+ suite.Require().True(ok)
+
+ clientState := path.EndpointA.GetClientState()
+ suite.Require().True(clientState.GetLatestHeight().EQ(tmHeader.GetHeight())) // new update, updated client state should have changed
+ suite.Require().True(clientState.GetLatestHeight().EQ(consensusHeights[0]))
+ }, true,
+ },
+ {
+ "success with height earlier than latest height", func() {
+ // commit a block so the pre-created ClientMessage
+ // isn't used to update the client to a newer height
+ suite.coordinator.CommitBlock(suite.chainB)
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ tmHeader, ok := clientMessage.(*ibctm.Header)
+ suite.Require().True(ok)
+ suite.Require().True(path.EndpointA.GetClientState().GetLatestHeight().GT(tmHeader.GetHeight()))
+
+ prevClientState = path.EndpointA.GetClientState()
+ },
+ func() {
+ clientState := path.EndpointA.GetClientState()
+ suite.Require().Equal(clientState, prevClientState) // fill in height, no change to client state
+ suite.Require().True(clientState.GetLatestHeight().GT(consensusHeights[0]))
+ }, true,
+ },
+ {
+ "success with duplicate header", func() {
+ // update client in advance
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ // use the same header which just updated the client
+ clientMessage, err = path.EndpointA.Chain.ConstructUpdateTMClientHeader(path.EndpointA.Counterparty.Chain, path.EndpointA.ClientID)
+ suite.Require().NoError(err)
+
+ tmHeader, ok := clientMessage.(*ibctm.Header)
+ suite.Require().True(ok)
+ suite.Require().Equal(path.EndpointA.GetClientState().GetLatestHeight(), tmHeader.GetHeight())
+
+ prevClientState = path.EndpointA.GetClientState()
+ prevConsensusState = path.EndpointA.GetConsensusState(tmHeader.GetHeight())
+ },
+ func() {
+ clientState := path.EndpointA.GetClientState()
+ suite.Require().Equal(clientState, prevClientState)
+ suite.Require().True(clientState.GetLatestHeight().EQ(consensusHeights[0]))
+
+ tmHeader, ok := clientMessage.(*ibctm.Header)
+ suite.Require().True(ok)
+ suite.Require().Equal(path.EndpointA.GetConsensusState(tmHeader.GetHeight()), prevConsensusState)
+ }, true,
+ },
+ {
+ "success with pruned consensus state", func() {
+ // this height will be expired and pruned
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+ pruneHeight = path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)
+
+ // Increment the time by a week
+ suite.coordinator.IncrementTimeBy(7 * 24 * time.Hour)
+
+ // create the consensus state that can be used as trusted height for next update
+ err = path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ // Increment the time by another week, then update the client.
+ // This will cause the first two consensus states to become expired.
+ suite.coordinator.IncrementTimeBy(7 * 24 * time.Hour)
+ err = path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ // ensure counterparty state is committed
+ suite.coordinator.CommitBlock(suite.chainB)
+ clientMessage, err = path.EndpointA.Chain.ConstructUpdateTMClientHeader(path.EndpointA.Counterparty.Chain, path.EndpointA.ClientID)
+ suite.Require().NoError(err)
+ },
+ func() {
+ tmHeader, ok := clientMessage.(*ibctm.Header)
+ suite.Require().True(ok)
+
+ clientState := path.EndpointA.GetClientState()
+ suite.Require().True(clientState.GetLatestHeight().EQ(tmHeader.GetHeight())) // new update, updated client state should have changed
+ suite.Require().True(clientState.GetLatestHeight().EQ(consensusHeights[0]))
+
+ // ensure consensus state was pruned
+ _, found := path.EndpointA.Chain.GetConsensusState(path.EndpointA.ClientID, pruneHeight)
+ suite.Require().False(found)
+ }, true,
+ },
+ {
+ "invalid ClientMessage type", func() {
+ clientMessage = &ibctm.Misbehaviour{}
+ },
+ func() {},
+ false,
+ },
+ }
+ for _, tc := range testCases {
+ tc := tc
+ suite.Run(tc.name, func() {
+ suite.SetupTest() // reset
+ pruneHeight = clienttypes.ZeroHeight()
+ path = ibctesting.NewPath(suite.chainA, suite.chainB)
+
+ err := path.EndpointA.CreateClient()
+ suite.Require().NoError(err)
+
+ // ensure counterparty state is committed
+ suite.coordinator.CommitBlock(suite.chainB)
+ clientMessage, err = path.EndpointA.Chain.ConstructUpdateTMClientHeader(path.EndpointA.Counterparty.Chain, path.EndpointA.ClientID)
+ suite.Require().NoError(err)
+
+ tc.malleate()
+
+ clientState := path.EndpointA.GetClientState()
+ clientStore = suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
+
+ if tc.expPass {
+ consensusHeights = clientState.UpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, clientMessage)
+
+ header := clientMessage.(*ibctm.Header)
+ expConsensusState := &ibctm.ConsensusState{
+ Timestamp: header.GetTime(),
+ Root: commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()),
+ NextValidatorsHash: header.Header.NextValidatorsHash,
+ }
+
+ bz := clientStore.Get(host.ConsensusStateKey(header.GetHeight()))
+ updatedConsensusState := clienttypes.MustUnmarshalConsensusState(suite.chainA.App.AppCodec(), bz)
+
+ suite.Require().Equal(expConsensusState, updatedConsensusState)
+
+ } else {
+ suite.Require().Panics(func() {
+ clientState.UpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, clientMessage)
+ })
+ }
+
+ // perform custom checks
+ tc.expResult()
+ })
+ }
+}
+
+func (suite *TendermintTestSuite) TestPruneConsensusState() {
+ // create path and setup clients
+ path := ibctesting.NewPath(suite.chainA, suite.chainB)
+ suite.coordinator.SetupClients(path)
+
+ // get the first height as it will be pruned first.
+ var pruneHeight exported.Height
+ getFirstHeightCb := func(height exported.Height) bool {
+ pruneHeight = height
+ return true
+ }
+ ctx := path.EndpointA.Chain.GetContext()
+ clientStore := path.EndpointA.Chain.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, path.EndpointA.ClientID)
+ ibctm.IterateConsensusStateAscending(clientStore, getFirstHeightCb)
+
+ // this height will be expired but not pruned
+ path.EndpointA.UpdateClient()
+ expiredHeight := path.EndpointA.GetClientState().GetLatestHeight()
+
+ // expected values that must still remain in store after pruning
+ expectedConsState, ok := path.EndpointA.Chain.GetConsensusState(path.EndpointA.ClientID, expiredHeight)
+ suite.Require().True(ok)
+ ctx = path.EndpointA.Chain.GetContext()
+ clientStore = path.EndpointA.Chain.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, path.EndpointA.ClientID)
+ expectedProcessTime, ok := ibctm.GetProcessedTime(clientStore, expiredHeight)
+ suite.Require().True(ok)
+ expectedProcessHeight, ok := ibctm.GetProcessedHeight(clientStore, expiredHeight)
+ suite.Require().True(ok)
+ expectedConsKey := ibctm.GetIterationKey(clientStore, expiredHeight)
+ suite.Require().NotNil(expectedConsKey)
+
+ // Increment the time by a week
+ suite.coordinator.IncrementTimeBy(7 * 24 * time.Hour)
+
+ // create the consensus state that can be used as trusted height for next update
+ path.EndpointA.UpdateClient()
+
+ // Increment the time by another week, then update the client.
+ // This will cause the first two consensus states to become expired.
+ suite.coordinator.IncrementTimeBy(7 * 24 * time.Hour)
+ path.EndpointA.UpdateClient()
+
+ ctx = path.EndpointA.Chain.GetContext()
+ clientStore = path.EndpointA.Chain.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, path.EndpointA.ClientID)
+
+ // check that the first expired consensus state got deleted along with all associated metadata
+ consState, ok := path.EndpointA.Chain.GetConsensusState(path.EndpointA.ClientID, pruneHeight)
+ suite.Require().Nil(consState, "expired consensus state not pruned")
+ suite.Require().False(ok)
+ // check processed time metadata is pruned
+ processTime, ok := ibctm.GetProcessedTime(clientStore, pruneHeight)
+ suite.Require().Equal(uint64(0), processTime, "processed time metadata not pruned")
+ suite.Require().False(ok)
+ processHeight, ok := ibctm.GetProcessedHeight(clientStore, pruneHeight)
+ suite.Require().Nil(processHeight, "processed height metadata not pruned")
+ suite.Require().False(ok)
+
+ // check iteration key metadata is pruned
+ consKey := ibctm.GetIterationKey(clientStore, pruneHeight)
+ suite.Require().Nil(consKey, "iteration key not pruned")
+
+ // check that second expired consensus state doesn't get deleted
+ // this ensures that there is a cap on gas cost of UpdateClient
+ consState, ok = path.EndpointA.Chain.GetConsensusState(path.EndpointA.ClientID, expiredHeight)
+ suite.Require().Equal(expectedConsState, consState, "consensus state incorrectly pruned")
+ suite.Require().True(ok)
+ // check processed time metadata is not pruned
+ processTime, ok = ibctm.GetProcessedTime(clientStore, expiredHeight)
+ suite.Require().Equal(expectedProcessTime, processTime, "processed time metadata incorrectly pruned")
+ suite.Require().True(ok)
+
+ // check processed height metadata is not pruned
+ processHeight, ok = ibctm.GetProcessedHeight(clientStore, expiredHeight)
+ suite.Require().Equal(expectedProcessHeight, processHeight, "processed height metadata incorrectly pruned")
+ suite.Require().True(ok)
+
+ // check iteration key metadata is not pruned
+ consKey = ibctm.GetIterationKey(clientStore, expiredHeight)
+ suite.Require().Equal(expectedConsKey, consKey, "iteration key incorrectly pruned")
+}
+
+func (suite *TendermintTestSuite) TestCheckForMisbehaviour() {
+ var (
+ path *ibctesting.Path
+ clientMessage exported.ClientMessage
+ )
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "valid update no misbehaviour",
+ func() {},
+ false,
+ },
+ {
+ "consensus state already exists, already updated",
+ func() {
+ header, ok := clientMessage.(*ibctm.Header)
+ suite.Require().True(ok)
+
+ consensusState := &ibctm.ConsensusState{
+ Timestamp: header.GetTime(),
+ Root: commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()),
+ NextValidatorsHash: header.Header.NextValidatorsHash,
+ }
+
+ tmHeader, ok := clientMessage.(*ibctm.Header)
+ suite.Require().True(ok)
+ suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), path.EndpointA.ClientID, tmHeader.GetHeight(), consensusState)
+ },
+ false,
+ },
+ {
+ "consensus state already exists, app hash mismatch",
+ func() {
+ header, ok := clientMessage.(*ibctm.Header)
+ suite.Require().True(ok)
+
+ consensusState := &ibctm.ConsensusState{
+ Timestamp: header.GetTime(),
+ Root: commitmenttypes.NewMerkleRoot([]byte{}), // empty bytes
+ NextValidatorsHash: header.Header.NextValidatorsHash,
+ }
+
+ tmHeader, ok := clientMessage.(*ibctm.Header)
+ suite.Require().True(ok)
+ suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), path.EndpointA.ClientID, tmHeader.GetHeight(), consensusState)
+ },
+ true,
+ },
+ {
+ "previous consensus state exists and header time is before previous consensus state time",
+ func() {
+ header, ok := clientMessage.(*ibctm.Header)
+ suite.Require().True(ok)
+
+ // offset header timestamp before previous consensus state timestamp
+ header.Header.Time = header.GetTime().Add(-time.Hour)
+ },
+ true,
+ },
+ {
+ "next consensus state exists and header time is after next consensus state time",
+ func() {
+ header, ok := clientMessage.(*ibctm.Header)
+ suite.Require().True(ok)
+
+ // commit block and update client, adding a new consensus state
+ suite.coordinator.CommitBlock(suite.chainB)
+ err := path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ // increase timestamp of current header
+ header.Header.Time = header.Header.Time.Add(time.Hour)
+ },
+ true,
+ },
+ {
+ "valid fork misbehaviour returns true",
+ func() {
+ header1, err := path.EndpointA.Chain.ConstructUpdateTMClientHeader(path.EndpointA.Counterparty.Chain, path.EndpointA.ClientID)
+ suite.Require().NoError(err)
+
+ // commit block and update client
+ suite.coordinator.CommitBlock(suite.chainB)
+ err = path.EndpointA.UpdateClient()
+ suite.Require().NoError(err)
+
+ header2, err := path.EndpointA.Chain.ConstructUpdateTMClientHeader(path.EndpointA.Counterparty.Chain, path.EndpointA.ClientID)
+ suite.Require().NoError(err)
+
+ // assign the same height, each header will have a different commit hash
+ header1.Header.Height = header2.Header.Height
+
+ clientMessage = &ibctm.Misbehaviour{
+ Header1: header1,
+ Header2: header2,
+ ClientId: path.EndpointA.ClientID,
+ }
+ },
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+ suite.Run(tc.name, func() {
+ // reset suite to create fresh application state
+ suite.SetupTest()
+ path = ibctesting.NewPath(suite.chainA, suite.chainB)
+
+ err := path.EndpointA.CreateClient()
+ suite.Require().NoError(err)
+
+ // ensure counterparty state is committed
+ suite.coordinator.CommitBlock(suite.chainB)
+ clientMessage, err = path.EndpointA.Chain.ConstructUpdateTMClientHeader(path.EndpointA.Counterparty.Chain, path.EndpointA.ClientID)
+ suite.Require().NoError(err)
+
+ tc.malleate()
+
+ clientState := path.EndpointA.GetClientState()
+ clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
+
+ foundMisbehaviour := clientState.CheckForMisbehaviour(
+ suite.chainA.GetContext(),
+ suite.chainA.App.AppCodec(),
+ clientStore, // pass in clientID prefixed clientStore
+ clientMessage,
+ )
+
+ if tc.expPass {
+ suite.Require().True(foundMisbehaviour)
+ } else {
+ suite.Require().False(foundMisbehaviour)
+ }
+ })
+ }
+}
+
+func (suite *TendermintTestSuite) TestUpdateStateOnMisbehaviour() {
+ var (
+ path *ibctesting.Path
+ )
+
+ testCases := []struct {
+ name string
+ malleate func()
+ expPass bool
+ }{
+ {
+ "success",
+ func() {},
+ true,
+ },
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+
+ suite.Run(tc.name, func() {
+ // reset suite to create fresh application state
+ suite.SetupTest()
+ path = ibctesting.NewPath(suite.chainA, suite.chainB)
+
+ err := path.EndpointA.CreateClient()
+ suite.Require().NoError(err)
+
+ tc.malleate()
+
+ clientState := path.EndpointA.GetClientState()
+ clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
+
+ clientState.UpdateStateOnMisbehaviour(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, nil)
+
+ if tc.expPass {
+ clientStateBz := clientStore.Get(host.ClientStateKey())
+ suite.Require().NotEmpty(clientStateBz)
+
+ newClientState := clienttypes.MustUnmarshalClientState(suite.chainA.Codec, clientStateBz)
+ suite.Require().Equal(frozenHeight, newClientState.(*ibctm.ClientState).FrozenHeight)
+ }
+ })
+ }
+}
diff --git a/modules/light-clients/07-tendermint/types/upgrade.go b/modules/light-clients/07-tendermint/upgrade.go
similarity index 78%
rename from modules/light-clients/07-tendermint/types/upgrade.go
rename to modules/light-clients/07-tendermint/upgrade.go
index 07ce9823d2e..277ced61273 100644
--- a/modules/light-clients/07-tendermint/types/upgrade.go
+++ b/modules/light-clients/07-tendermint/upgrade.go
@@ -1,4 +1,4 @@
-package types
+package tendermint
import (
"fmt"
@@ -14,11 +14,11 @@ import (
)
// VerifyUpgradeAndUpdateState checks if the upgraded client has been committed by the current client
-// It will zero out all client-specific fields (e.g. TrustingPeriod and verify all data
+// It will zero out all client-specific fields (e.g. TrustingPeriod) and verify all data
// in client state that must be the same across all valid Tendermint clients for the new chain.
// VerifyUpgrade will return an error if:
// - the upgradedClient is not a Tendermint ClientState
-// - the lastest height of the client state does not have the same revision number or has a greater
+// - the latest height of the client state does not have the same revision number or has a greater
// height than the committed client.
// - the height of upgraded client is not greater than that of current client
// - the latest height of the new client does not match or is greater than the height in committed client
@@ -28,16 +28,16 @@ func (cs ClientState) VerifyUpgradeAndUpdateState(
ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore,
upgradedClient exported.ClientState, upgradedConsState exported.ConsensusState,
proofUpgradeClient, proofUpgradeConsState []byte,
-) (exported.ClientState, exported.ConsensusState, error) {
+) error {
if len(cs.UpgradePath) == 0 {
- return nil, nil, sdkerrors.Wrap(clienttypes.ErrInvalidUpgradeClient, "cannot upgrade client, no upgrade path set")
+ return sdkerrors.Wrap(clienttypes.ErrInvalidUpgradeClient, "cannot upgrade client, no upgrade path set")
}
// last height of current counterparty chain must be client's latest height
lastHeight := cs.GetLatestHeight()
if !upgradedClient.GetLatestHeight().GT(lastHeight) {
- return nil, nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "upgraded client height %s must be at greater than current client height %s",
+ return sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "upgraded client height %s must be at greater than current client height %s",
upgradedClient.GetLatestHeight(), lastHeight)
}
@@ -46,52 +46,52 @@ func (cs ClientState) VerifyUpgradeAndUpdateState(
// counterparty must also commit to the upgraded consensus state at a sub-path under the upgrade path specified
tmUpgradeClient, ok := upgradedClient.(*ClientState)
if !ok {
- return nil, nil, sdkerrors.Wrapf(clienttypes.ErrInvalidClientType, "upgraded client must be Tendermint client. expected: %T got: %T",
+ return sdkerrors.Wrapf(clienttypes.ErrInvalidClientType, "upgraded client must be Tendermint client. expected: %T got: %T",
&ClientState{}, upgradedClient)
}
tmUpgradeConsState, ok := upgradedConsState.(*ConsensusState)
if !ok {
- return nil, nil, sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "upgraded consensus state must be Tendermint consensus state. expected %T, got: %T",
+ return sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "upgraded consensus state must be Tendermint consensus state. expected %T, got: %T",
&ConsensusState{}, upgradedConsState)
}
// unmarshal proofs
var merkleProofClient, merkleProofConsState commitmenttypes.MerkleProof
if err := cdc.Unmarshal(proofUpgradeClient, &merkleProofClient); err != nil {
- return nil, nil, sdkerrors.Wrapf(commitmenttypes.ErrInvalidProof, "could not unmarshal client merkle proof: %v", err)
+ return sdkerrors.Wrapf(commitmenttypes.ErrInvalidProof, "could not unmarshal client merkle proof: %v", err)
}
if err := cdc.Unmarshal(proofUpgradeConsState, &merkleProofConsState); err != nil {
- return nil, nil, sdkerrors.Wrapf(commitmenttypes.ErrInvalidProof, "could not unmarshal consensus state merkle proof: %v", err)
+ return sdkerrors.Wrapf(commitmenttypes.ErrInvalidProof, "could not unmarshal consensus state merkle proof: %v", err)
}
// Must prove against latest consensus state to ensure we are verifying against latest upgrade plan
// This verifies that upgrade is intended for the provided revision, since committed client must exist
// at this consensus state
- consState, err := GetConsensusState(clientStore, cdc, lastHeight)
- if err != nil {
- return nil, nil, sdkerrors.Wrap(err, "could not retrieve consensus state for lastHeight")
+ consState, found := GetConsensusState(clientStore, cdc, lastHeight)
+ if !found {
+ return sdkerrors.Wrap(clienttypes.ErrConsensusStateNotFound, "could not retrieve consensus state for lastHeight")
}
// Verify client proof
- bz, err := cdc.MarshalInterface(upgradedClient)
+ bz, err := cdc.MarshalInterface(upgradedClient.ZeroCustomFields())
if err != nil {
- return nil, nil, sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "could not marshal client state: %v", err)
+ return sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "could not marshal client state: %v", err)
}
// construct clientState Merkle path
upgradeClientPath := constructUpgradeClientMerklePath(cs.UpgradePath, lastHeight)
if err := merkleProofClient.VerifyMembership(cs.ProofSpecs, consState.GetRoot(), upgradeClientPath, bz); err != nil {
- return nil, nil, sdkerrors.Wrapf(err, "client state proof failed. Path: %s", upgradeClientPath.Pretty())
+ return sdkerrors.Wrapf(err, "client state proof failed. Path: %s", upgradeClientPath.Pretty())
}
// Verify consensus state proof
bz, err = cdc.MarshalInterface(upgradedConsState)
if err != nil {
- return nil, nil, sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "could not marshal consensus state: %v", err)
+ return sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "could not marshal consensus state: %v", err)
}
// construct consensus state Merkle path
upgradeConsStatePath := constructUpgradeConsStateMerklePath(cs.UpgradePath, lastHeight)
if err := merkleProofConsState.VerifyMembership(cs.ProofSpecs, consState.GetRoot(), upgradeConsStatePath, bz); err != nil {
- return nil, nil, sdkerrors.Wrapf(err, "consensus state proof failed. Path: %s", upgradeConsStatePath.Pretty())
+ return sdkerrors.Wrapf(err, "consensus state proof failed. Path: %s", upgradeConsStatePath.Pretty())
}
// Construct new client state and consensus state
@@ -105,7 +105,7 @@ func (cs ClientState) VerifyUpgradeAndUpdateState(
)
if err := newClientState.Validate(); err != nil {
- return nil, nil, sdkerrors.Wrap(err, "updated client state failed basic validation")
+ return sdkerrors.Wrap(err, "updated client state failed basic validation")
}
// The new consensus state is merely used as a trusted kernel against which headers on the new
@@ -119,10 +119,11 @@ func (cs ClientState) VerifyUpgradeAndUpdateState(
tmUpgradeConsState.Timestamp, commitmenttypes.NewMerkleRoot([]byte(SentinelRoot)), tmUpgradeConsState.NextValidatorsHash,
)
- // set metadata for this consensus state
+ setClientState(clientStore, cdc, newClientState)
+ setConsensusState(clientStore, cdc, newConsState, newClientState.LatestHeight)
setConsensusMetadata(ctx, clientStore, tmUpgradeClient.LatestHeight)
- return newClientState, newConsState, nil
+ return nil
}
// construct MerklePath for the committed client from upgradePath
diff --git a/modules/light-clients/07-tendermint/types/upgrade_test.go b/modules/light-clients/07-tendermint/upgrade_test.go
similarity index 93%
rename from modules/light-clients/07-tendermint/types/upgrade_test.go
rename to modules/light-clients/07-tendermint/upgrade_test.go
index fb21057a1e7..301b64288c9 100644
--- a/modules/light-clients/07-tendermint/types/upgrade_test.go
+++ b/modules/light-clients/07-tendermint/upgrade_test.go
@@ -1,4 +1,4 @@
-package types_test
+package tendermint_test
import (
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
@@ -6,14 +6,13 @@ import (
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
-var newChainId = "newChainId-1"
-
func (suite *TendermintTestSuite) TestVerifyUpgrade() {
var (
+ newChainID string
upgradedClient exported.ClientState
upgradedConsState exported.ConsensusState
lastHeight clienttypes.Height
@@ -55,9 +54,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
{
name: "successful upgrade to same revision",
setup: func() {
- upgradedHeight := clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+2))
- // don't use -1 suffix in chain id
- upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, upgradedHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
+ upgradedClient = ibctm.NewClientState(suite.chainB.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, clienttypes.NewHeight(clienttypes.ParseChainID(suite.chainB.ChainID), upgradedClient.GetLatestHeight().GetRevisionHeight()+10), commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
upgradedClient = upgradedClient.ZeroCustomFields()
upgradedClientBz, err = clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient)
suite.Require().NoError(err)
@@ -112,7 +109,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
name: "unsuccessful upgrade: committed client does not have zeroed custom fields",
setup: func() {
// non-zeroed upgrade client
- upgradedClient = types.NewClientState(newChainId, types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
+ upgradedClient = ibctm.NewClientState(newChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
upgradedClientBz, err = clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient)
suite.Require().NoError(err)
@@ -148,7 +145,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz)
// change upgradedClient client-specified parameters
- upgradedClient = types.NewClientState("wrongchainID", types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, true, true)
+ upgradedClient = ibctm.NewClientState("wrongchainID", ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, true, true)
suite.coordinator.CommitBlock(suite.chainB)
err := path.EndpointA.UpdateClient()
@@ -170,7 +167,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz)
// change upgradedClient client-specified parameters
- upgradedClient = types.NewClientState(newChainId, types.DefaultTrustLevel, ubdPeriod, ubdPeriod+trustingPeriod, maxClockDrift+5, lastHeight, commitmenttypes.GetSDKSpecs(), upgradePath, true, false)
+ upgradedClient = ibctm.NewClientState(newChainID, ibctm.DefaultTrustLevel, ubdPeriod, ubdPeriod+trustingPeriod, maxClockDrift+5, lastHeight, commitmenttypes.GetSDKSpecs(), upgradePath, true, false)
suite.coordinator.CommitBlock(suite.chainB)
err := path.EndpointA.UpdateClient()
@@ -195,7 +192,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz)
// change submitted upgradedConsensusState
- upgradedConsState = &types.ConsensusState{
+ upgradedConsState = &ibctm.ConsensusState{
NextValidatorsHash: []byte("maliciousValidators"),
}
@@ -299,7 +296,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight())
// SetClientState with empty upgrade path
- tmClient, _ := cs.(*types.ClientState)
+ tmClient, _ := cs.(*ibctm.ClientState)
tmClient.UpgradePath = []string{""}
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID, tmClient)
},
@@ -401,7 +398,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
name: "unsuccessful upgrade: final client is not valid",
setup: func() {
// new client has smaller unbonding period such that old trusting period is no longer valid
- upgradedClient = types.NewClientState(newChainId, types.DefaultTrustLevel, trustingPeriod, trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
+ upgradedClient = ibctm.NewClientState(newChainID, ibctm.DefaultTrustLevel, trustingPeriod, trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
upgradedClientBz, err = clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient)
suite.Require().NoError(err)
@@ -436,12 +433,20 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
path = ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupClients(path)
- upgradedClient = types.NewClientState(newChainId, types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
+
+ clientState := path.EndpointA.GetClientState().(*ibctm.ClientState)
+ revisionNumber := clienttypes.ParseChainID(clientState.ChainId)
+
+ var err error
+ 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.GetLatestHeight().GetRevisionHeight()+1), commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
upgradedClient = upgradedClient.ZeroCustomFields()
upgradedClientBz, err = clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient)
suite.Require().NoError(err)
- upgradedConsState = &types.ConsensusState{
+ upgradedConsState = &ibctm.ConsensusState{
NextValidatorsHash: []byte("nextValsHash"),
}
upgradedConsStateBz, err = clienttypes.MarshalConsensusState(suite.chainA.App.AppCodec(), upgradedConsState)
@@ -455,7 +460,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
// Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient
upgradedClient = upgradedClient.ZeroCustomFields()
- clientState, consensusState, err := cs.VerifyUpgradeAndUpdateState(
+ err = cs.VerifyUpgradeAndUpdateState(
suite.chainA.GetContext(),
suite.cdc,
clientStore,
@@ -467,14 +472,15 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
if tc.expPass {
suite.Require().NoError(err, "verify upgrade failed on valid case: %s", tc.name)
+
+ clientState := suite.chainA.GetClientState(path.EndpointA.ClientID)
suite.Require().NotNil(clientState, "verify upgrade failed on valid case: %s", tc.name)
+
+ consensusState, found := suite.chainA.GetConsensusState(path.EndpointA.ClientID, clientState.GetLatestHeight())
suite.Require().NotNil(consensusState, "verify upgrade failed on valid case: %s", tc.name)
+ suite.Require().True(found)
} else {
suite.Require().Error(err, "verify upgrade passed on invalid case: %s", tc.name)
- suite.Require().Nil(clientState, "verify upgrade passed on invalid case: %s", tc.name)
-
- suite.Require().Nil(consensusState, "verify upgrade passed on invalid case: %s", tc.name)
-
}
}
}
diff --git a/modules/light-clients/09-localhost/doc.go b/modules/light-clients/09-localhost/doc.go
deleted file mode 100644
index 40a0f060867..00000000000
--- a/modules/light-clients/09-localhost/doc.go
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
-Package localhost implements a concrete `ConsensusState`, `Header`,
-`Misbehaviour` and `Equivocation` types for the loop-back client.
-*/
-package localhost
diff --git a/modules/light-clients/09-localhost/module.go b/modules/light-clients/09-localhost/module.go
deleted file mode 100644
index cf1615a8023..00000000000
--- a/modules/light-clients/09-localhost/module.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package localhost
-
-import (
- "github.com/cosmos/ibc-go/v5/modules/light-clients/09-localhost/types"
-)
-
-// Name returns the IBC client name
-func Name() string {
- return types.SubModuleName
-}
diff --git a/modules/light-clients/09-localhost/types/client_state.go b/modules/light-clients/09-localhost/types/client_state.go
deleted file mode 100644
index ceda52b2354..00000000000
--- a/modules/light-clients/09-localhost/types/client_state.go
+++ /dev/null
@@ -1,340 +0,0 @@
-package types
-
-import (
- "bytes"
- "encoding/binary"
- "reflect"
- "strings"
-
- "github.com/cosmos/cosmos-sdk/codec"
- sdk "github.com/cosmos/cosmos-sdk/types"
- sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
-
- clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- connectiontypes "github.com/cosmos/ibc-go/v5/modules/core/03-connection/types"
- channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
- host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
-)
-
-var _ exported.ClientState = (*ClientState)(nil)
-
-// NewClientState creates a new ClientState instance
-func NewClientState(chainID string, height clienttypes.Height) *ClientState {
- return &ClientState{
- ChainId: chainID,
- Height: height,
- }
-}
-
-// GetChainID returns an empty string
-func (cs ClientState) GetChainID() string {
- return cs.ChainId
-}
-
-// ClientType is localhost.
-func (cs ClientState) ClientType() string {
- return exported.Localhost
-}
-
-// GetLatestHeight returns the latest height stored.
-func (cs ClientState) GetLatestHeight() exported.Height {
- return cs.Height
-}
-
-// Status always returns Active. The localhost status cannot be changed.
-func (cs ClientState) Status(_ sdk.Context, _ sdk.KVStore, _ codec.BinaryCodec,
-) exported.Status {
- return exported.Active
-}
-
-// Validate performs a basic validation of the client state fields.
-func (cs ClientState) Validate() error {
- if strings.TrimSpace(cs.ChainId) == "" {
- return sdkerrors.Wrap(sdkerrors.ErrInvalidChainID, "chain id cannot be blank")
- }
- if cs.Height.RevisionHeight == 0 {
- return sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "local revision height cannot be zero")
- }
- return nil
-}
-
-// ZeroCustomFields returns the same client state since there are no custom fields in localhost
-func (cs ClientState) ZeroCustomFields() exported.ClientState {
- return &cs
-}
-
-// Initialize ensures that initial consensus state for localhost is nil
-func (cs ClientState) Initialize(_ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore, consState exported.ConsensusState) error {
- if consState != nil {
- return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "initial consensus state for localhost must be nil.")
- }
- return nil
-}
-
-// ExportMetadata is a no-op for localhost client
-func (cs ClientState) ExportMetadata(_ sdk.KVStore) []exported.GenesisMetadata {
- return nil
-}
-
-// CheckHeaderAndUpdateState updates the localhost client. It only needs access to the context
-func (cs *ClientState) CheckHeaderAndUpdateState(
- ctx sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore, _ exported.Header,
-) (exported.ClientState, exported.ConsensusState, error) {
- // use the chain ID from context since the localhost client is from the running chain (i.e self).
- cs.ChainId = ctx.ChainID()
- revision := clienttypes.ParseChainID(cs.ChainId)
- cs.Height = clienttypes.NewHeight(revision, uint64(ctx.BlockHeight()))
- return cs, nil, nil
-}
-
-// CheckMisbehaviourAndUpdateState implements ClientState
-// Since localhost is the client of the running chain, misbehaviour cannot be submitted to it
-// Thus, CheckMisbehaviourAndUpdateState returns an error for localhost
-func (cs ClientState) CheckMisbehaviourAndUpdateState(
- _ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore, _ exported.Misbehaviour,
-) (exported.ClientState, error) {
- return nil, sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "cannot submit misbehaviour to localhost client")
-}
-
-// CheckSubstituteAndUpdateState returns an error. The localhost cannot be modified by
-// proposals.
-func (cs ClientState) CheckSubstituteAndUpdateState(
- ctx sdk.Context, _ codec.BinaryCodec, _, _ sdk.KVStore,
- _ exported.ClientState,
-) (exported.ClientState, error) {
- return nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "cannot update localhost client with a proposal")
-}
-
-// VerifyUpgradeAndUpdateState returns an error since localhost cannot be upgraded
-func (cs ClientState) VerifyUpgradeAndUpdateState(
- _ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore,
- _ exported.ClientState, _ exported.ConsensusState, _, _ []byte,
-) (exported.ClientState, exported.ConsensusState, error) {
- return nil, nil, sdkerrors.Wrap(clienttypes.ErrInvalidUpgradeClient, "cannot upgrade localhost client")
-}
-
-// VerifyClientState verifies that the localhost client state is stored locally
-func (cs ClientState) VerifyClientState(
- store sdk.KVStore, cdc codec.BinaryCodec,
- _ exported.Height, _ exported.Prefix, _ string, _ []byte, clientState exported.ClientState,
-) error {
- path := host.KeyClientState
- bz := store.Get([]byte(path))
- if bz == nil {
- return sdkerrors.Wrapf(clienttypes.ErrFailedClientStateVerification,
- "not found for path: %s", path)
- }
-
- selfClient := clienttypes.MustUnmarshalClientState(cdc, bz)
-
- if !reflect.DeepEqual(selfClient, clientState) {
- return sdkerrors.Wrapf(clienttypes.ErrFailedClientStateVerification,
- "stored clientState != provided clientState: \n%v\n≠\n%v",
- selfClient, clientState,
- )
- }
- return nil
-}
-
-// VerifyClientConsensusState returns nil since a local host client does not store consensus
-// states.
-func (cs ClientState) VerifyClientConsensusState(
- sdk.KVStore, codec.BinaryCodec,
- exported.Height, string, exported.Height, exported.Prefix,
- []byte, exported.ConsensusState,
-) error {
- return nil
-}
-
-// VerifyConnectionState verifies a proof of the connection state of the
-// specified connection end stored locally.
-func (cs ClientState) VerifyConnectionState(
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- _ exported.Height,
- _ exported.Prefix,
- _ []byte,
- connectionID string,
- connectionEnd exported.ConnectionI,
-) error {
- path := host.ConnectionKey(connectionID)
- bz := store.Get(path)
- if bz == nil {
- return sdkerrors.Wrapf(clienttypes.ErrFailedConnectionStateVerification, "not found for path %s", path)
- }
-
- var prevConnection connectiontypes.ConnectionEnd
- err := cdc.Unmarshal(bz, &prevConnection)
- if err != nil {
- return err
- }
-
- if !reflect.DeepEqual(&prevConnection, connectionEnd) {
- return sdkerrors.Wrapf(
- clienttypes.ErrFailedConnectionStateVerification,
- "connection end ≠ previous stored connection: \n%v\n≠\n%v", connectionEnd, prevConnection,
- )
- }
-
- return nil
-}
-
-// VerifyChannelState verifies a proof of the channel state of the specified
-// channel end, under the specified port, stored on the local machine.
-func (cs ClientState) VerifyChannelState(
- store sdk.KVStore,
- cdc codec.BinaryCodec,
- _ exported.Height,
- prefix exported.Prefix,
- _ []byte,
- portID,
- channelID string,
- channel exported.ChannelI,
-) error {
- path := host.ChannelKey(portID, channelID)
- bz := store.Get(path)
- if bz == nil {
- return sdkerrors.Wrapf(clienttypes.ErrFailedChannelStateVerification, "not found for path %s", path)
- }
-
- var prevChannel channeltypes.Channel
- err := cdc.Unmarshal(bz, &prevChannel)
- if err != nil {
- return err
- }
-
- if !reflect.DeepEqual(&prevChannel, channel) {
- return sdkerrors.Wrapf(
- clienttypes.ErrFailedChannelStateVerification,
- "channel end ≠ previous stored channel: \n%v\n≠\n%v", channel, prevChannel,
- )
- }
-
- return nil
-}
-
-// VerifyPacketCommitment verifies a proof of an outgoing packet commitment at
-// the specified port, specified channel, and specified sequence.
-func (cs ClientState) VerifyPacketCommitment(
- ctx sdk.Context,
- store sdk.KVStore,
- _ codec.BinaryCodec,
- _ exported.Height,
- _ uint64,
- _ uint64,
- _ exported.Prefix,
- _ []byte,
- portID,
- channelID string,
- sequence uint64,
- commitmentBytes []byte,
-) error {
- path := host.PacketCommitmentKey(portID, channelID, sequence)
-
- data := store.Get(path)
- if len(data) == 0 {
- return sdkerrors.Wrapf(clienttypes.ErrFailedPacketCommitmentVerification, "not found for path %s", path)
- }
-
- if !bytes.Equal(data, commitmentBytes) {
- return sdkerrors.Wrapf(
- clienttypes.ErrFailedPacketCommitmentVerification,
- "commitment ≠ previous commitment: \n%X\n≠\n%X", commitmentBytes, data,
- )
- }
-
- return nil
-}
-
-// VerifyPacketAcknowledgement verifies a proof of an incoming packet
-// acknowledgement at the specified port, specified channel, and specified sequence.
-func (cs ClientState) VerifyPacketAcknowledgement(
- ctx sdk.Context,
- store sdk.KVStore,
- _ codec.BinaryCodec,
- _ exported.Height,
- _ uint64,
- _ uint64,
- _ exported.Prefix,
- _ []byte,
- portID,
- channelID string,
- sequence uint64,
- acknowledgement []byte,
-) error {
- path := host.PacketAcknowledgementKey(portID, channelID, sequence)
-
- data := store.Get(path)
- if len(data) == 0 {
- return sdkerrors.Wrapf(clienttypes.ErrFailedPacketAckVerification, "not found for path %s", path)
- }
-
- if !bytes.Equal(data, acknowledgement) {
- return sdkerrors.Wrapf(
- clienttypes.ErrFailedPacketAckVerification,
- "ak bytes ≠ previous ack: \n%X\n≠\n%X", acknowledgement, data,
- )
- }
-
- return nil
-}
-
-// VerifyPacketReceiptAbsence verifies a proof of the absence of an
-// incoming packet receipt at the specified port, specified channel, and
-// specified sequence.
-func (cs ClientState) VerifyPacketReceiptAbsence(
- ctx sdk.Context,
- store sdk.KVStore,
- _ codec.BinaryCodec,
- _ exported.Height,
- _ uint64,
- _ uint64,
- _ exported.Prefix,
- _ []byte,
- portID,
- channelID string,
- sequence uint64,
-) error {
- path := host.PacketReceiptKey(portID, channelID, sequence)
-
- data := store.Get(path)
- if data != nil {
- return sdkerrors.Wrap(clienttypes.ErrFailedPacketReceiptVerification, "expected no packet receipt")
- }
-
- return nil
-}
-
-// VerifyNextSequenceRecv verifies a proof of the next sequence number to be
-// received of the specified channel at the specified port.
-func (cs ClientState) VerifyNextSequenceRecv(
- ctx sdk.Context,
- store sdk.KVStore,
- _ codec.BinaryCodec,
- _ exported.Height,
- _ uint64,
- _ uint64,
- _ exported.Prefix,
- _ []byte,
- portID,
- channelID string,
- nextSequenceRecv uint64,
-) error {
- path := host.NextSequenceRecvKey(portID, channelID)
-
- data := store.Get(path)
- if len(data) == 0 {
- return sdkerrors.Wrapf(clienttypes.ErrFailedNextSeqRecvVerification, "not found for path %s", path)
- }
-
- prevSequenceRecv := binary.BigEndian.Uint64(data)
- if prevSequenceRecv != nextSequenceRecv {
- return sdkerrors.Wrapf(
- clienttypes.ErrFailedNextSeqRecvVerification,
- "next sequence receive ≠ previous stored sequence (%d ≠ %d)", nextSequenceRecv, prevSequenceRecv,
- )
- }
-
- return nil
-}
diff --git a/modules/light-clients/09-localhost/types/client_state_test.go b/modules/light-clients/09-localhost/types/client_state_test.go
deleted file mode 100644
index 83eb0e8ea51..00000000000
--- a/modules/light-clients/09-localhost/types/client_state_test.go
+++ /dev/null
@@ -1,526 +0,0 @@
-package types_test
-
-import (
- sdk "github.com/cosmos/cosmos-sdk/types"
-
- clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- connectiontypes "github.com/cosmos/ibc-go/v5/modules/core/03-connection/types"
- channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
- commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
- host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
- "github.com/cosmos/ibc-go/v5/modules/light-clients/09-localhost/types"
-)
-
-const (
- testConnectionID = "connectionid"
- testPortID = "testportid"
- testChannelID = "testchannelid"
- 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
- clientState *types.ClientState
- expPass bool
- }{
- {
- name: "valid client",
- clientState: types.NewClientState("chainID", clienttypes.NewHeight(3, 10)),
- expPass: true,
- },
- {
- name: "invalid chain id",
- clientState: types.NewClientState(" ", clienttypes.NewHeight(3, 10)),
- expPass: false,
- },
- {
- name: "invalid height",
- clientState: types.NewClientState("chainID", clienttypes.ZeroHeight()),
- expPass: false,
- },
- }
-
- for _, tc := range testCases {
- err := tc.clientState.Validate()
- if tc.expPass {
- suite.Require().NoError(err, tc.name)
- } else {
- suite.Require().Error(err, tc.name)
- }
- }
-}
-
-func (suite *LocalhostTestSuite) TestInitialize() {
- testCases := []struct {
- name string
- consState exported.ConsensusState
- expPass bool
- }{
- {
- "valid initialization",
- nil,
- true,
- },
- {
- "invalid consenus state",
- &ibctmtypes.ConsensusState{},
- false,
- },
- }
-
- clientState := types.NewClientState("chainID", clienttypes.NewHeight(3, 10))
-
- for _, tc := range testCases {
- err := clientState.Initialize(suite.ctx, suite.cdc, suite.store, tc.consState)
-
- if tc.expPass {
- suite.Require().NoError(err, "valid testcase: %s failed", tc.name)
- } else {
- suite.Require().Error(err, "invalid testcase: %s passed", tc.name)
- }
- }
-}
-
-func (suite *LocalhostTestSuite) TestVerifyClientState() {
- clientState := types.NewClientState("chainID", clientHeight)
- invalidClient := types.NewClientState("chainID", clienttypes.NewHeight(0, 12))
-
- testCases := []struct {
- name string
- clientState *types.ClientState
- malleate func()
- counterparty *types.ClientState
- expPass bool
- }{
- {
- name: "proof verification success",
- clientState: clientState,
- malleate: func() {
- bz := clienttypes.MustMarshalClientState(suite.cdc, clientState)
- suite.store.Set(host.ClientStateKey(), bz)
- },
- counterparty: clientState,
- expPass: true,
- },
- {
- name: "proof verification failed: invalid client",
- clientState: clientState,
- malleate: func() {
- bz := clienttypes.MustMarshalClientState(suite.cdc, clientState)
- suite.store.Set(host.ClientStateKey(), bz)
- },
- counterparty: invalidClient,
- expPass: false,
- },
- {
- name: "proof verification failed: client not stored",
- clientState: clientState,
- malleate: func() {},
- counterparty: clientState,
- expPass: false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- suite.SetupTest()
- tc.malleate()
-
- err := tc.clientState.VerifyClientState(
- suite.store, suite.cdc, clienttypes.NewHeight(0, 10), nil, "", []byte{}, tc.counterparty,
- )
-
- if tc.expPass {
- suite.Require().NoError(err)
- } else {
- suite.Require().Error(err)
- }
- })
- }
-}
-
-func (suite *LocalhostTestSuite) TestVerifyClientConsensusState() {
- clientState := types.NewClientState("chainID", clientHeight)
- err := clientState.VerifyClientConsensusState(
- nil, nil, nil, "", nil, nil, nil, nil,
- )
- suite.Require().NoError(err)
-}
-
-func (suite *LocalhostTestSuite) TestCheckHeaderAndUpdateState() {
- clientState := types.NewClientState("chainID", clientHeight)
- cs, _, err := clientState.CheckHeaderAndUpdateState(suite.ctx, nil, nil, nil)
- suite.Require().NoError(err)
- suite.Require().Equal(uint64(0), cs.GetLatestHeight().GetRevisionNumber())
- suite.Require().Equal(suite.ctx.BlockHeight(), int64(cs.GetLatestHeight().GetRevisionHeight()))
- suite.Require().Equal(suite.ctx.BlockHeader().ChainID, clientState.ChainId)
-}
-
-func (suite *LocalhostTestSuite) TestMisbehaviourAndUpdateState() {
- clientState := types.NewClientState("chainID", clientHeight)
- cs, err := clientState.CheckMisbehaviourAndUpdateState(suite.ctx, nil, nil, nil)
- suite.Require().Error(err)
- suite.Require().Nil(cs)
-}
-
-func (suite *LocalhostTestSuite) TestProposedHeaderAndUpdateState() {
- clientState := types.NewClientState("chainID", clientHeight)
- cs, err := clientState.CheckSubstituteAndUpdateState(suite.ctx, nil, nil, nil, nil)
- suite.Require().Error(err)
- suite.Require().Nil(cs)
-}
-
-func (suite *LocalhostTestSuite) TestVerifyConnectionState() {
- counterparty := connectiontypes.NewCounterparty("clientB", testConnectionID, commitmenttypes.NewMerklePrefix([]byte("ibc")))
- conn1 := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "clientA", counterparty, []*connectiontypes.Version{connectiontypes.NewVersion("1", nil)}, 0)
- conn2 := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "clientA", counterparty, []*connectiontypes.Version{connectiontypes.NewVersion("2", nil)}, 0)
-
- testCases := []struct {
- name string
- clientState *types.ClientState
- malleate func()
- connection connectiontypes.ConnectionEnd
- expPass bool
- }{
- {
- name: "proof verification success",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {
- bz, err := suite.cdc.Marshal(&conn1)
- suite.Require().NoError(err)
- suite.store.Set(host.ConnectionKey(testConnectionID), bz)
- },
- connection: conn1,
- expPass: true,
- },
- {
- name: "proof verification failed: connection not stored",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {},
- connection: conn1,
- expPass: false,
- },
- {
- name: "proof verification failed: unmarshal error",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {
- suite.store.Set(host.ConnectionKey(testConnectionID), []byte("connection"))
- },
- connection: conn1,
- expPass: false,
- },
- {
- name: "proof verification failed: different connection stored",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {
- bz, err := suite.cdc.Marshal(&conn2)
- suite.Require().NoError(err)
- suite.store.Set(host.ConnectionKey(testConnectionID), bz)
- },
- connection: conn1,
- expPass: false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- suite.SetupTest()
- tc.malleate()
-
- err := tc.clientState.VerifyConnectionState(
- suite.store, suite.cdc, clientHeight, nil, []byte{}, testConnectionID, &tc.connection,
- )
-
- if tc.expPass {
- suite.Require().NoError(err)
- } else {
- suite.Require().Error(err)
- }
- })
- }
-}
-
-func (suite *LocalhostTestSuite) TestVerifyChannelState() {
- counterparty := channeltypes.NewCounterparty(testPortID, testChannelID)
- ch1 := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, counterparty, []string{testConnectionID}, "1.0.0")
- ch2 := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, counterparty, []string{testConnectionID}, "2.0.0")
-
- testCases := []struct {
- name string
- clientState *types.ClientState
- malleate func()
- channel channeltypes.Channel
- expPass bool
- }{
- {
- name: "proof verification success",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {
- bz, err := suite.cdc.Marshal(&ch1)
- suite.Require().NoError(err)
- suite.store.Set(host.ChannelKey(testPortID, testChannelID), bz)
- },
- channel: ch1,
- expPass: true,
- },
- {
- name: "proof verification failed: channel not stored",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {},
- channel: ch1,
- expPass: false,
- },
- {
- name: "proof verification failed: unmarshal failed",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {
- suite.store.Set(host.ChannelKey(testPortID, testChannelID), []byte("channel"))
- },
- channel: ch1,
- expPass: false,
- },
- {
- name: "proof verification failed: different channel stored",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {
- bz, err := suite.cdc.Marshal(&ch2)
- suite.Require().NoError(err)
- suite.store.Set(host.ChannelKey(testPortID, testChannelID), bz)
- },
- channel: ch1,
- expPass: false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- suite.SetupTest()
- tc.malleate()
-
- err := tc.clientState.VerifyChannelState(
- suite.store, suite.cdc, clientHeight, nil, []byte{}, testPortID, testChannelID, &tc.channel,
- )
-
- if tc.expPass {
- suite.Require().NoError(err)
- } else {
- suite.Require().Error(err)
- }
- })
- }
-}
-
-func (suite *LocalhostTestSuite) TestVerifyPacketCommitment() {
- testCases := []struct {
- name string
- clientState *types.ClientState
- malleate func()
- commitment []byte
- expPass bool
- }{
- {
- name: "proof verification success",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {
- suite.store.Set(
- host.PacketCommitmentKey(testPortID, testChannelID, testSequence), []byte("commitment"),
- )
- },
- commitment: []byte("commitment"),
- expPass: true,
- },
- {
- name: "proof verification failed: different commitment stored",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {
- suite.store.Set(
- host.PacketCommitmentKey(testPortID, testChannelID, testSequence), []byte("different"),
- )
- },
- commitment: []byte("commitment"),
- expPass: false,
- },
- {
- name: "proof verification failed: no commitment stored",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {},
- commitment: []byte{},
- expPass: false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- suite.SetupTest()
- tc.malleate()
-
- err := tc.clientState.VerifyPacketCommitment(
- suite.ctx, suite.store, suite.cdc, clientHeight, 0, 0, nil, []byte{}, testPortID, testChannelID, testSequence, tc.commitment,
- )
-
- if tc.expPass {
- suite.Require().NoError(err)
- } else {
- suite.Require().Error(err)
- }
- })
- }
-}
-
-func (suite *LocalhostTestSuite) TestVerifyPacketAcknowledgement() {
- testCases := []struct {
- name string
- clientState *types.ClientState
- malleate func()
- ack []byte
- expPass bool
- }{
- {
- name: "proof verification success",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {
- suite.store.Set(
- host.PacketAcknowledgementKey(testPortID, testChannelID, testSequence), []byte("acknowledgement"),
- )
- },
- ack: []byte("acknowledgement"),
- expPass: true,
- },
- {
- name: "proof verification failed: different ack stored",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {
- suite.store.Set(
- host.PacketAcknowledgementKey(testPortID, testChannelID, testSequence), []byte("different"),
- )
- },
- ack: []byte("acknowledgement"),
- expPass: false,
- },
- {
- name: "proof verification failed: no commitment stored",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {},
- ack: []byte{},
- expPass: false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- suite.SetupTest()
- tc.malleate()
-
- err := tc.clientState.VerifyPacketAcknowledgement(
- suite.ctx, suite.store, suite.cdc, clientHeight, 0, 0, nil, []byte{}, testPortID, testChannelID, testSequence, tc.ack,
- )
-
- if tc.expPass {
- suite.Require().NoError(err)
- } else {
- suite.Require().Error(err)
- }
- })
- }
-}
-
-func (suite *LocalhostTestSuite) TestVerifyPacketReceiptAbsence() {
- clientState := types.NewClientState("chainID", clientHeight)
-
- err := clientState.VerifyPacketReceiptAbsence(
- suite.ctx, suite.store, suite.cdc, clientHeight, 0, 0, nil, nil, testPortID, testChannelID, testSequence,
- )
-
- suite.Require().NoError(err, "receipt absence failed")
-
- suite.store.Set(host.PacketReceiptKey(testPortID, testChannelID, testSequence), []byte("receipt"))
-
- err = clientState.VerifyPacketReceiptAbsence(
- suite.ctx, suite.store, suite.cdc, clientHeight, 0, 0, nil, nil, testPortID, testChannelID, testSequence,
- )
- suite.Require().Error(err, "receipt exists in store")
-}
-
-func (suite *LocalhostTestSuite) TestVerifyNextSeqRecv() {
- nextSeqRecv := uint64(5)
-
- testCases := []struct {
- name string
- clientState *types.ClientState
- malleate func()
- nextSeqRecv uint64
- expPass bool
- }{
- {
- name: "proof verification success",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {
- suite.store.Set(
- host.NextSequenceRecvKey(testPortID, testChannelID),
- sdk.Uint64ToBigEndian(nextSeqRecv),
- )
- },
- nextSeqRecv: nextSeqRecv,
- expPass: true,
- },
- {
- name: "proof verification failed: different nextSeqRecv stored",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {
- suite.store.Set(
- host.NextSequenceRecvKey(testPortID, testChannelID),
- sdk.Uint64ToBigEndian(3),
- )
- },
- nextSeqRecv: nextSeqRecv,
- expPass: false,
- },
- {
- name: "proof verification failed: no nextSeqRecv stored",
- clientState: types.NewClientState("chainID", clientHeight),
- malleate: func() {},
- nextSeqRecv: nextSeqRecv,
- expPass: false,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- suite.Run(tc.name, func() {
- suite.SetupTest()
- tc.malleate()
-
- err := tc.clientState.VerifyNextSequenceRecv(
- suite.ctx, suite.store, suite.cdc, clientHeight, 0, 0, nil, []byte{}, testPortID, testChannelID, nextSeqRecv,
- )
-
- if tc.expPass {
- suite.Require().NoError(err)
- } else {
- suite.Require().Error(err)
- }
- })
- }
-}
diff --git a/modules/light-clients/09-localhost/types/codec.go b/modules/light-clients/09-localhost/types/codec.go
deleted file mode 100644
index 0e0a31d31d7..00000000000
--- a/modules/light-clients/09-localhost/types/codec.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package types
-
-import (
- codectypes "github.com/cosmos/cosmos-sdk/codec/types"
-
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
-)
-
-// RegisterInterfaces register the ibc interfaces submodule implementations to protobuf
-// Any.
-func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
- registry.RegisterImplementations(
- (*exported.ClientState)(nil),
- &ClientState{},
- )
-}
diff --git a/modules/light-clients/09-localhost/types/errors.go b/modules/light-clients/09-localhost/types/errors.go
deleted file mode 100644
index 57ad7c1f6a6..00000000000
--- a/modules/light-clients/09-localhost/types/errors.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package types
-
-import (
- sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
-)
-
-// Localhost sentinel errors
-var (
- ErrConsensusStatesNotStored = sdkerrors.Register(SubModuleName, 2, "localhost does not store consensus states")
-)
diff --git a/modules/light-clients/09-localhost/types/keys.go b/modules/light-clients/09-localhost/types/keys.go
deleted file mode 100644
index 2fe7c7e48f5..00000000000
--- a/modules/light-clients/09-localhost/types/keys.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package types
-
-const (
- // SubModuleName for the localhost (loopback) client
- SubModuleName = "localhost"
-)
diff --git a/modules/light-clients/09-localhost/types/localhost.pb.go b/modules/light-clients/09-localhost/types/localhost.pb.go
deleted file mode 100644
index 7c674191e64..00000000000
--- a/modules/light-clients/09-localhost/types/localhost.pb.go
+++ /dev/null
@@ -1,369 +0,0 @@
-// Code generated by protoc-gen-gogo. DO NOT EDIT.
-// source: ibc/lightclients/localhost/v1/localhost.proto
-
-package types
-
-import (
- fmt "fmt"
- types "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- _ "github.com/gogo/protobuf/gogoproto"
- proto "github.com/gogo/protobuf/proto"
- io "io"
- math "math"
- math_bits "math/bits"
-)
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
-
-// ClientState defines a loopback (localhost) client. It requires (read-only)
-// access to keys outside the client prefix.
-type ClientState struct {
- // self chain ID
- ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty" yaml:"chain_id"`
- // self latest block height
- Height types.Height `protobuf:"bytes,2,opt,name=height,proto3" json:"height"`
-}
-
-func (m *ClientState) Reset() { *m = ClientState{} }
-func (m *ClientState) String() string { return proto.CompactTextString(m) }
-func (*ClientState) ProtoMessage() {}
-func (*ClientState) Descriptor() ([]byte, []int) {
- return fileDescriptor_acd9f5b22d41bf6d, []int{0}
-}
-func (m *ClientState) XXX_Unmarshal(b []byte) error {
- return m.Unmarshal(b)
-}
-func (m *ClientState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
- if deterministic {
- return xxx_messageInfo_ClientState.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 *ClientState) XXX_Merge(src proto.Message) {
- xxx_messageInfo_ClientState.Merge(m, src)
-}
-func (m *ClientState) XXX_Size() int {
- return m.Size()
-}
-func (m *ClientState) XXX_DiscardUnknown() {
- xxx_messageInfo_ClientState.DiscardUnknown(m)
-}
-
-var xxx_messageInfo_ClientState proto.InternalMessageInfo
-
-func init() {
- proto.RegisterType((*ClientState)(nil), "ibc.lightclients.localhost.v1.ClientState")
-}
-
-func init() {
- proto.RegisterFile("ibc/lightclients/localhost/v1/localhost.proto", fileDescriptor_acd9f5b22d41bf6d)
-}
-
-var fileDescriptor_acd9f5b22d41bf6d = []byte{
- // 288 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0xcd, 0x4c, 0x4a, 0xd6,
- 0xcf, 0xc9, 0x4c, 0xcf, 0x28, 0x49, 0xce, 0xc9, 0x4c, 0xcd, 0x2b, 0x29, 0xd6, 0xcf, 0xc9, 0x4f,
- 0x4e, 0xcc, 0xc9, 0xc8, 0x2f, 0x2e, 0xd1, 0x2f, 0x33, 0x44, 0x70, 0xf4, 0x0a, 0x8a, 0xf2, 0x4b,
- 0xf2, 0x85, 0x64, 0x33, 0x93, 0x92, 0xf5, 0x90, 0x95, 0xeb, 0x21, 0x54, 0x94, 0x19, 0x4a, 0x89,
- 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x55, 0xea, 0x83, 0x58, 0x10, 0x4d, 0x52, 0xf2, 0x20, 0x3b, 0x92,
- 0xf3, 0x8b, 0x52, 0xf5, 0x21, 0x9a, 0x40, 0x06, 0x43, 0x58, 0x10, 0x05, 0x4a, 0xb5, 0x5c, 0xdc,
- 0xce, 0x60, 0x7e, 0x70, 0x49, 0x62, 0x49, 0xaa, 0x90, 0x1e, 0x17, 0x47, 0x72, 0x46, 0x62, 0x66,
- 0x5e, 0x7c, 0x66, 0x8a, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xa7, 0x93, 0xf0, 0xa7, 0x7b, 0xf2, 0xfc,
- 0x95, 0x89, 0xb9, 0x39, 0x56, 0x4a, 0x30, 0x19, 0xa5, 0x20, 0x76, 0x30, 0xd3, 0x33, 0x45, 0xc8,
- 0x82, 0x8b, 0x2d, 0x23, 0x15, 0xe4, 0x26, 0x09, 0x26, 0x05, 0x46, 0x0d, 0x6e, 0x23, 0x29, 0x3d,
- 0x90, 0x2b, 0x41, 0x16, 0xea, 0x41, 0xad, 0x29, 0x33, 0xd4, 0xf3, 0x00, 0xab, 0x70, 0x62, 0x39,
- 0x71, 0x4f, 0x9e, 0x21, 0x08, 0xaa, 0xde, 0x8a, 0xa5, 0x63, 0x81, 0x3c, 0x83, 0x53, 0xdc, 0x89,
- 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3,
- 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0xb9, 0xa4, 0x67, 0x96, 0x64, 0x94, 0x26,
- 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x27, 0xe7, 0x17, 0xe7, 0xe6, 0x17, 0xeb, 0x67, 0x26, 0x25, 0xeb,
- 0xa6, 0xe7, 0xeb, 0x97, 0x99, 0xea, 0xe7, 0xe6, 0xa7, 0x94, 0xe6, 0xa4, 0x16, 0x43, 0x42, 0x4f,
- 0x17, 0x16, 0x7c, 0x06, 0x96, 0xba, 0x88, 0x10, 0x2c, 0xa9, 0x2c, 0x48, 0x2d, 0x4e, 0x62, 0x03,
- 0xfb, 0xd2, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x75, 0xe7, 0x2e, 0x11, 0x6c, 0x01, 0x00, 0x00,
-}
-
-func (m *ClientState) 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 *ClientState) MarshalTo(dAtA []byte) (int, error) {
- size := m.Size()
- return m.MarshalToSizedBuffer(dAtA[:size])
-}
-
-func (m *ClientState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
- i := len(dAtA)
- _ = i
- var l int
- _ = l
- {
- size, err := m.Height.MarshalToSizedBuffer(dAtA[:i])
- if err != nil {
- return 0, err
- }
- i -= size
- i = encodeVarintLocalhost(dAtA, i, uint64(size))
- }
- i--
- dAtA[i] = 0x12
- if len(m.ChainId) > 0 {
- i -= len(m.ChainId)
- copy(dAtA[i:], m.ChainId)
- i = encodeVarintLocalhost(dAtA, i, uint64(len(m.ChainId)))
- i--
- dAtA[i] = 0xa
- }
- return len(dAtA) - i, nil
-}
-
-func encodeVarintLocalhost(dAtA []byte, offset int, v uint64) int {
- offset -= sovLocalhost(v)
- base := offset
- for v >= 1<<7 {
- dAtA[offset] = uint8(v&0x7f | 0x80)
- v >>= 7
- offset++
- }
- dAtA[offset] = uint8(v)
- return base
-}
-func (m *ClientState) Size() (n int) {
- if m == nil {
- return 0
- }
- var l int
- _ = l
- l = len(m.ChainId)
- if l > 0 {
- n += 1 + l + sovLocalhost(uint64(l))
- }
- l = m.Height.Size()
- n += 1 + l + sovLocalhost(uint64(l))
- return n
-}
-
-func sovLocalhost(x uint64) (n int) {
- return (math_bits.Len64(x|1) + 6) / 7
-}
-func sozLocalhost(x uint64) (n int) {
- return sovLocalhost(uint64((x << 1) ^ uint64((int64(x) >> 63))))
-}
-func (m *ClientState) 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 ErrIntOverflowLocalhost
- }
- 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: ClientState: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: ClientState: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType)
- }
- var stringLen uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowLocalhost
- }
- 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 ErrInvalidLengthLocalhost
- }
- postIndex := iNdEx + intStringLen
- if postIndex < 0 {
- return ErrInvalidLengthLocalhost
- }
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.ChainId = string(dAtA[iNdEx:postIndex])
- iNdEx = postIndex
- case 2:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType)
- }
- var msglen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowLocalhost
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- msglen |= int(b&0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if msglen < 0 {
- return ErrInvalidLengthLocalhost
- }
- postIndex := iNdEx + msglen
- if postIndex < 0 {
- return ErrInvalidLengthLocalhost
- }
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- if err := m.Height.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipLocalhost(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if (skippy < 0) || (iNdEx+skippy) < 0 {
- return ErrInvalidLengthLocalhost
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func skipLocalhost(dAtA []byte) (n int, err error) {
- l := len(dAtA)
- iNdEx := 0
- depth := 0
- for iNdEx < l {
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowLocalhost
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- wireType := int(wire & 0x7)
- switch wireType {
- case 0:
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowLocalhost
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- iNdEx++
- if dAtA[iNdEx-1] < 0x80 {
- break
- }
- }
- case 1:
- iNdEx += 8
- case 2:
- var length int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowLocalhost
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- length |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if length < 0 {
- return 0, ErrInvalidLengthLocalhost
- }
- iNdEx += length
- case 3:
- depth++
- case 4:
- if depth == 0 {
- return 0, ErrUnexpectedEndOfGroupLocalhost
- }
- depth--
- case 5:
- iNdEx += 4
- default:
- return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
- }
- if iNdEx < 0 {
- return 0, ErrInvalidLengthLocalhost
- }
- if depth == 0 {
- return iNdEx, nil
- }
- }
- return 0, io.ErrUnexpectedEOF
-}
-
-var (
- ErrInvalidLengthLocalhost = fmt.Errorf("proto: negative length found during unmarshaling")
- ErrIntOverflowLocalhost = fmt.Errorf("proto: integer overflow")
- ErrUnexpectedEndOfGroupLocalhost = fmt.Errorf("proto: unexpected end of group")
-)
diff --git a/modules/light-clients/09-localhost/types/localhost_test.go b/modules/light-clients/09-localhost/types/localhost_test.go
deleted file mode 100644
index 50bfdcb62f9..00000000000
--- a/modules/light-clients/09-localhost/types/localhost_test.go
+++ /dev/null
@@ -1,41 +0,0 @@
-package types_test
-
-import (
- "testing"
-
- "github.com/cosmos/cosmos-sdk/codec"
- sdk "github.com/cosmos/cosmos-sdk/types"
- "github.com/stretchr/testify/suite"
- tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
-
- clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
- "github.com/cosmos/ibc-go/v5/modules/core/exported"
- "github.com/cosmos/ibc-go/v5/testing/simapp"
-)
-
-const (
- height = 4
-)
-
-var clientHeight = clienttypes.NewHeight(0, 10)
-
-type LocalhostTestSuite struct {
- suite.Suite
-
- cdc codec.Codec
- ctx sdk.Context
- store sdk.KVStore
-}
-
-func (suite *LocalhostTestSuite) SetupTest() {
- isCheckTx := false
- app := simapp.Setup(isCheckTx)
-
- suite.cdc = app.AppCodec()
- suite.ctx = app.BaseApp.NewContext(isCheckTx, tmproto.Header{Height: 1, ChainID: "ibc-chain"})
- suite.store = app.IBCKeeper.ClientKeeper.ClientStore(suite.ctx, exported.Localhost)
-}
-
-func TestLocalhostTestSuite(t *testing.T) {
- suite.Run(t, new(LocalhostTestSuite))
-}
diff --git a/proto/ibc/core/client/v1/tx.proto b/proto/ibc/core/client/v1/tx.proto
index 8e716226d95..27f81917e4c 100644
--- a/proto/ibc/core/client/v1/tx.proto
+++ b/proto/ibc/core/client/v1/tx.proto
@@ -40,15 +40,15 @@ message MsgCreateClient {
message MsgCreateClientResponse {}
// MsgUpdateClient defines an sdk.Msg to update a IBC client state using
-// the given header.
+// the given client message.
message MsgUpdateClient {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
// client unique identifier
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
- // header to update the light client
- google.protobuf.Any header = 2;
+ // client message to update the light client
+ google.protobuf.Any client_message = 2;
// signer address
string signer = 3;
}
@@ -82,16 +82,17 @@ message MsgUpgradeClientResponse {}
// MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for
// light client misbehaviour.
+// Warning: DEPRECATED
message MsgSubmitMisbehaviour {
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\"", deprecated = true];
// misbehaviour used for freezing the light client
- google.protobuf.Any misbehaviour = 2;
+ google.protobuf.Any misbehaviour = 2 [deprecated = true];
// signer address
- string signer = 3;
+ string signer = 3 [deprecated = true];
}
// MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response
diff --git a/proto/ibc/lightclients/localhost/v1/localhost.proto b/proto/ibc/lightclients/localhost/v1/localhost.proto
deleted file mode 100644
index 909c4ebcef5..00000000000
--- a/proto/ibc/lightclients/localhost/v1/localhost.proto
+++ /dev/null
@@ -1,18 +0,0 @@
-syntax = "proto3";
-
-package ibc.lightclients.localhost.v1;
-
-option go_package = "github.com/cosmos/ibc-go/v5/modules/light-clients/09-localhost/types";
-
-import "gogoproto/gogo.proto";
-import "ibc/core/client/v1/client.proto";
-
-// ClientState defines a loopback (localhost) client. It requires (read-only)
-// access to keys outside the client prefix.
-message ClientState {
- option (gogoproto.goproto_getters) = false;
- // self 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];
-}
diff --git a/proto/ibc/lightclients/solomachine/v2/solomachine.proto b/proto/ibc/lightclients/solomachine/v2/solomachine.proto
index 61dcc45b2d7..5cc5ba9c551 100644
--- a/proto/ibc/lightclients/solomachine/v2/solomachine.proto
+++ b/proto/ibc/lightclients/solomachine/v2/solomachine.proto
@@ -2,7 +2,7 @@ syntax = "proto3";
package ibc.lightclients.solomachine.v2;
-option go_package = "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types";
+option go_package = "github.com/cosmos/ibc-go/v5/modules/core/02-client/migrations/v6";
import "ibc/core/connection/v1/connection.proto";
import "ibc/core/channel/v1/channel.proto";
diff --git a/proto/ibc/lightclients/solomachine/v3/solomachine.proto b/proto/ibc/lightclients/solomachine/v3/solomachine.proto
new file mode 100644
index 00000000000..5475a16bd93
--- /dev/null
+++ b/proto/ibc/lightclients/solomachine/v3/solomachine.proto
@@ -0,0 +1,103 @@
+syntax = "proto3";
+
+package ibc.lightclients.solomachine.v3;
+
+option go_package = "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine;solomachine";
+
+import "gogoproto/gogo.proto";
+import "google/protobuf/any.proto";
+
+// ClientState defines a solo machine client that tracks the current consensus
+// state and if the client is frozen.
+message ClientState {
+ option (gogoproto.goproto_getters) = false;
+ // latest sequence of the client state
+ uint64 sequence = 1;
+ // frozen sequence of the solo machine
+ bool is_frozen = 2 [(gogoproto.moretags) = "yaml:\"is_frozen\""];
+ 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\""];
+}
+
+// ConsensusState defines a solo machine consensus state. The sequence of a
+// consensus state is contained in the "height" key used in storing the
+// consensus state.
+message ConsensusState {
+ option (gogoproto.goproto_getters) = false;
+ // public key of the solo machine
+ 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;
+}
+
+// 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\""];
+}
+
+// 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;
+
+ // ClientID is deprecated
+ string client_id = 1 [deprecated = true, (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;
+ bytes path = 2;
+ 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;
+}
+
+// SignBytes defines the signed bytes used for signature verification.
+message SignBytes {
+ option (gogoproto.goproto_getters) = false;
+
+ // the sequence number
+ uint64 sequence = 1;
+ // the proof timestamp
+ uint64 timestamp = 2;
+ // the public key diversifier
+ string diversifier = 3;
+ // the standardised path bytes
+ bytes path = 4;
+ // the marshaled data bytes
+ bytes data = 5;
+}
+
+// HeaderData returns the SignBytes data for update verification.
+message HeaderData {
+ option (gogoproto.goproto_getters) = false;
+
+ // header public 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\""];
+}
diff --git a/proto/ibc/lightclients/tendermint/v1/tendermint.proto b/proto/ibc/lightclients/tendermint/v1/tendermint.proto
index 48b47aee6cb..27c5c909460 100644
--- a/proto/ibc/lightclients/tendermint/v1/tendermint.proto
+++ b/proto/ibc/lightclients/tendermint/v1/tendermint.proto
@@ -2,7 +2,7 @@ syntax = "proto3";
package ibc.lightclients.tendermint.v1;
-option go_package = "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types";
+option go_package = "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint;tendermint";
import "tendermint/types/validator.proto";
import "tendermint/types/types.proto";
@@ -79,7 +79,8 @@ message ConsensusState {
message Misbehaviour {
option (gogoproto.goproto_getters) = false;
- string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
+ // ClientID is deprecated
+ string client_id = 1 [deprecated = true, (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\""];
}
diff --git a/testing/README.md b/testing/README.md
index c682ba9ed8e..a488ffa42f1 100644
--- a/testing/README.md
+++ b/testing/README.md
@@ -255,8 +255,8 @@ import (
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
- "github.com/cosmos/ibc-go/v4/modules/apps/transfer/simapp"
- ibctesting "github.com/cosmos/ibc-go/v4/testing"
+ "github.com/cosmos/ibc-go/v5/modules/apps/transfer/simapp"
+ ibctesting "github.com/cosmos/ibc-go/v5/testing"
)
func SetupTransferTestingApp() (ibctesting.TestingApp, map[string]json.RawMessage) {
diff --git a/testing/chain.go b/testing/chain.go
index ab7f707007c..9e01513e66b 100644
--- a/testing/chain.go
+++ b/testing/chain.go
@@ -30,7 +30,7 @@ import (
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
"github.com/cosmos/ibc-go/v5/modules/core/types"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
"github.com/cosmos/ibc-go/v5/testing/mock"
"github.com/cosmos/ibc-go/v5/testing/simapp"
)
@@ -53,8 +53,8 @@ type TestChain struct {
Coordinator *Coordinator
App TestingApp
ChainID string
- LastHeader *ibctmtypes.Header // header for last block height committed
- CurrentHeader tmproto.Header // header for current block height
+ LastHeader *ibctm.Header // header for last block height committed
+ CurrentHeader tmproto.Header // header for current block height
QueryServer types.QueryServer
TxConfig client.TxConfig
Codec codec.BinaryCodec
@@ -200,11 +200,18 @@ func (chain *TestChain) QueryProof(key []byte) ([]byte, clienttypes.Height) {
return chain.QueryProofAtHeight(key, chain.App.LastBlockHeight())
}
-// QueryProof performs an abci query with the given key and returns the proto encoded merkle proof
-// for the query and the height at which the proof will succeed on a tendermint verifier.
+// QueryProofAtHeight performs an abci query with the given key and returns the proto encoded merkle proof
+// for the query and the height at which the proof will succeed on a tendermint verifier. Only the IBC
+// store is supported
func (chain *TestChain) QueryProofAtHeight(key []byte, height int64) ([]byte, clienttypes.Height) {
+ return chain.QueryProofForStore(host.StoreKey, key, height)
+}
+
+// QueryProofForStore performs an abci query with the given key and returns the proto encoded merkle proof
+// for the query and the height at which the proof will succeed on a tendermint verifier.
+func (chain *TestChain) QueryProofForStore(storeKey string, key []byte, height int64) ([]byte, clienttypes.Height) {
res := chain.App.Query(abci.RequestQuery{
- Path: fmt.Sprintf("store/%s/key", host.StoreKey),
+ Path: fmt.Sprintf("store/%s/key", storeKey),
Height: height - 1,
Data: key,
Prove: true,
@@ -385,13 +392,13 @@ 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) {
+func (chain *TestChain) ConstructUpdateTMClientHeader(counterparty *TestChain, clientID string) (*ibctm.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) {
+func (chain *TestChain) ConstructUpdateTMClientHeaderWithTrustedHeight(counterparty *TestChain, clientID string, trustedHeight clienttypes.Height) (*ibctm.Header, error) {
header := counterparty.LastHeader
// Relayer must query for LatestHeight on client to get TrustedHeight if the trusted height is not set
if trustedHeight.IsZero() {
@@ -413,7 +420,7 @@ func (chain *TestChain) ConstructUpdateTMClientHeaderWithTrustedHeight(counterpa
// NextValidatorsHash
tmTrustedVals, ok = counterparty.GetValsAtHeight(int64(trustedHeight.RevisionHeight + 1))
if !ok {
- return nil, sdkerrors.Wrapf(ibctmtypes.ErrInvalidHeaderHeight, "could not retrieve trusted validators at trustedHeight: %d", trustedHeight)
+ return nil, sdkerrors.Wrapf(ibctm.ErrInvalidHeaderHeight, "could not retrieve trusted validators at trustedHeight: %d", trustedHeight)
}
}
// inject trusted fields into last header
@@ -437,13 +444,13 @@ func (chain *TestChain) ExpireClient(amount time.Duration) {
// CurrentTMClientHeader creates a TM header using the current header parameters
// on the chain. The trusted fields in the header are set to nil.
-func (chain *TestChain) CurrentTMClientHeader() *ibctmtypes.Header {
+func (chain *TestChain) CurrentTMClientHeader() *ibctm.Header {
return chain.CreateTMClientHeader(chain.ChainID, chain.CurrentHeader.Height, clienttypes.Height{}, chain.CurrentHeader.Time, chain.Vals, chain.NextVals, nil, chain.Signers)
}
// CreateTMClientHeader creates a TM header to update the TM client. Args are passed in to allow
// caller flexibility to use params that differ from the chain.
-func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64, trustedHeight clienttypes.Height, timestamp time.Time, tmValSet, nextVals, tmTrustedVals *tmtypes.ValidatorSet, signers map[string]tmtypes.PrivValidator) *ibctmtypes.Header {
+func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64, trustedHeight clienttypes.Height, timestamp time.Time, tmValSet, nextVals, tmTrustedVals *tmtypes.ValidatorSet, signers map[string]tmtypes.PrivValidator) *ibctm.Header {
var (
valSet *tmproto.ValidatorSet
trustedVals *tmproto.ValidatorSet
@@ -502,7 +509,7 @@ func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64,
// The trusted fields may be nil. They may be filled before relaying messages to a client.
// The relayer is responsible for querying client and injecting appropriate trusted fields.
- return &ibctmtypes.Header{
+ return &ibctm.Header{
SignedHeader: signedHeader,
ValidatorSet: valSet,
TrustedHeight: trustedHeight,
diff --git a/testing/config.go b/testing/config.go
index 2090681a53e..768aa968708 100644
--- a/testing/config.go
+++ b/testing/config.go
@@ -6,7 +6,7 @@ import (
connectiontypes "github.com/cosmos/ibc-go/v5/modules/core/03-connection/types"
channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
"github.com/cosmos/ibc-go/v5/testing/mock"
)
@@ -15,7 +15,7 @@ type ClientConfig interface {
}
type TendermintConfig struct {
- TrustLevel ibctmtypes.Fraction
+ TrustLevel ibctm.Fraction
TrustingPeriod time.Duration
UnbondingPeriod time.Duration
MaxClockDrift time.Duration
diff --git a/testing/coordinator.go b/testing/coordinator.go
index f2cc49f9a91..6374a17b170 100644
--- a/testing/coordinator.go
+++ b/testing/coordinator.go
@@ -11,7 +11,9 @@ import (
)
var (
- ChainIDPrefix = "testchain"
+ ChainIDPrefix = "testchain"
+ // to disable revision format, set ChainIDSuffix to ""
+ ChainIDSuffix = "-1"
globalStartTime = time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC)
TimeIncrement = time.Second * 5
)
@@ -173,7 +175,7 @@ func (coord *Coordinator) GetChain(chainID string) *TestChain {
// GetChainID returns the chainID used for the provided index.
func GetChainID(index int) string {
- return ChainIDPrefix + strconv.Itoa(index)
+ return ChainIDPrefix + strconv.Itoa(index) + ChainIDSuffix
}
// CommitBlock commits a block on the provided indexes and then increments the global time.
diff --git a/testing/endpoint.go b/testing/endpoint.go
index b44fcad035f..8331980da93 100644
--- a/testing/endpoint.go
+++ b/testing/endpoint.go
@@ -2,6 +2,7 @@ package ibctesting
import (
"fmt"
+ "strings"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
@@ -12,7 +13,7 @@ import (
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
)
// Endpoint is a which represents a channel endpoint and its associated
@@ -91,7 +92,7 @@ func (endpoint *Endpoint) CreateClient() (err error) {
require.True(endpoint.Chain.T, ok)
height := endpoint.Counterparty.Chain.LastHeader.GetHeight().(clienttypes.Height)
- clientState = ibctmtypes.NewClientState(
+ clientState = ibctm.NewClientState(
endpoint.Counterparty.Chain.ChainID, tmConfig.TrustLevel, tmConfig.TrustingPeriod, tmConfig.UnbondingPeriod, tmConfig.MaxClockDrift,
height, commitmenttypes.GetSDKSpecs(), UpgradePath, tmConfig.AllowUpdateAfterExpiry, tmConfig.AllowUpdateAfterMisbehaviour,
)
@@ -131,7 +132,7 @@ func (endpoint *Endpoint) UpdateClient() (err error) {
// ensure counterparty has committed state
endpoint.Chain.Coordinator.CommitBlock(endpoint.Counterparty.Chain)
- var header exported.Header
+ var header exported.ClientMessage
switch endpoint.ClientConfig.GetClientType() {
case exported.Tendermint:
@@ -154,6 +155,59 @@ func (endpoint *Endpoint) UpdateClient() (err error) {
return endpoint.Chain.sendMsgs(msg)
}
+// UpgradeChain will upgrade a chain's chainID to the next revision number.
+// It will also update the counterparty client.
+// TODO: implement actual upgrade chain functionality via scheduling an upgrade
+// and upgrading the client via MsgUpgradeClient
+// see reference https://github.com/cosmos/ibc-go/pull/1169
+func (endpoint *Endpoint) UpgradeChain() error {
+ if strings.TrimSpace(endpoint.Counterparty.ClientID) == "" {
+ return fmt.Errorf("cannot upgrade chain if there is no counterparty client")
+ }
+
+ clientState := endpoint.Counterparty.GetClientState().(*ibctm.ClientState)
+
+ // increment revision number in chainID
+
+ oldChainID := clientState.ChainId
+ if !clienttypes.IsRevisionFormat(oldChainID) {
+ return fmt.Errorf("cannot upgrade chain which is not of revision format: %s", oldChainID)
+ }
+
+ revisionNumber := clienttypes.ParseChainID(oldChainID)
+ newChainID, err := clienttypes.SetRevisionNumber(oldChainID, revisionNumber+1)
+ if err != nil {
+ return err
+ }
+
+ // update chain
+ endpoint.Chain.ChainID = newChainID
+ endpoint.Chain.CurrentHeader.ChainID = newChainID
+ endpoint.Chain.NextBlock() // commit changes
+
+ // update counterparty client manually
+ clientState.ChainId = newChainID
+ clientState.LatestHeight = clienttypes.NewHeight(revisionNumber+1, clientState.LatestHeight.GetRevisionHeight()+1)
+ endpoint.Counterparty.SetClientState(clientState)
+
+ consensusState := &ibctm.ConsensusState{
+ Timestamp: endpoint.Chain.LastHeader.GetTime(),
+ Root: commitmenttypes.NewMerkleRoot(endpoint.Chain.LastHeader.Header.GetAppHash()),
+ NextValidatorsHash: endpoint.Chain.LastHeader.Header.NextValidatorsHash,
+ }
+ endpoint.Counterparty.SetConsensusState(consensusState, clientState.GetLatestHeight())
+
+ // ensure the next update isn't identical to the one set in state
+ endpoint.Chain.Coordinator.IncrementTime()
+ endpoint.Chain.NextBlock()
+
+ if err = endpoint.Counterparty.UpdateClient(); err != nil {
+ return err
+ }
+
+ return nil
+}
+
// ConnOpenInit will construct and execute a MsgConnectionOpenInit on the associated endpoint.
func (endpoint *Endpoint) ConnOpenInit() error {
msg := connectiontypes.NewMsgConnectionOpenInit(
diff --git a/testing/solomachine.go b/testing/solomachine.go
index 50974e58268..d22e67afd24 100644
--- a/testing/solomachine.go
+++ b/testing/solomachine.go
@@ -16,7 +16,7 @@ import (
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
"github.com/cosmos/ibc-go/v5/modules/core/exported"
- solomachinetypes "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine/types"
+ solomachinetypes "github.com/cosmos/ibc-go/v5/modules/light-clients/06-solomachine"
)
// Solomachine is a testing helper used to simulate a counterparty
@@ -107,7 +107,8 @@ func (solo *Solomachine) GetHeight() exported.Height {
// CreateHeader generates a new private/public key pair and creates the
// necessary signature to construct a valid solo machine header.
-func (solo *Solomachine) CreateHeader() *solomachinetypes.Header {
+// A new diversifier will be used as well
+func (solo *Solomachine) CreateHeader(newDiversifier string) *solomachinetypes.Header {
// generate new private keys and signature for header
newPrivKeys, newPubKeys, newPubKey := GenerateKeys(solo.t, uint64(len(solo.PrivateKeys)))
@@ -116,7 +117,7 @@ func (solo *Solomachine) CreateHeader() *solomachinetypes.Header {
data := &solomachinetypes.HeaderData{
NewPubKey: publicKey,
- NewDiversifier: solo.Diversifier,
+ NewDiversifier: newDiversifier,
}
dataBz, err := solo.cdc.Marshal(data)
@@ -126,7 +127,7 @@ func (solo *Solomachine) CreateHeader() *solomachinetypes.Header {
Sequence: solo.Sequence,
Timestamp: solo.Time,
Diversifier: solo.Diversifier,
- DataType: solomachinetypes.HEADER,
+ Path: []byte{},
Data: dataBz,
}
@@ -140,7 +141,7 @@ func (solo *Solomachine) CreateHeader() *solomachinetypes.Header {
Timestamp: solo.Time,
Signature: sig,
NewPublicKey: publicKey,
- NewDiversifier: solo.Diversifier,
+ NewDiversifier: newDiversifier,
}
// assumes successful header update
@@ -148,6 +149,7 @@ func (solo *Solomachine) CreateHeader() *solomachinetypes.Header {
solo.PrivateKeys = newPrivKeys
solo.PublicKeys = newPubKeys
solo.PublicKey = newPubKey
+ solo.Diversifier = newDiversifier
return header
}
@@ -155,20 +157,19 @@ func (solo *Solomachine) CreateHeader() *solomachinetypes.Header {
// CreateMisbehaviour constructs testing misbehaviour for the solo machine client
// by signing over two different data bytes at the same sequence.
func (solo *Solomachine) CreateMisbehaviour() *solomachinetypes.Misbehaviour {
- path := solo.GetClientStatePath("counterparty")
- dataOne, err := solomachinetypes.ClientStateDataBytes(solo.cdc, path, solo.ClientState())
+ merklePath := solo.GetClientStatePath("counterparty")
+ path, err := solo.cdc.Marshal(&merklePath)
require.NoError(solo.t, err)
- path = solo.GetConsensusStatePath("counterparty", clienttypes.NewHeight(0, 1))
- dataTwo, err := solomachinetypes.ConsensusStateDataBytes(solo.cdc, path, solo.ConsensusState())
+ data, err := solo.cdc.Marshal(solo.ClientState())
require.NoError(solo.t, err)
signBytes := &solomachinetypes.SignBytes{
Sequence: solo.Sequence,
Timestamp: solo.Time,
Diversifier: solo.Diversifier,
- DataType: solomachinetypes.CLIENT,
- Data: dataOne,
+ Path: path,
+ Data: data,
}
bz, err := solo.cdc.Marshal(signBytes)
@@ -177,20 +178,27 @@ func (solo *Solomachine) CreateMisbehaviour() *solomachinetypes.Misbehaviour {
sig := solo.GenerateSignature(bz)
signatureOne := solomachinetypes.SignatureAndData{
Signature: sig,
- DataType: solomachinetypes.CLIENT,
- Data: dataOne,
+ Path: path,
+ Data: data,
Timestamp: solo.Time,
}
// misbehaviour signaturess can have different timestamps
solo.Time++
+ merklePath = solo.GetConsensusStatePath("counterparty", clienttypes.NewHeight(0, 1))
+ path, err = solo.cdc.Marshal(&merklePath)
+ require.NoError(solo.t, err)
+
+ data, err = solo.cdc.Marshal(solo.ConsensusState())
+ require.NoError(solo.t, err)
+
signBytes = &solomachinetypes.SignBytes{
Sequence: solo.Sequence,
Timestamp: solo.Time,
Diversifier: solo.Diversifier,
- DataType: solomachinetypes.CONSENSUS,
- Data: dataTwo,
+ Path: path,
+ Data: data,
}
bz, err = solo.cdc.Marshal(signBytes)
@@ -199,8 +207,8 @@ func (solo *Solomachine) CreateMisbehaviour() *solomachinetypes.Misbehaviour {
sig = solo.GenerateSignature(bz)
signatureTwo := solomachinetypes.SignatureAndData{
Signature: sig,
- DataType: solomachinetypes.CONSENSUS,
- Data: dataTwo,
+ Path: path,
+ Data: data,
Timestamp: solo.Time,
}
diff --git a/testing/values.go b/testing/values.go
index 46df3b5ba27..e60de189e03 100644
--- a/testing/values.go
+++ b/testing/values.go
@@ -12,7 +12,7 @@ import (
ibctransfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types"
connectiontypes "github.com/cosmos/ibc-go/v5/modules/core/03-connection/types"
commitmenttypes "github.com/cosmos/ibc-go/v5/modules/core/23-commitment/types"
- ibctmtypes "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint/types"
+ ibctm "github.com/cosmos/ibc-go/v5/modules/light-clients/07-tendermint"
"github.com/cosmos/ibc-go/v5/testing/mock"
"github.com/cosmos/ibc-go/v5/testing/simapp"
)
@@ -47,7 +47,7 @@ var (
DefaultOpenInitVersion *connectiontypes.Version
// DefaultTrustLevel sets params variables used to create a TM client
- DefaultTrustLevel = ibctmtypes.DefaultTrustLevel
+ DefaultTrustLevel = ibctm.DefaultTrustLevel
TestCoin = sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))
UpgradePath = []string{"upgrade", "upgradedIBCState"}