fn check_misbehaviour(
        &mut self,
        update: UpdateClient,
        client_state: &AnyClientState,
    ) -> Result<Option<AnyMisbehaviour>, Error> {
        crate::time!("light client check_misbehaviour");

        let update_header = update.header.clone().ok_or_else(|| {
            Kind::Misbehaviour(format!(
                "missing header in update client event {}",
                self.chain_id
            ))
        })?;

        let tm_ibc_client_header =
            downcast!(update_header => AnyHeader::Tendermint).ok_or_else(|| {
                Kind::Misbehaviour(format!(
                    "header type incompatible for chain {}",
                    self.chain_id
                ))
            })?;

        let latest_chain_block = self.fetch_light_block(AtHeight::Highest)?;
        let latest_chain_height =
            ibc::Height::new(self.chain_id.version(), latest_chain_block.height().into());

        // set the target height to the minimum between the update height and latest chain height
        let target_height = std::cmp::min(update.consensus_height(), latest_chain_height);
        let trusted_height = tm_ibc_client_header.trusted_height;

        // TODO - check that a consensus state at trusted_height still exists on-chain,
        // currently we don't have access to Cosmos chain query from here

        if trusted_height >= latest_chain_height {
            // Can happen with multiple FLA attacks, we return no evidence and hope to catch this in
            // the next iteration. e.g:
            // existing consensus states: 1000, 900, 300, 200 (only known by the caller)
            // latest_chain_height = 300
            // target_height = 1000
            // trusted_height = 900
            return Ok(None);
        }

        let tm_witness_node_header = {
            let trusted_light_block = self.fetch(trusted_height.increment())?;
            let target_light_block = self.verify(trusted_height, target_height, &client_state)?;
            TmHeader {
                trusted_height,
                signed_header: target_light_block.signed_header,
                validator_set: target_light_block.validators,
                trusted_validator_set: trusted_light_block.validators,
            }
        };

        let misbehaviour = if !tm_witness_node_header.compatible_with(&tm_ibc_client_header) {
            Some(
                AnyMisbehaviour::Tendermint(TmMisbehaviour {
                    client_id: update.client_id().clone(),
                    header1: tm_ibc_client_header,
                    header2: tm_witness_node_header,
                })
                .wrap_any(),
            )
        } else {
            None
        };

        Ok(misbehaviour)
    }
/// Given a client update event that includes the header used in a client update.
/// it looks for misbehaviour by fetching a header at same or latest height.
/// TODO - return also intermediate headers.
Given a client update event that includes the header used in a client update.
it looks for misbehaviour by fetching a header at same or latest height.
TODO - return also intermediate headers.
Given a client update event that includes the header used in a client update . it looks for misbehaviour by fetching a header at same or latest height . TODO - return also intermediate headers .
fn check_misbehaviour(
        &mut self,
        update: UpdateClient,
        client_state: &AnyClientState,
    ) -> Result<Option<AnyMisbehaviour>, Error> {
        crate::time!("light client check_misbehaviour");
        let update_header = update.header.clone().ok_or_else(|| {
            Kind::Misbehaviour(format!(
                "missing header in update client event {}",
                self.chain_id
            ))
        })?;
        let tm_ibc_client_header =
            downcast!(update_header => AnyHeader::Tendermint).ok_or_else(|| {
                Kind::Misbehaviour(format!(
                    "header type incompatible for chain {}",
                    self.chain_id
                ))
            })?;
        let latest_chain_block = self.fetch_light_block(AtHeight::Highest)?;
        let latest_chain_height =
            ibc::Height::new(self.chain_id.version(), latest_chain_block.height().into());
        // set the target height to the minimum between the update height and latest chain height
        let target_height = std::cmp::min(update.consensus_height(), latest_chain_height);
        let trusted_height = tm_ibc_client_header.trusted_height;
        // TODO - check that a consensus state at trusted_height still exists on-chain,
        // currently we don't have access to Cosmos chain query from here
        if trusted_height >= latest_chain_height {
            // Can happen with multiple FLA attacks, we return no evidence and hope to catch this in
            // the next iteration. e.g:
            // existing consensus states: 1000, 900, 300, 200 (only known by the caller)
            // latest_chain_height = 300
            // target_height = 1000
            // trusted_height = 900
            return Ok(None);
        }
        let tm_witness_node_header = {
            let trusted_light_block = self.fetch(trusted_height.increment())?;
            let target_light_block = self.verify(trusted_height, target_height, &client_state)?;
            TmHeader {
                trusted_height,
                signed_header: target_light_block.signed_header,
                validator_set: target_light_block.validators,
                trusted_validator_set: trusted_light_block.validators,
            }
        };
        let misbehaviour = if !tm_witness_node_header.compatible_with(&tm_ibc_client_header) {
            Some(
                AnyMisbehaviour::Tendermint(TmMisbehaviour {
                    client_id: update.client_id().clone(),
                    header1: tm_ibc_client_header,
                    header2: tm_witness_node_header,
                })
                .wrap_any(),
            )
        } else {
            None
        };
        Ok(misbehaviour)
    }
fn check_misbehaviour ( & mut self , update : UpdateClient , client_state : & AnyClientState , ) -> Result < Option < AnyMisbehaviour > , Error > { crate :: time ! ( " " ) ; let update_header = update . header . clone ( ) . ok_or_else ( | | { Kind :: Misbehaviour ( format ! ( " " self chain_id ) ) } ) ? ; let tm_ibc_client_header = downcast ! ( update_header AnyHeader Tendermint ) . ok_or_else ( | | { Kind :: Misbehaviour ( format ! ( " " self chain_id ) ) } ) ? ; let latest_chain_block = self . fetch_light_block ( AtHeight :: Highest ) ? ; let latest_chain_height = ibc :: Height :: new ( self . chain_id . version ( ) , latest_chain_block . height ( ) . into ( ) ) ; // set the target height to the minimum between the update height and latest chain height let target_height = std :: cmp :: min ( update . consensus_height ( ) , latest_chain_height ) ; let trusted_height = tm_ibc_client_header . trusted_height ; // TODO - check that a consensus state at trusted_height still exists on-chain, // currently we don't have access to Cosmos chain query from here if trusted_height >= latest_chain_height { // Can happen with multiple FLA attacks, we return no evidence and hope to catch this in // the next iteration. e.g: // existing consensus states: 1000, 900, 300, 200 (only known by the caller) // latest_chain_height = 300 // target_height = 1000 // trusted_height = 900 return Ok ( None ) ; } let tm_witness_node_header = { let trusted_light_block = self . fetch ( trusted_height . increment ( ) ) ? ; let target_light_block = self . verify ( trusted_height , target_height , & client_state ) ? ; TmHeader { trusted_height , signed_header : target_light_block . signed_header , validator_set : target_light_block . validators , trusted_validator_set : trusted_light_block . validators , } } ; let misbehaviour = if ! tm_witness_node_header . compatible_with ( & tm_ibc_client_header ) { Some ( AnyMisbehaviour :: Tendermint ( TmMisbehaviour { client_id : update . client_id ( ) . clone ( ) , header1 : tm_ibc_client_header , header2 : tm_witness_node_header , } ) . wrap_any ( ) , ) } else { None } ; Ok ( misbehaviour ) }
Given a client update event that includes the header used in a client update.
Given a client update event that includes the header used in a client update .
&mut self
update
UpdateClient
client_state
&AnyClientState
&mut self
update
UpdateClient
client_state
&AnyClientState