diff --git a/crates/core/component/ibc/src/component/rpc/connection_query.rs b/crates/core/component/ibc/src/component/rpc/connection_query.rs index 64c0d04d95..73fcb76d10 100644 --- a/crates/core/component/ibc/src/component/rpc/connection_query.rs +++ b/crates/core/component/ibc/src/component/rpc/connection_query.rs @@ -1,5 +1,6 @@ use async_trait::async_trait; +use ibc_proto::ibc::core::client; use ibc_proto::ibc::core::client::v1::{Height, IdentifiedClientState}; use ibc_proto::ibc::core::connection::v1::query_server::Query as ConnectionQuery; use ibc_proto::ibc::core::connection::v1::{ @@ -12,7 +13,9 @@ use ibc_proto::ibc::core::connection::v1::{ use ibc_types::core::client::ClientId; use ibc_types::core::connection::{ClientPaths, ConnectionId, IdentifiedConnectionEnd}; -use ibc_types::path::{ClientConnectionPath, ClientStatePath, ConnectionPath}; +use ibc_types::path::{ + ClientConnectionPath, ClientConsensusStatePath, ClientStatePath, ConnectionPath, +}; use ibc_types::DomainType; use prost::Message; use std::str::FromStr; @@ -219,9 +222,53 @@ impl ConnectionQuery for IbcQuery { /// connection. async fn connection_consensus_state( &self, - _request: tonic::Request, + request: tonic::Request, ) -> std::result::Result, tonic::Status> { - Err(tonic::Status::unimplemented("not implemented")) + let snapshot = self.0.latest_snapshot(); + let consensus_state_height = ibc_types::core::client::Height { + revision_number: request.get_ref().revision_number, + revision_height: request.get_ref().revision_height, + }; + let connection_id = &ConnectionId::from_str(&request.get_ref().connection_id) + .map_err(|e| tonic::Status::aborted(format!("invalid connection id: {e}")))?; + + let client_id = snapshot + .get_connection(connection_id) + .await + .map_err(|e| tonic::Status::aborted(format!("couldn't get connection: {e}")))? + .ok_or("unable to get connection") + .map_err(|e| tonic::Status::aborted(format!("couldn't get connection: {e}")))? + .client_id; + + let (consensus_state, proof) = snapshot + .get_with_proof( + IBC_COMMITMENT_PREFIX + .apply_string( + ClientConsensusStatePath::new(&client_id, &consensus_state_height) + .to_string(), + ) + .as_bytes() + .to_vec(), + ) + .await + .map_err(|e| tonic::Status::aborted(format!("couldn't get client state: {e}")))?; + + let consensus_state_any = consensus_state + .map(|cs_bytes| ibc_proto::google::protobuf::Any::decode(cs_bytes.as_ref())) + .transpose() + .map_err(|e| tonic::Status::aborted(format!("couldn't decode client state: {e}")))?; + + Ok(tonic::Response::new( + QueryConnectionConsensusStateResponse { + consensus_state: consensus_state_any, + client_id: client_id.to_string(), + proof: proof.encode_to_vec(), + proof_height: Some(Height { + revision_number: 0, + revision_height: snapshot.version(), + }), + }, + )) } }