Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

imp: make it easier to use custom verifiers for Tendermint clients #1168

Merged
merged 9 commits into from
Apr 17, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- [ibc-client-tendermint] Simplify custom verifiers usage for Tendermint
clients by directly binding with `tendermint_light_client_verifier::Verifier`
and removing the unused `TmVerifier` trait.
([\#1168](https://github.com/cosmos/ibc-rs/pull/1168))
6 changes: 2 additions & 4 deletions ibc-clients/ics07-tendermint/src/client_state/misbehaviour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use tendermint_light_client_verifier::options::Options;
use tendermint_light_client_verifier::Verifier;

use crate::types::Header;
use crate::verifier::TmVerifier;

/// Determines whether or not two conflicting headers at the same height would
/// have convinced the light client.
Expand All @@ -25,7 +24,7 @@ pub fn verify_misbehaviour<V, H>(
client_id: &ClientId,
chain_id: &ChainId,
options: &Options,
verifier: &impl TmVerifier,
verifier: &impl Verifier,
) -> Result<(), ClientError>
where
V: ExtClientValidationContext,
Expand Down Expand Up @@ -87,7 +86,7 @@ pub fn verify_misbehaviour_header<H>(
trusted_timestamp: Time,
trusted_next_validator_hash: Hash,
current_timestamp: Timestamp,
verifier: &impl TmVerifier,
verifier: &impl Verifier,
) -> Result<(), ClientError>
where
H: MerkleHash + Sha256 + Default,
Expand Down Expand Up @@ -134,7 +133,6 @@ where
})?;

verifier
.verifier()
.verify_misbehaviour_header(untrusted_state, trusted_state, options, current_timestamp)
.into_result()?;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@ use tendermint_light_client_verifier::options::Options;
use tendermint_light_client_verifier::types::{TrustedBlockState, UntrustedBlockState};
use tendermint_light_client_verifier::Verifier;

use crate::verifier::TmVerifier;

pub fn verify_header<V, H>(
ctx: &V,
header: &TmHeader,
client_id: &ClientId,
chain_id: &ChainId,
options: &Options,
verifier: &impl TmVerifier,
verifier: &impl Verifier,
) -> Result<(), ClientError>
where
V: ExtClientValidationContext,
Expand Down Expand Up @@ -92,7 +90,6 @@ where

// main header verification, delegated to the tendermint-light-client crate.
verifier
.verifier()
.verify_update_header(untrusted_state, trusted_state, options, now)
.into_result()?;
}
Expand Down
33 changes: 24 additions & 9 deletions ibc-clients/ics07-tendermint/src/client_state/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,35 @@ use ibc_primitives::proto::Any;
use tendermint::crypto::default::Sha256;
use tendermint::crypto::Sha256 as Sha256Trait;
use tendermint::merkle::MerkleHash;
use tendermint_light_client_verifier::{ProdVerifier, Verifier};

use super::{check_for_misbehaviour_on_misbehavior, check_for_misbehaviour_on_update, ClientState};
use crate::client_state::{verify_header, verify_misbehaviour};
use crate::verifier::{DefaultVerifier, TmVerifier};

impl<V> ClientStateValidation<V> for ClientState
where
V: ExtClientValidationContext,
V::ConsensusStateRef: Convertible<ConsensusStateType, ClientError>,
{
/// The default verification logic exposed by ibc-rs simply delegates to a
/// standalone `verify_client_message` function. This is to make it as simple
/// as possible for those who merely need the `DefaultVerifier` behaviour, as
/// well as those who require custom verification logic.
/// standalone `verify_client_message` function. This is to make it as
/// simple as possible for those who merely need the default
/// [`ProdVerifier`] behaviour, as well as those who require custom
/// verification logic.
///
/// In a situation where the Tendermint [`ProdVerifier`] doesn't provide the
/// desired outcome, users should define a custom verifier struct and then
/// implement the [`Verifier`] trait for it.
///
/// In order to wire up the custom verifier, create a newtype `ClientState`
/// wrapper similar to [`ClientState`] and implement all client state traits
/// for it. For method implementation, the simplest way is to import and
/// call their analogous standalone versions under the
/// [`crate::client_state`] module, unless bespoke logic is desired for any
/// of those functions. Then, when it comes to implementing the
/// `verify_client_message` method, use the [`verify_client_message`]
/// function and pass your custom verifier object as the `verifier`
/// parameter.
fn verify_client_message(
&self,
ctx: &V,
Expand All @@ -38,7 +53,7 @@ where
ctx,
client_id,
client_message,
&DefaultVerifier,
&ProdVerifier::default(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I am a bit confused about how I would reuse this interface for a custom verifier. After I implement Verifier trait for my custom logic, how do I pass it here instead of ProdVerifier::default()?

Copy link
Member Author

Choose a reason for hiding this comment

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

See if this works. b8244a5

Copy link
Collaborator

@rnbguy rnbguy Apr 17, 2024

Choose a reason for hiding this comment

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

Am I correct to conclude that someone has to create a wrapper struct:

struct CustomClientState(ClientState);

and delegate all calls except this one? If I am correct, can we add a generic to the current ClientState?

struct ClientState<V: Verifier + Default> { ... }

type DefaultClientState = ClientState<ProdVerifier>;
type SovClientState = ClientState<SovVerifier>;

I am just confirming my understanding. If you already plan for this in future PRs, go ahead with this current merge.

Copy link
Member Author

Choose a reason for hiding this comment

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

Am I correct to conclude that someone has to create a wrapper struct

That's right

Can we add a generic to the current ClientState

Our plan was to do this, but adding a generic introduces complications that eventually lead to refactoring some of the APIs as well. Aside from that, we didn't want to introduce complexity to normal users.
We can consider the generic or even writing macros in the future if there be a serious need.

)
}

Expand All @@ -63,9 +78,9 @@ where
/// Verify the client message as part of the client state validation process.
///
/// Note that this function is typically implemented as part of the
/// [`ClientStateValidation`] trait, but has been made a standalone function
/// in order to make the ClientState APIs more flexible. It mostly adheres to
/// the same signature as the `ClientStateValidation::verify_client_message`
/// [`ClientStateValidation`] trait, but has been made a standalone function in
/// order to make the ClientState APIs more flexible. It mostly adheres to the
/// same signature as the `ClientStateValidation::verify_client_message`
/// function, except for an additional `verifier` parameter that allows users
/// who require custom verification logic to easily pass in their own verifier
/// implementation.
Expand All @@ -74,7 +89,7 @@ pub fn verify_client_message<V, H>(
ctx: &V,
client_id: &ClientId,
client_message: Any,
verifier: &impl TmVerifier,
verifier: &impl Verifier,
) -> Result<(), ClientError>
where
V: ExtClientValidationContext,
Expand Down
8 changes: 4 additions & 4 deletions ibc-clients/ics07-tendermint/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! ICS 07: Tendermint light client implementation along with re-exporting data
//! structures and implementations of IBC core client module.
//! ICS 07: Tendermint light client implementation along with re-exporting the
//! necessary types from `ibc-client-tendermint-types` crate.
#![no_std]
#![forbid(unsafe_code)]
#![cfg_attr(not(test), deny(clippy::unwrap_used))]
Expand All @@ -18,11 +18,11 @@ extern crate std;

pub mod client_state;
pub mod consensus_state;
pub mod verifier;

pub const TENDERMINT_CLIENT_TYPE: &str = "07-tendermint";

/// Re-export of Tendermint light client data structures from `ibc-client-tendermint` crate.
/// Re-exports Tendermint light client data structures from the
/// `ibc-client-tendermint-type` crate.
pub mod types {
#[doc(inline)]
pub use ibc_client_tendermint_types::*;
Expand Down
37 changes: 0 additions & 37 deletions ibc-clients/ics07-tendermint/src/verifier.rs

This file was deleted.

Loading