Skip to content
This repository has been archived by the owner on Jun 24, 2024. It is now read-only.

Commit

Permalink
feat: implement check_misbehaviour method for DA(Celestia) part (#118)
Browse files Browse the repository at this point in the history
* feat: implement check_misbehaviour

* chore: update basecoin rev

* nit: edit TODO text
  • Loading branch information
Farhad-Shabani authored Apr 3, 2024
1 parent 05c8ebe commit 67633a6
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 39 deletions.
42 changes: 21 additions & 21 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

71 changes: 71 additions & 0 deletions clients/sov-celestia/src/client_state/update_client.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use ibc_client_tendermint::context::TmVerifier;
use ibc_client_tendermint::types::Header as TmHeader;
use ibc_core::client::types::error::ClientError;
use ibc_core::client::types::Height;
use ibc_core::host::types::identifiers::{ChainId, ClientId};
use ibc_core::host::types::path::ClientConsensusStatePath;
use sov_celestia_client_types::client_message::SovTmHeader;
use sov_celestia_client_types::consensus_state::SovTmConsensusState;
use sov_celestia_client_types::error::IntoResult;
use tendermint_light_client_verifier::options::Options;
use tendermint_light_client_verifier::types::{TrustedBlockState, UntrustedBlockState};
Expand Down Expand Up @@ -123,3 +125,72 @@ where

Ok(())
}

/// Checks for DA misbehaviour upon receiving a new consensus state as part of a
/// client update.
pub fn check_da_misbehaviour_on_update<V>(
ctx: &V,
header: SovTmHeader,
client_id: &ClientId,
client_latest_height: &Height,
) -> Result<bool, ClientError>
where
V: SovValidationContext,
V::ConsensusStateRef: ConsensusStateConverter,
{
let maybe_existing_consensus_state = {
let path_at_header_height = ClientConsensusStatePath::new(
client_id.clone(),
header.height().revision_number(),
header.height().revision_height(),
);

ctx.consensus_state(&path_at_header_height).ok()
};

if let Some(existing_consensus_state) = maybe_existing_consensus_state {
let existing_consensus_state = existing_consensus_state.try_into()?;

let header_consensus_state = SovTmConsensusState::from(header);

// There is evidence of misbehaviour if the stored consensus state
// is different from the new one we received.
Ok(existing_consensus_state != header_consensus_state)
} else {
// If no header was previously installed, we ensure the monotonicity of timestamps.

// 1. for all headers, the new header needs to have a larger timestamp than
// the “previous header”
{
let maybe_prev_cs = ctx.prev_consensus_state(client_id, &header.height())?;

if let Some(prev_cs) = maybe_prev_cs {
// New header timestamp cannot occur *before* the
// previous consensus state's height
let prev_cs = prev_cs.try_into()?;

if header.da_header.signed_header.header().time <= prev_cs.timestamp() {
return Ok(true);
}
}
}

// 2. if a header comes in and is not the “last” header, then we also ensure
// that its timestamp is less than the “next header”
if &header.height() < client_latest_height {
let maybe_next_cs = ctx.next_consensus_state(client_id, &header.height())?;

if let Some(next_cs) = maybe_next_cs {
// New (untrusted) header timestamp cannot occur *after* next
// consensus state's height
let next_cs = next_cs.try_into()?;

if header.da_header.signed_header.header().time >= next_cs.timestamp() {
return Ok(true);
}
}
}

Ok(false)
}
}
45 changes: 40 additions & 5 deletions clients/sov-celestia/src/client_state/validation.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use ibc_client_tendermint::client_state::check_for_misbehaviour_on_misbehavior;
use ibc_client_tendermint::context::{DefaultVerifier, TmVerifier};
use ibc_core::client::context::client_state::ClientStateValidation;
use ibc_core::client::types::error::ClientError;
Expand All @@ -13,7 +14,7 @@ use sov_celestia_client_types::client_message::{
use sov_celestia_client_types::client_state::SovTmClientState;

use super::ClientState;
use crate::client_state::{verify_header, verify_misbehaviour};
use crate::client_state::{check_da_misbehaviour_on_update, verify_header, verify_misbehaviour};
use crate::context::{ConsensusStateConverter, ValidationContext as SovValidationContext};

impl<V> ClientStateValidation<V> for ClientState
Expand All @@ -38,11 +39,11 @@ where

fn check_for_misbehaviour(
&self,
_ctx: &V,
_client_id: &ClientId,
_client_message: Any,
ctx: &V,
client_id: &ClientId,
client_message: Any,
) -> Result<bool, ClientError> {
Ok(false)
check_for_misbehaviour(self.inner(), ctx, client_id, client_message)
}

fn status(&self, ctx: &V, client_id: &ClientId) -> Result<Status, ClientError> {
Expand Down Expand Up @@ -90,6 +91,40 @@ where
}
}

/// Check for misbehaviour on the client state as part of the client state
/// validation process.
pub fn check_for_misbehaviour<V>(
client_state: &SovTmClientState,
ctx: &V,
client_id: &ClientId,
client_message: Any,
) -> Result<bool, ClientError>
where
V: SovValidationContext,
V::ConsensusStateRef: ConsensusStateConverter,
{
match client_message.type_url.as_str() {
SOV_TENDERMINT_HEADER_TYPE_URL => {
let header = SovTmHeader::try_from(client_message)?;
check_da_misbehaviour_on_update(ctx, header, client_id, &client_state.latest_height)

// TODO: Determine if we need any sort of misbehaviour check for the
// rollup (aggregated proof) part.
}
SOV_TENDERMINT_MISBEHAVIOUR_TYPE_URL => {
let misbehaviour = SovTmMisbehaviour::try_from(client_message)?;
check_for_misbehaviour_on_misbehavior(
&misbehaviour.header1().da_header,
&misbehaviour.header2().da_header,
)

// TODO: Determine if we need any sort of misbehaviour check for the
// rollup (aggregated proof) part.
}
_ => Err(ClientError::InvalidUpdateClientMessage),
}
}

/// Checks the status (whether it is active, frozen, or expired) of the
/// Sovereign client state.
pub fn status<V>(
Expand Down
10 changes: 2 additions & 8 deletions clients/sov-celestia/types/src/consensus_state/definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,7 @@ impl From<tendermint::block::Header> for SovTmConsensusState {
fn from(header: tendermint::block::Header) -> Self {
Self {
root: CommitmentRoot::from_bytes(header.app_hash.as_ref()),
da_params: TmConsensusParams {
timestamp: header.time,
next_validators_hash: header.next_validators_hash,
},
da_params: TmConsensusParams::new(header.time, header.next_validators_hash),
}
}
}
Expand All @@ -128,10 +125,7 @@ impl From<SovTmHeader> for SovTmConsensusState {
.final_state_root
.as_ref(),
),
da_params: TmConsensusParams {
timestamp: tm_header.time,
next_validators_hash: tm_header.next_validators_hash,
},
da_params: TmConsensusParams::new(tm_header.time, tm_header.next_validators_hash),
}
}
}
10 changes: 5 additions & 5 deletions mocks/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ tracing = "0.1.36"
typed-builder = "0.18.0"

# internal dependencies
sov-ibc = { git = "https://github.com/informalsystems/sovereign-ibc.git", rev = "fbaea802" }
sov-ibc-transfer = { git = "https://github.com/informalsystems/sovereign-ibc.git", rev = "fbaea802" }
sov-consensus-state-tracker = { git = "https://github.com/informalsystems/sovereign-ibc.git", rev = "fbaea802" }
sov-celestia-client = { git = "https://github.com/informalsystems/sovereign-ibc.git", rev = "fbaea802", features = ["test-util"] }
sov-ibc = { git = "https://github.com/informalsystems/sovereign-ibc.git", rev = "79c90604" }
sov-ibc-transfer = { git = "https://github.com/informalsystems/sovereign-ibc.git", rev = "79c90604" }
sov-consensus-state-tracker = { git = "https://github.com/informalsystems/sovereign-ibc.git", rev = "79c90604" }
sov-celestia-client = { git = "https://github.com/informalsystems/sovereign-ibc.git", rev = "79c90604", features = ["test-util"] }

# ibc dependencies
ibc-core = { workspace = true }
Expand All @@ -46,7 +46,7 @@ ibc-query = { workspace = true }
ibc-testkit = { workspace = true }

# cosmos dependencies
basecoin = { git = "https://github.com/informalsystems/basecoin-rs.git", rev = "c186aa1" }
basecoin = { git = "https://github.com/informalsystems/basecoin-rs.git", rev = "264f677" }
tendermint = { workspace = true }
tendermint-testgen = { workspace = true }

Expand Down

0 comments on commit 67633a6

Please sign in to comment.