pub fn handle_misbehaviour(
        &self,
        mut update: Option<UpdateClient>,
    ) -> Result<Option<AnyMisbehaviour>, ForeignClientError> {
        thread::sleep(Duration::from_millis(100));

        // Get the latest client state on destination.
        let client_state = self
            .dst_chain()
            .query_client_state(&self.id, Height::zero())
            .map_err(|e| {
                ForeignClientError::Misbehaviour(format!(
                    "failed querying client state on dst chain {} with error: {}",
                    self.id, e
                ))
            })?;

        // Get the list of consensus state heights in descending order.
        // Note: If chain does not prune consensus states then the last consensus state is
        // the one installed by the `CreateClient` which does not include a header.
        // For chains that do support pruning, it is possible that the last consensus state
        // was installed by an `UpdateClient` and an event and header will be found.
        let consensus_state_heights = self.consensus_state_heights()?;
        info!(
            "checking misbehaviour for consensus state heights {:?}",
            consensus_state_heights
        );

        for target_height in consensus_state_heights {
            // Start with specified update event or the one for latest consensus height
            let update_event = if let Some(ref event) = update {
                // we are here only on the first iteration when called with `Some` update event
                event.clone()
            } else if let Some(event) = self.update_client_event(target_height)? {
                // we are here either on the first iteration with `None` initial update event or
                // subsequent iterations
                event
            } else {
                // we are here if the consensus state was installed on-chain when client was
                // created, therefore there will be no update client event
                break;
            };

            // Skip over heights higher than the update event one.
            // This can happen if a client update happened with a lower height than latest.
            if target_height > update_event.consensus_height() {
                continue;
            }

            // Ensure consensus height of the event is same as target height. This should be the
            // case as we either
            // - got the `update_event` from the `target_height` above, or
            // - an `update_event` was specified and we should eventually find a consensus state
            //   at that height
            // We break here in case we got a bogus event.
            if target_height < update_event.consensus_height() {
                break;
            }

            // Check for misbehaviour according to the specific source chain type.
            // In case of Tendermint client, this will also check the BFT time violation if
            // a header for the event height cannot be retrieved from the witness.
            let misbehavior = self
                .src_chain
                .check_misbehaviour(update_event, client_state.clone())
                .map_err(|e| {
                    ForeignClientError::Misbehaviour(format!("failed to build misbehaviour {}", e))
                })?;

            if misbehavior.is_some() {
                // TODO - add updateClient messages if light blocks are returned from
                //  `src_chain.check_misbehaviour` call above i.e. supporting headers are required
                return Ok(misbehavior);
            }

            // Clear the update
            update = None;
        }

        Ok(None)
    }
/// Checks for misbehaviour and submits evidence.
/// The check starts with and `update_event` emitted by chain B (`dst_chain`) for a client update
/// with a header from chain A (`src_chain`). The algorithm goes backwards through the headers
/// until it gets to the first misbehaviour.
///
/// The following cases are covered:
/// 1 - fork:
/// Assumes at least one consensus state before the fork point exists.
/// Let existing consensus states on chain B be: [Sn,.., Sf, Sf-1, S0] with `Sf-1` being
/// the most recent state before fork.
/// Chain A is queried for a header `Hf'` at `Sf.height` and if it is different than the `Hf`
/// in the event for the client update (the one that has generated `Sf` on chain), then the two
/// headers are included in the evidence and submitted.
/// Note that in this case the headers are different but have the same height.
///
/// 2 - BFT time violation for unavailable header (a.k.a. Future Lunatic Attack or FLA):
/// Some header with a height that is higher than the latest
/// height on A has been accepted and a consensus state was created on B. Note that this implies
/// that the timestamp of this header must be within the `clock_drift` of the client.
/// Assume the client on B has been updated with `h2`(not present on/ produced by chain A)
/// and it has a timestamp of `t2` that is at most `clock_drift` in the future.
/// Then the latest header from A is fetched, let it be `h1`, with a timestamp of `t1`.
/// If `t1 >= t2` then evidence of misbehavior is submitted to A.
///
/// 3 - BFT time violation for existing headers (TODO):
/// Ensure that consensus state times are monotonically increasing with height.
///
/// Other notes:
/// - the algorithm builds misbehavior at each consensus height, starting with the
/// highest height assuming the previous one is trusted. It submits the first constructed
/// evidence (the one with the highest height)
/// - a lot of the logic here is derived from the behavior of the only implemented client
/// (ics07-tendermint) and might not be general enough.
///
Checks for misbehaviour and submits evidence.

The following cases are covered:
1 - fork:
Assumes at least one consensus state before the fork point exists.
Let existing consensus states on chain B be: [Sn,.., Sf, Sf-1, S0] with `Sf-1` being
the most recent state before fork.

BFT time violation for unavailable header (a.k.a. Future Lunatic Attack or FLA):
Some header with a height that is higher than the latest
height on A has been accepted and a consensus state was created on B. Note that this implies
that the timestamp of this header must be within the `clock_drift` of the client.

BFT time violation for existing headers (TODO):
Ensure that consensus state times are monotonically increasing with height.

Other notes:
the algorithm builds misbehavior at each consensus height, starting with the
highest height assuming the previous one is trusted. It submits the first constructed
evidence (the one with the highest height)
a lot of the logic here is derived from the behavior of the only implemented client
(ics07-tendermint) and might not be general enough.
Checks for misbehaviour and submits evidence . The following cases are covered : 1 - fork : Assumes at least one consensus state before the fork point exists . Let existing consensus states on chain B be : [ Sn .. Sf Sf - 1 S0 ] with ` Sf - 1 ` being the most recent state before fork . BFT time violation for unavailable header ( a . k . a . Future Lunatic Attack or FLA ) : Some header with a height that is higher than the latest height on A has been accepted and a consensus state was created on B . Note that this implies that the timestamp of this header must be within the ` clock_drift ` of the client . BFT time violation for existing headers ( TODO ) : Ensure that consensus state times are monotonically increasing with height . Other notes : the algorithm builds misbehavior at each consensus height starting with the highest height assuming the previous one is trusted . It submits the first constructed evidence ( the one with the highest height ) a lot of the logic here is derived from the behavior of the only implemented client ( ics07 - tendermint ) and might not be general enough .
pub fn handle_misbehaviour(
        &self,
        mut update: Option<UpdateClient>,
    ) -> Result<Option<AnyMisbehaviour>, ForeignClientError> {
        thread::sleep(Duration::from_millis(100));
        // Get the latest client state on destination.
        let client_state = self
            .dst_chain()
            .query_client_state(&self.id, Height::zero())
            .map_err(|e| {
                ForeignClientError::Misbehaviour(format!(
                    "failed querying client state on dst chain {} with error: {}",
                    self.id, e
                ))
            })?;
        // Get the list of consensus state heights in descending order.
        // Note: If chain does not prune consensus states then the last consensus state is
        // the one installed by the `CreateClient` which does not include a header.
        // For chains that do support pruning, it is possible that the last consensus state
        // was installed by an `UpdateClient` and an event and header will be found.
        let consensus_state_heights = self.consensus_state_heights()?;
        info!(
            "checking misbehaviour for consensus state heights {:?}",
            consensus_state_heights
        );
        for target_height in consensus_state_heights {
            // Start with specified update event or the one for latest consensus height
            let update_event = if let Some(ref event) = update {
                // we are here only on the first iteration when called with `Some` update event
                event.clone()
            } else if let Some(event) = self.update_client_event(target_height)? {
                // we are here either on the first iteration with `None` initial update event or
                // subsequent iterations
                event
            } else {
                // we are here if the consensus state was installed on-chain when client was
                // created, therefore there will be no update client event
                break;
            };
            // Skip over heights higher than the update event one.
            // This can happen if a client update happened with a lower height than latest.
            if target_height > update_event.consensus_height() {
                continue;
            }
            // Ensure consensus height of the event is same as target height. This should be the
            // case as we either
            // - got the `update_event` from the `target_height` above, or
            // - an `update_event` was specified and we should eventually find a consensus state
            //   at that height
            // We break here in case we got a bogus event.
            if target_height < update_event.consensus_height() {
                break;
            }
            // Check for misbehaviour according to the specific source chain type.
            // In case of Tendermint client, this will also check the BFT time violation if
            // a header for the event height cannot be retrieved from the witness.
            let misbehavior = self
                .src_chain
                .check_misbehaviour(update_event, client_state.clone())
                .map_err(|e| {
                    ForeignClientError::Misbehaviour(format!("failed to build misbehaviour {}", e))
                })?;
            if misbehavior.is_some() {
                // TODO - add updateClient messages if light blocks are returned from
                //  `src_chain.check_misbehaviour` call above i.e. supporting headers are required
                return Ok(misbehavior);
            }
            // Clear the update
            update = None;
        }
        Ok(None)
    }
pub fn handle_misbehaviour ( & self , mut update : Option < UpdateClient > , ) -> Result < Option < AnyMisbehaviour > , ForeignClientError > { thread :: sleep ( Duration :: from_millis ( 100 ) ) ; // Get the latest client state on destination. let client_state = self . dst_chain ( ) . query_client_state ( & self . id , Height :: zero ( ) ) . map_err ( | e | { ForeignClientError :: Misbehaviour ( format ! ( " " self id e ) ) } ) ? ; // Get the list of consensus state heights in descending order. // Note: If chain does not prune consensus states then the last consensus state is // the one installed by the `CreateClient` which does not include a header. // For chains that do support pruning, it is possible that the last consensus state // was installed by an `UpdateClient` and an event and header will be found. let consensus_state_heights = self . consensus_state_heights ( ) ? ; info ! ( " " consensus_state_heights ) ; for target_height in consensus_state_heights { // Start with specified update event or the one for latest consensus height let update_event = if let Some ( ref event ) = update { // we are here only on the first iteration when called with `Some` update event event . clone ( ) } else if let Some ( event ) = self . update_client_event ( target_height ) ? { // we are here either on the first iteration with `None` initial update event or // subsequent iterations event } else { // we are here if the consensus state was installed on-chain when client was // created, therefore there will be no update client event break ; } ; // Skip over heights higher than the update event one. // This can happen if a client update happened with a lower height than latest. if target_height > update_event . consensus_height ( ) { continue ; } // Ensure consensus height of the event is same as target height. This should be the // case as we either // - got the `update_event` from the `target_height` above, or // - an `update_event` was specified and we should eventually find a consensus state //   at that height // We break here in case we got a bogus event. if target_height < update_event . consensus_height ( ) { break ; } // Check for misbehaviour according to the specific source chain type. // In case of Tendermint client, this will also check the BFT time violation if // a header for the event height cannot be retrieved from the witness. let misbehavior = self . src_chain . check_misbehaviour ( update_event , client_state . clone ( ) ) . map_err ( | e | { ForeignClientError :: Misbehaviour ( format ! ( " " e ) ) } ) ? ; if misbehavior . is_some ( ) { // TODO - add updateClient messages if light blocks are returned from //  `src_chain.check_misbehaviour` call above i.e. supporting headers are required return Ok ( misbehavior ) ; } // Clear the update update = None ; } Ok ( None ) }
Checks for misbehaviour and submits evidence.
Checks for misbehaviour and submits evidence .
&self
update
Option<UpdateClient>
&self
update
Option<UpdateClient>