Skip to content

Commit

Permalink
Copy over verify_header method
Browse files Browse the repository at this point in the history
  • Loading branch information
soareschen committed Oct 25, 2023
1 parent 22d693e commit 6f59bfd
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 1 deletion.
6 changes: 6 additions & 0 deletions crates/ibc-cosmos-components/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ all-features = true

[dependencies]
cgp-core = { version = "0.1.0" }
ibc = { path = "../ibc" }

[dependencies.tendermint-light-client-verifier]
version = "0.34"
default-features = false
features = ["rust-crypto"]
1 change: 1 addition & 0 deletions crates/ibc-cosmos-components/src/client/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod verify;
118 changes: 118 additions & 0 deletions crates/ibc-cosmos-components/src/client/verify.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use alloc::format;

use ibc::clients::ics07_tendermint::consensus_state::ConsensusState as TmConsensusState;
use ibc::clients::ics07_tendermint::error::{Error, IntoResult};
use ibc::clients::ics07_tendermint::header::Header as TmHeader;
use ibc::clients::ics07_tendermint::ValidationContext as TmValidationContext;
use ibc::core::ics02_client::error::ClientError;
use ibc::core::ics24_host::identifier::{ChainId, ClientId};
use ibc::core::ics24_host::path::ClientConsensusStatePath;
use ibc::prelude::ToString;
use tendermint_light_client_verifier::options::Options;
use tendermint_light_client_verifier::types::{TrustedBlockState, UntrustedBlockState};
use tendermint_light_client_verifier::{ProdVerifier, Verifier};

pub trait HasClientStateMethods {
fn chain_id(&self) -> &ChainId;

fn light_client_options(&self) -> Options;

fn verifier(&self) -> &ProdVerifier;
}

pub fn verify_header<ClientValidationContext, ClientState>(
client_state: &ClientState,
ctx: &ClientValidationContext,
client_id: &ClientId,
header: TmHeader,
) -> Result<(), ClientError>
where
ClientState: HasClientStateMethods,
ClientValidationContext: TmValidationContext,
{
// Checks that the header fields are valid.
header.validate_basic()?;

// The tendermint-light-client crate though works on heights that are assumed
// to have the same revision number. We ensure this here.
header.verify_chain_id_version_matches_height(client_state.chain_id())?;

// Delegate to tendermint-light-client, which contains the required checks
// of the new header against the trusted consensus state.
{
let trusted_state = {
let trusted_client_cons_state_path =
ClientConsensusStatePath::new(client_id, &header.trusted_height);
let trusted_consensus_state: TmConsensusState = ctx
.consensus_state(&trusted_client_cons_state_path)?
.try_into()
.map_err(|err| ClientError::Other {
description: err.to_string(),
})?;

check_header_trusted_next_validator_set(&header, &trusted_consensus_state)?;

TrustedBlockState {
chain_id: &client_state
.chain_id()
.to_string()
.try_into()
.map_err(|e| ClientError::Other {
description: format!("failed to parse chain id: {}", e),
})?,
header_time: trusted_consensus_state.timestamp,
height: header
.trusted_height
.revision_height()
.try_into()
.map_err(|_| ClientError::ClientSpecific {
description: Error::InvalidHeaderHeight {
height: header.trusted_height.revision_height(),
}
.to_string(),
})?,
next_validators: &header.trusted_next_validator_set,
next_validators_hash: trusted_consensus_state.next_validators_hash,
}
};

let untrusted_state = UntrustedBlockState {
signed_header: &header.signed_header,
validators: &header.validator_set,
// NB: This will skip the
// VerificationPredicates::next_validators_match check for the
// untrusted state.
next_validators: None,
};

let options = client_state.light_client_options();
let now =
ctx.host_timestamp()?
.into_tm_time()
.ok_or_else(|| ClientError::ClientSpecific {
description: "host timestamp is not a valid TM timestamp".to_string(),
})?;

// main header verification, delegated to the tendermint-light-client crate.
client_state
.verifier()
.verify_update_header(untrusted_state, trusted_state, &options, now)
.into_result()?;
}

Ok(())
}

fn check_header_trusted_next_validator_set(
header: &TmHeader,
trusted_consensus_state: &TmConsensusState,
) -> Result<(), ClientError> {
if header.trusted_next_validator_set.hash() == trusted_consensus_state.next_validators_hash {
Ok(())
} else {
Err(ClientError::HeaderVerificationFailure {
reason: "header trusted next validator set hash does not match hash stored on chain"
.to_string(),
})
}
}
4 changes: 4 additions & 0 deletions crates/ibc-cosmos-components/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
#![no_std]

extern crate alloc;

pub mod client;
2 changes: 1 addition & 1 deletion crates/ibc/src/clients/ics07_tendermint/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ impl From<IdentifierError> for Error {
}
}

pub(crate) trait IntoResult<T, E> {
pub trait IntoResult<T, E> {
fn into_result(self) -> Result<T, E>;
}

Expand Down

0 comments on commit 6f59bfd

Please sign in to comment.