use alloc::sync::Arc;
use core::fmt::{self, Debug, Display};
use crossbeam_channel as channel;
use tracing::Span;
use ibc_relayer_types::{
core::{
ics02_client::events::UpdateClient,
ics03_connection::{
connection::{ConnectionEnd, IdentifiedConnectionEnd},
version::Version,
},
ics04_channel::{
channel::{ChannelEnd, IdentifiedChannelEnd},
packet::{PacketMsgType, Sequence},
},
ics23_commitment::{commitment::CommitmentPrefix, merkle::MerkleProof},
ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId},
},
proofs::Proofs,
signer::Signer,
Height,
};
use crate::{
account::Balance,
client_state::{AnyClientState, IdentifiedAnyClientState},
config::ChainConfig,
connection::ConnectionMsgType,
consensus_state::{AnyConsensusState, AnyConsensusStateWithHeight},
denom::DenomTrace,
error::Error,
event::{
monitor::{EventBatch, Result as MonitorResult},
IbcEventWithHeight,
},
keyring::AnySigningKeyPair,
light_client::AnyHeader,
misbehaviour::MisbehaviourEvidence,
};
use super::{
client::ClientSettings,
endpoint::{ChainStatus, HealthCheck},
requests::*,
tracking::TrackedMsgs,
};
mod base;
mod cache;
mod counting;
pub use base::BaseChainHandle;
pub use counting::CountingChainHandle;
pub type CachingChainHandle = cache::CachingChainHandle<BaseChainHandle>;
pub type CountingAndCachingChainHandle =
cache::CachingChainHandle<CountingChainHandle<BaseChainHandle>>;
#[derive(Clone)]
pub struct ChainHandlePair<ChainA: ChainHandle, ChainB: ChainHandle> {
pub a: ChainA,
pub b: ChainB,
}
impl<ChainA: ChainHandle, ChainB: ChainHandle> ChainHandlePair<ChainA, ChainB> {
pub fn swap(self) -> ChainHandlePair<ChainB, ChainA> {
ChainHandlePair {
a: self.b,
b: self.a,
}
}
}
impl<ChainA: ChainHandle, ChainB: ChainHandle> Debug for ChainHandlePair<ChainA, ChainB> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ChainHandlePair")
.field("a", &self.a.id())
.field("b", &self.b.id())
.finish()
}
}
pub type Subscription = channel::Receiver<Arc<MonitorResult<EventBatch>>>;
pub type ReplyTo<T> = channel::Sender<Result<T, Error>>;
pub type Reply<T> = channel::Receiver<Result<T, Error>>;
pub fn reply_channel<T>() -> (ReplyTo<T>, Reply<T>) {
channel::bounded(1)
}
#[derive(Clone, Debug)]
#[allow(clippy::large_enum_variant)]
pub enum ChainRequest {
Shutdown {
reply_to: ReplyTo<()>,
},
HealthCheck {
reply_to: ReplyTo<HealthCheck>,
},
Subscribe {
reply_to: ReplyTo<Subscription>,
},
SendMessagesAndWaitCommit {
tracked_msgs: TrackedMsgs,
reply_to: ReplyTo<Vec<IbcEventWithHeight>>,
},
SendMessagesAndWaitCheckTx {
tracked_msgs: TrackedMsgs,
reply_to: ReplyTo<Vec<tendermint_rpc::endpoint::broadcast::tx_sync::Response>>,
},
Config {
reply_to: ReplyTo<ChainConfig>,
},
Signer {
reply_to: ReplyTo<Signer>,
},
GetKey {
reply_to: ReplyTo<AnySigningKeyPair>,
},
AddKey {
key_name: String,
key: AnySigningKeyPair,
reply_to: ReplyTo<()>,
},
IbcVersion {
reply_to: ReplyTo<Option<semver::Version>>,
},
QueryBalance {
key_name: Option<String>,
denom: Option<String>,
reply_to: ReplyTo<Balance>,
},
QueryAllBalances {
key_name: Option<String>,
reply_to: ReplyTo<Vec<Balance>>,
},
QueryDenomTrace {
hash: String,
reply_to: ReplyTo<DenomTrace>,
},
QueryApplicationStatus {
reply_to: ReplyTo<ChainStatus>,
},
QueryClients {
request: QueryClientStatesRequest,
reply_to: ReplyTo<Vec<IdentifiedAnyClientState>>,
},
BuildHeader {
trusted_height: Height,
target_height: Height,
client_state: AnyClientState,
reply_to: ReplyTo<(AnyHeader, Vec<AnyHeader>)>,
},
BuildClientState {
height: Height,
settings: ClientSettings,
reply_to: ReplyTo<AnyClientState>,
},
BuildConsensusState {
trusted: Height,
target: Height,
client_state: AnyClientState,
reply_to: ReplyTo<AnyConsensusState>,
},
BuildMisbehaviour {
client_state: AnyClientState,
update_event: UpdateClient,
reply_to: ReplyTo<Option<MisbehaviourEvidence>>,
},
BuildConnectionProofsAndClientState {
message_type: ConnectionMsgType,
connection_id: ConnectionId,
client_id: ClientId,
height: Height,
reply_to: ReplyTo<(Option<AnyClientState>, Proofs)>,
},
QueryClientState {
request: QueryClientStateRequest,
include_proof: IncludeProof,
reply_to: ReplyTo<(AnyClientState, Option<MerkleProof>)>,
},
QueryClientConnections {
request: QueryClientConnectionsRequest,
reply_to: ReplyTo<Vec<ConnectionId>>,
},
QueryConsensusState {
request: QueryConsensusStateRequest,
include_proof: IncludeProof,
reply_to: ReplyTo<(AnyConsensusState, Option<MerkleProof>)>,
},
QueryConsensusStates {
request: QueryConsensusStatesRequest,
reply_to: ReplyTo<Vec<AnyConsensusStateWithHeight>>,
},
QueryUpgradedClientState {
request: QueryUpgradedClientStateRequest,
reply_to: ReplyTo<(AnyClientState, MerkleProof)>,
},
QueryUpgradedConsensusState {
request: QueryUpgradedConsensusStateRequest,
reply_to: ReplyTo<(AnyConsensusState, MerkleProof)>,
},
QueryCommitmentPrefix {
reply_to: ReplyTo<CommitmentPrefix>,
},
QueryCompatibleVersions {
reply_to: ReplyTo<Vec<Version>>,
},
QueryConnection {
request: QueryConnectionRequest,
include_proof: IncludeProof,
reply_to: ReplyTo<(ConnectionEnd, Option<MerkleProof>)>,
},
QueryConnections {
request: QueryConnectionsRequest,
reply_to: ReplyTo<Vec<IdentifiedConnectionEnd>>,
},
QueryConnectionChannels {
request: QueryConnectionChannelsRequest,
reply_to: ReplyTo<Vec<IdentifiedChannelEnd>>,
},
QueryChannels {
request: QueryChannelsRequest,
reply_to: ReplyTo<Vec<IdentifiedChannelEnd>>,
},
QueryChannel {
request: QueryChannelRequest,
include_proof: IncludeProof,
reply_to: ReplyTo<(ChannelEnd, Option<MerkleProof>)>,
},
QueryChannelClientState {
request: QueryChannelClientStateRequest,
reply_to: ReplyTo<Option<IdentifiedAnyClientState>>,
},
QueryNextSequenceReceive {
request: QueryNextSequenceReceiveRequest,
include_proof: IncludeProof,
reply_to: ReplyTo<(Sequence, Option<MerkleProof>)>,
},
BuildChannelProofs {
port_id: PortId,
channel_id: ChannelId,
height: Height,
reply_to: ReplyTo<Proofs>,
},
BuildPacketProofs {
packet_type: PacketMsgType,
port_id: PortId,
channel_id: ChannelId,
sequence: Sequence,
height: Height,
reply_to: ReplyTo<Proofs>,
},
QueryPacketCommitment {
request: QueryPacketCommitmentRequest,
include_proof: IncludeProof,
reply_to: ReplyTo<(Vec<u8>, Option<MerkleProof>)>,
},
QueryPacketCommitments {
request: QueryPacketCommitmentsRequest,
reply_to: ReplyTo<(Vec<Sequence>, Height)>,
},
QueryPacketReceipt {
request: QueryPacketReceiptRequest,
include_proof: IncludeProof,
reply_to: ReplyTo<(Vec<u8>, Option<MerkleProof>)>,
},
QueryUnreceivedPackets {
request: QueryUnreceivedPacketsRequest,
reply_to: ReplyTo<Vec<Sequence>>,
},
QueryPacketAcknowledgement {
request: QueryPacketAcknowledgementRequest,
include_proof: IncludeProof,
reply_to: ReplyTo<(Vec<u8>, Option<MerkleProof>)>,
},
QueryPacketAcknowledgements {
request: QueryPacketAcknowledgementsRequest,
reply_to: ReplyTo<(Vec<Sequence>, Height)>,
},
QueryUnreceivedAcknowledgement {
request: QueryUnreceivedAcksRequest,
reply_to: ReplyTo<Vec<Sequence>>,
},
QueryPacketEventDataFromTxs {
request: QueryTxRequest,
reply_to: ReplyTo<Vec<IbcEventWithHeight>>,
},
QueryPacketEventData {
request: QueryPacketEventDataRequest,
reply_to: ReplyTo<Vec<IbcEventWithHeight>>,
},
QueryHostConsensusState {
request: QueryHostConsensusStateRequest,
reply_to: ReplyTo<AnyConsensusState>,
},
MaybeRegisterCounterpartyPayee {
channel_id: ChannelId,
port_id: PortId,
counterparty_payee: Signer,
reply_to: ReplyTo<()>,
},
}
pub trait ChainHandle: Clone + Display + Send + Sync + Debug + 'static {
fn new(chain_id: ChainId, sender: channel::Sender<(Span, ChainRequest)>) -> Self;
fn id(&self) -> ChainId;
fn shutdown(&self) -> Result<(), Error>;
fn health_check(&self) -> Result<HealthCheck, Error>;
fn subscribe(&self) -> Result<Subscription, Error>;
fn send_messages_and_wait_commit(
&self,
tracked_msgs: TrackedMsgs,
) -> Result<Vec<IbcEventWithHeight>, Error>;
fn send_messages_and_wait_check_tx(
&self,
tracked_msgs: TrackedMsgs,
) -> Result<Vec<tendermint_rpc::endpoint::broadcast::tx_sync::Response>, Error>;
fn get_signer(&self) -> Result<Signer, Error>;
fn config(&self) -> Result<ChainConfig, Error>;
fn get_key(&self) -> Result<AnySigningKeyPair, Error>;
fn add_key(&self, key_name: String, key: AnySigningKeyPair) -> Result<(), Error>;
fn ibc_version(&self) -> Result<Option<semver::Version>, Error>;
fn query_balance(
&self,
key_name: Option<String>,
denom: Option<String>,
) -> Result<Balance, Error>;
fn query_all_balances(&self, key_name: Option<String>) -> Result<Vec<Balance>, Error>;
fn query_denom_trace(&self, hash: String) -> Result<DenomTrace, Error>;
fn query_application_status(&self) -> Result<ChainStatus, Error>;
fn query_latest_height(&self) -> Result<Height, Error> {
Ok(self.query_application_status()?.height)
}
fn query_clients(
&self,
request: QueryClientStatesRequest,
) -> Result<Vec<IdentifiedAnyClientState>, Error>;
fn query_client_state(
&self,
request: QueryClientStateRequest,
include_proof: IncludeProof,
) -> Result<(AnyClientState, Option<MerkleProof>), Error>;
fn query_client_connections(
&self,
request: QueryClientConnectionsRequest,
) -> Result<Vec<ConnectionId>, Error>;
fn query_consensus_state(
&self,
request: QueryConsensusStateRequest,
include_proof: IncludeProof,
) -> Result<(AnyConsensusState, Option<MerkleProof>), Error>;
fn query_consensus_states(
&self,
request: QueryConsensusStatesRequest,
) -> Result<Vec<AnyConsensusStateWithHeight>, Error>;
fn query_upgraded_client_state(
&self,
request: QueryUpgradedClientStateRequest,
) -> Result<(AnyClientState, MerkleProof), Error>;
fn query_upgraded_consensus_state(
&self,
request: QueryUpgradedConsensusStateRequest,
) -> Result<(AnyConsensusState, MerkleProof), Error>;
fn query_commitment_prefix(&self) -> Result<CommitmentPrefix, Error>;
fn query_compatible_versions(&self) -> Result<Vec<Version>, Error>;
fn query_connection(
&self,
request: QueryConnectionRequest,
include_proof: IncludeProof,
) -> Result<(ConnectionEnd, Option<MerkleProof>), Error>;
fn query_connections(
&self,
request: QueryConnectionsRequest,
) -> Result<Vec<IdentifiedConnectionEnd>, Error>;
fn query_connection_channels(
&self,
request: QueryConnectionChannelsRequest,
) -> Result<Vec<IdentifiedChannelEnd>, Error>;
fn query_next_sequence_receive(
&self,
request: QueryNextSequenceReceiveRequest,
include_proof: IncludeProof,
) -> Result<(Sequence, Option<MerkleProof>), Error>;
fn query_channels(
&self,
request: QueryChannelsRequest,
) -> Result<Vec<IdentifiedChannelEnd>, Error>;
fn query_channel(
&self,
request: QueryChannelRequest,
include_proof: IncludeProof,
) -> Result<(ChannelEnd, Option<MerkleProof>), Error>;
fn query_channel_client_state(
&self,
request: QueryChannelClientStateRequest,
) -> Result<Option<IdentifiedAnyClientState>, Error>;
fn build_header(
&self,
trusted_height: Height,
target_height: Height,
client_state: AnyClientState,
) -> Result<(AnyHeader, Vec<AnyHeader>), Error>;
fn build_client_state(
&self,
height: Height,
settings: ClientSettings,
) -> Result<AnyClientState, Error>;
fn build_consensus_state(
&self,
trusted: Height,
target: Height,
client_state: AnyClientState,
) -> Result<AnyConsensusState, Error>;
fn check_misbehaviour(
&self,
update: UpdateClient,
client_state: AnyClientState,
) -> Result<Option<MisbehaviourEvidence>, Error>;
fn build_connection_proofs_and_client_state(
&self,
message_type: ConnectionMsgType,
connection_id: &ConnectionId,
client_id: &ClientId,
height: Height,
) -> Result<(Option<AnyClientState>, Proofs), Error>;
fn build_channel_proofs(
&self,
port_id: &PortId,
channel_id: &ChannelId,
height: Height,
) -> Result<Proofs, Error>;
fn build_packet_proofs(
&self,
packet_type: PacketMsgType,
port_id: &PortId,
channel_id: &ChannelId,
sequence: Sequence,
height: Height,
) -> Result<Proofs, Error>;
fn query_packet_commitment(
&self,
request: QueryPacketCommitmentRequest,
include_proof: IncludeProof,
) -> Result<(Vec<u8>, Option<MerkleProof>), Error>;
fn query_packet_commitments(
&self,
request: QueryPacketCommitmentsRequest,
) -> Result<(Vec<Sequence>, Height), Error>;
fn query_packet_receipt(
&self,
request: QueryPacketReceiptRequest,
include_proof: IncludeProof,
) -> Result<(Vec<u8>, Option<MerkleProof>), Error>;
fn query_unreceived_packets(
&self,
request: QueryUnreceivedPacketsRequest,
) -> Result<Vec<Sequence>, Error>;
fn query_packet_acknowledgement(
&self,
request: QueryPacketAcknowledgementRequest,
include_proof: IncludeProof,
) -> Result<(Vec<u8>, Option<MerkleProof>), Error>;
fn query_packet_acknowledgements(
&self,
request: QueryPacketAcknowledgementsRequest,
) -> Result<(Vec<Sequence>, Height), Error>;
fn query_unreceived_acknowledgements(
&self,
request: QueryUnreceivedAcksRequest,
) -> Result<Vec<Sequence>, Error>;
fn query_txs(&self, request: QueryTxRequest) -> Result<Vec<IbcEventWithHeight>, Error>;
fn query_packet_events(
&self,
request: QueryPacketEventDataRequest,
) -> Result<Vec<IbcEventWithHeight>, Error>;
fn query_host_consensus_state(
&self,
request: QueryHostConsensusStateRequest,
) -> Result<AnyConsensusState, Error>;
fn maybe_register_counterparty_payee(
&self,
channel_id: ChannelId,
port_id: PortId,
counterparty_payee: Signer,
) -> Result<(), Error>;
}