Skip to main content

ADR 005: UpdateClient Events - ClientState Consensus Heights


  • 25/04/2022: initial draft




The ibc-go implementation leverages the Cosmos-SDK's EventManager to provide subscribers a method of reacting to application specific events. Some IBC relayers depend on the consensus_height 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 ConsensusStates into the application state tree with a single UpdateClient message. This flexibility is provided in ibc-go by the usage of the Protobuf Any field contained within the UpdateClient 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:

message BatchedHeaders {
repeated Header headers = 1;

To complement this flexibility, the UpdateClient handler will now support the submission of client misbehaviour by consolidating the Header and Misbehaviour interfaces into a single ClientMessage interface type:

// 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 {

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.
  2. Emitting a single consensus_height event attribute is not sufficient in the case of a batched client update containing multiple Headers.


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.
// 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
  1. 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.

  2. 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.



  • 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.


  • Consumers of IBC core UpdateClient events are forced to make future code changes.