diff --git a/ibc-eureka-core/ics02-client/context/src/context.rs b/ibc-eureka-core/ics02-client/context/src/context.rs index 7c219cf00..dc134e1fd 100644 --- a/ibc-eureka-core/ics02-client/context/src/context.rs +++ b/ibc-eureka-core/ics02-client/context/src/context.rs @@ -1,4 +1,5 @@ use ibc_eureka_core_client_types::Height; +use ibc_eureka_core_commitment_types::commitment::CommitmentPrefix; use ibc_eureka_core_host_types::error::HostError; use ibc_eureka_core_host_types::identifiers::ClientId; use ibc_eureka_core_host_types::path::{ClientConsensusStatePath, ClientStatePath}; @@ -39,6 +40,12 @@ pub trait ClientValidationContext: Sized { client_id: &ClientId, height: &Height, ) -> Result<(Timestamp, Height), HostError>; + + /// Returns the client identifier and the commitment prefix of the counterparty client. + fn counterparty_meta( + &self, + client_id: &ClientId, + ) -> Result, HostError>; } /// Defines the methods that all client `ExecutionContext`s (precisely the @@ -98,6 +105,17 @@ pub trait ClientExecutionContext: /// /// Note that this timestamp is determined by the host. fn delete_update_meta(&mut self, client_id: ClientId, height: Height) -> Result<(), HostError>; + + /// Store the client identifier and the commitment prefix of the counterparty client. + fn store_counterparty_meta( + &self, + client_id: &ClientId, + counterparty_client_id: &ClientId, + counterparty_prefix: &CommitmentPrefix, + ) -> Result<(), HostError>; + + /// Delete the client identifier and the commitment prefix of the counterparty client. + fn delete_counterparty_meta(&self, client_id: &ClientId) -> Result<(), HostError>; } /// An optional trait that extends the client validation context capabilities by diff --git a/ibc-eureka-core/ics02-client/src/handler/mod.rs b/ibc-eureka-core/ics02-client/src/handler/mod.rs index 791b5ce39..cd5a9e65c 100644 --- a/ibc-eureka-core/ics02-client/src/handler/mod.rs +++ b/ibc-eureka-core/ics02-client/src/handler/mod.rs @@ -1,6 +1,7 @@ //! This module implements the processing logic for ICS2 (client abstractions and functions) msgs. pub mod create_client; +pub mod provide_counterparty; pub mod recover_client; pub mod update_client; pub mod upgrade_client; diff --git a/ibc-eureka-core/ics02-client/src/handler/provide_counterparty.rs b/ibc-eureka-core/ics02-client/src/handler/provide_counterparty.rs new file mode 100644 index 000000000..b4154f3c6 --- /dev/null +++ b/ibc-eureka-core/ics02-client/src/handler/provide_counterparty.rs @@ -0,0 +1,57 @@ +//! Protocol logic specific to processing ICS2 messages of type `MsgProvideCouterparty`. + +use ibc_eureka_core_client_context::prelude::*; +use ibc_eureka_core_client_types::error::ClientError; +use ibc_eureka_core_client_types::msgs::MsgProvideCouterparty; +use ibc_eureka_core_host::{ExecutionContext, ValidationContext}; +use ibc_primitives::prelude::*; + +pub fn validate(ctx: &Ctx, msg: MsgProvideCouterparty) -> Result<(), ClientError> +where + Ctx: ValidationContext, +{ + let MsgProvideCouterparty { + client_id, signer, .. + } = &msg; + + ctx.validate_message_signer(signer)?; + + let client_val_ctx = ctx.get_client_validation_context(); + + // Read client state from the host chain store. The client should already exist. + let client_state = client_val_ctx.client_state(client_id)?; + + client_state + .status(client_val_ctx, client_id)? + .verify_is_active()?; + + if client_val_ctx.counterparty_meta(client_id)?.is_some() { + return Err(ClientError::ClientSpecific { + description: "counterparty is already provided".into(), + }); + } + + Ok(()) +} + +pub fn execute(ctx: &mut Ctx, msg: MsgProvideCouterparty) -> Result<(), ClientError> +where + Ctx: ExecutionContext, +{ + let MsgProvideCouterparty { + client_id, + counterparty_client_id, + counterparty_commitment_prefix, + .. + } = &msg; + + let client_exec_ctx = ctx.get_client_execution_context(); + + client_exec_ctx.store_counterparty_meta( + client_id, + counterparty_client_id, + counterparty_commitment_prefix, + )?; + + Ok(()) +} diff --git a/ibc-eureka-core/ics02-client/types/src/msgs/mod.rs b/ibc-eureka-core/ics02-client/types/src/msgs/mod.rs index 7c02331c3..0ba422b1c 100644 --- a/ibc-eureka-core/ics02-client/types/src/msgs/mod.rs +++ b/ibc-eureka-core/ics02-client/types/src/msgs/mod.rs @@ -9,12 +9,14 @@ use ibc_proto::google::protobuf::Any; mod create_client; mod misbehaviour; +mod provide_counterparty; mod recover_client; mod update_client; mod upgrade_client; pub use create_client::*; pub use misbehaviour::*; +pub use provide_counterparty::*; pub use recover_client::*; pub use update_client::*; pub use upgrade_client::*; @@ -33,6 +35,7 @@ pub enum ClientMsg { Misbehaviour(MsgSubmitMisbehaviour), UpgradeClient(MsgUpgradeClient), RecoverClient(MsgRecoverClient), + ProvideCounterparty(MsgProvideCouterparty), } pub enum MsgUpdateOrMisbehaviour { diff --git a/ibc-eureka-core/ics02-client/types/src/msgs/provide_counterparty.rs b/ibc-eureka-core/ics02-client/types/src/msgs/provide_counterparty.rs new file mode 100644 index 000000000..8c3d97fe5 --- /dev/null +++ b/ibc-eureka-core/ics02-client/types/src/msgs/provide_counterparty.rs @@ -0,0 +1,38 @@ +//! Definition of domain type message `MsgProvideCouterparty`. + +use ibc_eureka_core_commitment_types::commitment::CommitmentPrefix; +use ibc_eureka_core_host_types::identifiers::ClientId; +use ibc_primitives::prelude::*; +use ibc_primitives::Signer; + +pub const _PROVIDE_COUNTERPARTY_TYPE_URL: &str = "/ibc.core.client.v1.MsgProvideCouterparty"; + +/// A type of message that links an on-chain (IBC) client to its counterparty. +#[cfg_attr( + feature = "borsh", + derive(borsh::BorshSerialize, borsh::BorshDeserialize) +)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct MsgProvideCouterparty { + pub client_id: ClientId, + pub counterparty_client_id: ClientId, + pub counterparty_commitment_prefix: CommitmentPrefix, + pub signer: Signer, +} + +impl MsgProvideCouterparty { + pub fn new( + client_id: ClientId, + counterparty_client_id: ClientId, + counterparty_commitment_prefix: CommitmentPrefix, + signer: Signer, + ) -> Self { + MsgProvideCouterparty { + client_id, + counterparty_client_id, + counterparty_commitment_prefix, + signer, + } + } +} diff --git a/ibc-eureka-core/ics04-channel/src/context.rs b/ibc-eureka-core/ics04-channel/src/context.rs index 87b0ab296..91c9f012f 100644 --- a/ibc-eureka-core/ics04-channel/src/context.rs +++ b/ibc-eureka-core/ics04-channel/src/context.rs @@ -5,7 +5,9 @@ use ibc_eureka_core_client::context::prelude::*; use ibc_eureka_core_handler_types::events::IbcEvent; use ibc_eureka_core_host::types::error::HostError; use ibc_eureka_core_host::types::identifiers::Sequence; -use ibc_eureka_core_host::types::path::{CommitmentPath, SeqSendPath}; +use ibc_eureka_core_host::types::path::{ + CommitmentPathV2 as CommitmentPath, SeqSendPathV2 as SeqSendPath, +}; use ibc_eureka_core_host::{ExecutionContext, ValidationContext}; use ibc_primitives::prelude::*; diff --git a/ibc-eureka-core/ics04-channel/src/handler/acknowledgement.rs b/ibc-eureka-core/ics04-channel/src/handler/acknowledgement.rs index 1c0f32e5d..6c2f1a5ec 100644 --- a/ibc-eureka-core/ics04-channel/src/handler/acknowledgement.rs +++ b/ibc-eureka-core/ics04-channel/src/handler/acknowledgement.rs @@ -6,7 +6,10 @@ use ibc_eureka_core_channel_types::events::AcknowledgePacket; use ibc_eureka_core_channel_types::msgs::MsgAcknowledgement; use ibc_eureka_core_client::context::prelude::*; use ibc_eureka_core_handler_types::events::{IbcEvent, MessageEvent}; -use ibc_eureka_core_host::types::path::{AckPath, ClientConsensusStatePath, CommitmentPath, Path}; +use ibc_eureka_core_host::types::identifiers::ClientId; +use ibc_eureka_core_host::types::path::{ + AckPathV2 as AckPath, ClientConsensusStatePath, CommitmentPathV2 as CommitmentPath, Path, +}; use ibc_eureka_core_host::{ExecutionContext, ValidationContext}; use ibc_eureka_core_router::module::Module; use ibc_primitives::prelude::*; @@ -33,10 +36,9 @@ where ExecCtx: ExecutionContext, { let packet = &msg.packet; - let payload = &packet.payloads[0]; - let (_, port_id_on_a) = &payload.header.source_port; - let channel_id_on_a = &packet.header.target_client_on_source; + let channel_target_client_on_source = &packet.header.target_client_on_source; + let channel_source_client_on_target = &packet.header.source_client_on_target; let seq_on_a = &packet.header.seq_on_a; // In all cases, this event is emitted @@ -44,7 +46,11 @@ where ctx_a.emit_ibc_event(IbcEvent::Message(MessageEvent::Channel))?; ctx_a.emit_ibc_event(event)?; - let commitment_path_on_a = CommitmentPath::new(port_id_on_a, channel_id_on_a, *seq_on_a); + let commitment_path_on_a = CommitmentPath::new( + channel_source_client_on_target.as_ref(), + channel_target_client_on_source.as_ref(), + seq_on_a, + ); // check if we're in the NO-OP case if ctx_a.get_packet_commitment(&commitment_path_on_a).is_err() { @@ -92,14 +98,16 @@ where let packet = &msg.packet; let payload = &packet.payloads[0]; - let (prefix_on_a, port_id_on_a) = &payload.header.source_port; - let channel_id_on_a = &packet.header.target_client_on_source; - let (_, port_id_on_b) = &payload.header.target_port; - let channel_id_on_b = &packet.header.source_client_on_target; + let channel_target_client_on_source = &packet.header.target_client_on_source; + let channel_source_client_on_target = &packet.header.source_client_on_target; let seq_on_a = &packet.header.seq_on_a; let data = &payload.data; - let commitment_path_on_a = CommitmentPath::new(port_id_on_a, channel_id_on_a, *seq_on_a); + let commitment_path_on_a = CommitmentPath::new( + channel_source_client_on_target.as_ref(), + channel_target_client_on_source.as_ref(), + seq_on_a, + ); // Verify packet commitment let Ok(commitment_on_a) = ctx_a.get_packet_commitment(&commitment_path_on_a) else { @@ -126,34 +134,53 @@ where // Verify proofs { // TODO(rano): avoid a vs b confusion - let client_id_on_a = channel_id_on_b.as_ref(); + let id_target_client_on_source = channel_target_client_on_source.as_ref(); + let id_source_client_on_target: &ClientId = channel_source_client_on_target.as_ref(); let client_val_ctx_a = ctx_a.get_client_validation_context(); - let client_state_of_b_on_a = client_val_ctx_a.client_state(client_id_on_a)?; + let (stored_id_source_client_on_target, target_prefix) = client_val_ctx_a + .counterparty_meta(id_target_client_on_source)? + .ok_or(ChannelError::MissingCounterparty)?; - client_state_of_b_on_a - .status(ctx_a.get_client_validation_context(), client_id_on_a)? + if &stored_id_source_client_on_target != id_source_client_on_target { + return Err(ChannelError::MismatchCounterparty { + expected: stored_id_source_client_on_target.clone(), + actual: id_source_client_on_target.clone(), + }); + } + + let target_client_on_source = client_val_ctx_a.client_state(id_target_client_on_source)?; + + target_client_on_source + .status( + ctx_a.get_client_validation_context(), + id_target_client_on_source, + )? .verify_is_active()?; - client_state_of_b_on_a.validate_proof_height(msg.proof_height_on_b)?; + target_client_on_source.validate_proof_height(msg.proof_height_on_b)?; let client_cons_state_path_on_a = ClientConsensusStatePath::new( - client_id_on_a.clone(), + id_target_client_on_source.clone(), msg.proof_height_on_b.revision_number(), msg.proof_height_on_b.revision_height(), ); let consensus_state_of_b_on_a = client_val_ctx_a.consensus_state(&client_cons_state_path_on_a)?; let ack_commitment = compute_ack_commitment(&msg.acknowledgement); - let ack_path_on_b = AckPath::new(port_id_on_b, channel_id_on_b, *seq_on_a); + let ack_path_on_b = AckPath::new( + channel_source_client_on_target.as_ref(), + channel_target_client_on_source.as_ref(), + seq_on_a, + ); // Verify the proof for the packet against the chain store. - client_state_of_b_on_a.verify_membership( - prefix_on_a, + target_client_on_source.verify_membership( + &target_prefix, &msg.proof_acked_on_b, consensus_state_of_b_on_a.root(), - Path::Ack(ack_path_on_b), + Path::AckV2(ack_path_on_b), ack_commitment.into_vec(), )?; } diff --git a/ibc-eureka-core/ics04-channel/src/handler/recv_packet.rs b/ibc-eureka-core/ics04-channel/src/handler/recv_packet.rs index ea76af1e3..1a3eca9ad 100644 --- a/ibc-eureka-core/ics04-channel/src/handler/recv_packet.rs +++ b/ibc-eureka-core/ics04-channel/src/handler/recv_packet.rs @@ -6,8 +6,10 @@ use ibc_eureka_core_channel_types::events::{ReceivePacket, WriteAcknowledgement} use ibc_eureka_core_channel_types::msgs::MsgRecvPacket; use ibc_eureka_core_client::context::prelude::*; use ibc_eureka_core_handler_types::events::{IbcEvent, MessageEvent}; +use ibc_eureka_core_host::types::identifiers::ClientId; use ibc_eureka_core_host::types::path::{ - AckPath, ClientConsensusStatePath, CommitmentPath, Path, ReceiptPath, SeqRecvPath, + AckPathV2 as AckPath, ClientConsensusStatePath, CommitmentPathV2 as CommitmentPath, Path, + ReceiptPathV2 as ReceiptPath, SeqRecvPathV2 as SeqRecvPath, }; use ibc_eureka_core_host::{ExecutionContext, ValidationContext}; use ibc_eureka_core_router::module::Module; @@ -33,18 +35,20 @@ where ExecCtx: ExecutionContext, { let packet = &msg.packet; - let payload = &packet.payloads[0]; - let (_, target_port) = &payload.header.target_port; let channel_source_client_on_target = &packet.header.source_client_on_target; + let channel_target_client_on_source = &packet.header.target_client_on_source; let seq_on_a = &packet.header.seq_on_a; // Check if another relayer already relayed the packet. // We don't want to fail the transaction in this case. { let packet_already_received = { - let receipt_path_on_b = - ReceiptPath::new(target_port, channel_source_client_on_target, *seq_on_a); + let receipt_path_on_b = ReceiptPath::new( + channel_source_client_on_target.as_ref(), + channel_target_client_on_source.as_ref(), + seq_on_a, + ); ctx_b.get_packet_receipt(&receipt_path_on_b)?.is_ok() }; @@ -59,11 +63,18 @@ where { // `recvPacket` core handler state changes { - let seq_recv_path_on_b = SeqRecvPath::new(target_port, channel_source_client_on_target); + let seq_recv_path_on_b = SeqRecvPath::new( + channel_source_client_on_target.as_ref(), + channel_target_client_on_source.as_ref(), + ); let next_seq_recv = ctx_b.get_next_sequence_recv(&seq_recv_path_on_b)?; ctx_b.store_next_sequence_recv(&seq_recv_path_on_b, next_seq_recv.increment())?; } - let ack_path_on_b = AckPath::new(target_port, channel_source_client_on_target, *seq_on_a); + let ack_path_on_b = AckPath::new( + channel_source_client_on_target.as_ref(), + channel_target_client_on_source.as_ref(), + seq_on_a, + ); // `writeAcknowledgement` handler state changes ctx_b.store_packet_acknowledgement( &ack_path_on_b, @@ -105,7 +116,6 @@ where let packet = &msg.packet; let payload = &packet.payloads[0]; - let (prefix_source, source_port) = &payload.header.source_port; let channel_target_client_on_source = &packet.header.target_client_on_source; let channel_source_client_on_target = &packet.header.source_client_on_target; let seq_on_a = &packet.header.seq_on_a; @@ -131,7 +141,21 @@ where // Verify proofs { let id_source_client_on_target = channel_source_client_on_target.as_ref(); + let id_target_client_on_source: &ClientId = channel_target_client_on_source.as_ref(); + let client_val_ctx_b = ctx_b.get_client_validation_context(); + + let (stored_id_target_client_on_source, source_prefix) = client_val_ctx_b + .counterparty_meta(id_source_client_on_target)? + .ok_or(ChannelError::MissingCounterparty)?; + + if &stored_id_target_client_on_source != id_target_client_on_source { + return Err(ChannelError::MismatchCounterparty { + expected: stored_id_target_client_on_source.clone(), + actual: id_target_client_on_source.clone(), + }); + } + let source_client_on_target = client_val_ctx_b.client_state(id_source_client_on_target)?; source_client_on_target @@ -157,15 +181,18 @@ where &packet.header.timeout_height_on_b, &packet.header.timeout_timestamp_on_b, ); - let commitment_path_on_a = - CommitmentPath::new(source_port, channel_target_client_on_source, *seq_on_a); + let commitment_path_on_a = CommitmentPath::new( + channel_source_client_on_target.as_ref(), + channel_target_client_on_source.as_ref(), + seq_on_a, + ); // Verify the proof for the packet against the chain store. source_client_on_target.verify_membership( - prefix_source, + &source_prefix, &msg.proof_commitment_on_a, consensus_state_of_a_on_b.root(), - Path::Commitment(commitment_path_on_a), + Path::CommitmentV2(commitment_path_on_a), expected_commitment_on_a.into_vec(), )?; } @@ -189,13 +216,16 @@ where Ctx: ValidationContext, { let packet = &msg.packet; - let payload = &packet.payloads[0]; - let (_, target_port) = &payload.header.target_port; let channel_source_client_on_target = &packet.header.source_client_on_target; + let channel_target_client_on_source = &packet.header.target_client_on_source; let seq_on_a = &packet.header.seq_on_a; - let ack_path_on_b = AckPath::new(target_port, channel_source_client_on_target, *seq_on_a); + let ack_path_on_b = AckPath::new( + channel_source_client_on_target.as_ref(), + channel_target_client_on_source.as_ref(), + seq_on_a, + ); if ctx_b.get_packet_acknowledgement(&ack_path_on_b).is_ok() { return Err(ChannelError::DuplicateAcknowledgment(*seq_on_a)); } diff --git a/ibc-eureka-core/ics04-channel/src/handler/send_packet.rs b/ibc-eureka-core/ics04-channel/src/handler/send_packet.rs index 6e9747ebe..b1a15110d 100644 --- a/ibc-eureka-core/ics04-channel/src/handler/send_packet.rs +++ b/ibc-eureka-core/ics04-channel/src/handler/send_packet.rs @@ -4,7 +4,10 @@ use ibc_eureka_core_channel_types::events::SendPacket; use ibc_eureka_core_channel_types::packet::Packet; use ibc_eureka_core_client::context::prelude::*; use ibc_eureka_core_handler_types::events::{IbcEvent, MessageEvent}; -use ibc_eureka_core_host::types::path::{ClientConsensusStatePath, CommitmentPath, SeqSendPath}; +use ibc_eureka_core_host::types::identifiers::ClientId; +use ibc_eureka_core_host::types::path::{ + ClientConsensusStatePath, CommitmentPathV2 as CommitmentPath, SeqSendPathV2 as SeqSendPath, +}; use ibc_primitives::prelude::*; use crate::context::{SendPacketExecutionContext, SendPacketValidationContext}; @@ -30,15 +33,25 @@ pub fn send_packet_validate( return Err(ChannelError::MissingTimeout); } - let payload = &packet.payloads[0]; - - let (_, source_port) = &payload.header.source_port; let channel_target_client_on_source = &packet.header.target_client_on_source; + let channel_source_client_on_target = &packet.header.source_client_on_target; let seq_on_a = &packet.header.seq_on_a; + let client_val_ctx_a = ctx_a.get_client_validation_context(); + let id_target_client_on_source = channel_target_client_on_source.as_ref(); + let id_source_client_on_target: &ClientId = channel_source_client_on_target.as_ref(); - let client_val_ctx_a = ctx_a.get_client_validation_context(); + let (stored_id_source_client_on_target, _) = client_val_ctx_a + .counterparty_meta(id_target_client_on_source)? + .ok_or(ChannelError::MissingCounterparty)?; + + if &stored_id_source_client_on_target != id_source_client_on_target { + return Err(ChannelError::MismatchCounterparty { + expected: stored_id_source_client_on_target.clone(), + actual: id_source_client_on_target.clone(), + }); + } let target_client_on_source = client_val_ctx_a.client_state(id_target_client_on_source)?; @@ -75,7 +88,11 @@ pub fn send_packet_validate( } // TODO(rano): include full channel identifier in the path - let seq_send_path_on_a = SeqSendPath::new(source_port, channel_target_client_on_source); + let seq_send_path_on_a = SeqSendPath::new( + channel_source_client_on_target.as_ref(), + // todo(rano): use ascii encoding of the bytes + channel_target_client_on_source.as_ref(), + ); let next_seq_send_on_a = ctx_a.get_next_sequence_send(&seq_send_path_on_a)?; if seq_on_a != &next_seq_send_on_a { @@ -97,20 +114,27 @@ pub fn send_packet_execute( ) -> Result<(), ChannelError> { let payload = &packet.payloads[0]; - let (_, source_port) = &payload.header.source_port; let channel_target_client_on_source = &packet.header.target_client_on_source; + let channel_source_client_on_target = &packet.header.source_client_on_target; let seq_on_a = &packet.header.seq_on_a; let data = &payload.data; { - let seq_send_path_on_a = SeqSendPath::new(source_port, channel_target_client_on_source); + let seq_send_path_on_a = SeqSendPath::new( + channel_source_client_on_target.as_ref(), + channel_target_client_on_source.as_ref(), + ); let next_seq_send_on_a = ctx_a.get_next_sequence_send(&seq_send_path_on_a)?; ctx_a.store_next_sequence_send(&seq_send_path_on_a, next_seq_send_on_a.increment())?; } ctx_a.store_packet_commitment( - &CommitmentPath::new(source_port, channel_target_client_on_source, *seq_on_a), + &CommitmentPath::new( + channel_source_client_on_target.as_ref(), + channel_target_client_on_source.as_ref(), + seq_on_a, + ), compute_packet_commitment( data, &packet.header.timeout_height_on_b, diff --git a/ibc-eureka-core/ics04-channel/src/handler/timeout.rs b/ibc-eureka-core/ics04-channel/src/handler/timeout.rs index 0166dffc8..24ac17f31 100644 --- a/ibc-eureka-core/ics04-channel/src/handler/timeout.rs +++ b/ibc-eureka-core/ics04-channel/src/handler/timeout.rs @@ -4,8 +4,10 @@ use ibc_eureka_core_channel_types::events::TimeoutPacket; use ibc_eureka_core_channel_types::msgs::MsgTimeout; use ibc_eureka_core_client::context::prelude::*; use ibc_eureka_core_handler_types::events::{IbcEvent, MessageEvent}; +use ibc_eureka_core_host::types::identifiers::ClientId; use ibc_eureka_core_host::types::path::{ - ClientConsensusStatePath, CommitmentPath, Path, ReceiptPath, + ClientConsensusStatePath, CommitmentPathV2 as CommitmentPath, Path, + ReceiptPathV2 as ReceiptPath, }; use ibc_eureka_core_host::{ExecutionContext, ValidationContext}; use ibc_eureka_core_router::module::Module; @@ -36,10 +38,8 @@ where { let (packet, signer) = (msg.packet, msg.signer); - let payload = &packet.payloads[0]; - - let (_, source_port) = &payload.header.source_port; let channel_target_client_on_source = &packet.header.target_client_on_source; + let channel_source_client_on_target = &packet.header.source_client_on_target; let seq_on_a = &packet.header.seq_on_a; // In all cases, this event is emitted @@ -47,8 +47,11 @@ where ctx_a.emit_ibc_event(IbcEvent::Message(MessageEvent::Channel))?; ctx_a.emit_ibc_event(event)?; - let commitment_path_on_a = - CommitmentPath::new(source_port, channel_target_client_on_source, *seq_on_a); + let commitment_path_on_a = CommitmentPath::new( + channel_source_client_on_target.as_ref(), + channel_target_client_on_source.as_ref(), + seq_on_a, + ); // check if we're in the NO-OP case if ctx_a.get_packet_commitment(&commitment_path_on_a).is_err() { @@ -88,16 +91,17 @@ where let packet = &msg.packet; let payload = &packet.payloads[0]; - let (_, source_port) = &payload.header.source_port; let channel_target_client_on_source = &packet.header.target_client_on_source; - let (target_prefix, target_port) = &payload.header.target_port; let channel_source_client_on_target = &packet.header.source_client_on_target; let seq_on_a = &packet.header.seq_on_a; let data = &payload.data; //verify packet commitment - let commitment_path_on_a = - CommitmentPath::new(source_port, channel_target_client_on_source, *seq_on_a); + let commitment_path_on_a = CommitmentPath::new( + channel_source_client_on_target.as_ref(), + channel_target_client_on_source.as_ref(), + seq_on_a, + ); let Ok(commitment_on_a) = ctx_a.get_packet_commitment(&commitment_path_on_a) else { // This error indicates that the timeout has already been relayed // or there is a misconfigured relayer attempting to prove a timeout @@ -122,7 +126,21 @@ where // Verify proofs { let id_target_client_on_source = channel_target_client_on_source.as_ref(); + let id_source_client_on_target: &ClientId = channel_source_client_on_target.as_ref(); + let client_val_ctx_a = ctx_a.get_client_validation_context(); + + let (stored_id_source_client_on_target, target_prefix) = client_val_ctx_a + .counterparty_meta(id_target_client_on_source)? + .ok_or(ChannelError::MissingCounterparty)?; + + if &stored_id_source_client_on_target != id_source_client_on_target { + return Err(ChannelError::MismatchCounterparty { + expected: stored_id_source_client_on_target.clone(), + actual: id_source_client_on_target.clone(), + }); + } + let target_client_on_source = client_val_ctx_a.client_state(id_target_client_on_source)?; target_client_on_source @@ -154,14 +172,17 @@ where } let next_seq_recv_verification_result = { - let receipt_path_on_b = - ReceiptPath::new(target_port, channel_source_client_on_target, *seq_on_a); + let receipt_path_on_b = ReceiptPath::new( + channel_source_client_on_target.as_ref(), + channel_target_client_on_source.as_ref(), + seq_on_a, + ); target_client_on_source.verify_non_membership( - target_prefix, + &target_prefix, &msg.proof_unreceived_on_b, consensus_state_of_b_on_a.root(), - Path::Receipt(receipt_path_on_b), + Path::ReceiptV2(receipt_path_on_b), ) }; diff --git a/ibc-eureka-core/ics04-channel/types/src/error.rs b/ibc-eureka-core/ics04-channel/types/src/error.rs index bcaad7b9a..8d2529744 100644 --- a/ibc-eureka-core/ics04-channel/types/src/error.rs +++ b/ibc-eureka-core/ics04-channel/types/src/error.rs @@ -4,7 +4,7 @@ use displaydoc::Display; use ibc_eureka_core_client_types::error::ClientError; use ibc_eureka_core_client_types::Height; use ibc_eureka_core_host_types::error::{DecodingError, HostError, IdentifierError}; -use ibc_eureka_core_host_types::identifiers::Sequence; +use ibc_eureka_core_host_types::identifiers::{ClientId, Sequence}; use ibc_primitives::prelude::*; use ibc_primitives::{Timestamp, TimestampError}; @@ -50,6 +50,11 @@ pub enum ChannelError { MissingCounterparty, /// missing timeout MissingTimeout, + /// mismatched counterparty: expected `{expected}`, actual `{actual}` + MismatchCounterparty { + expected: ClientId, + actual: ClientId, + }, /// mismatched packet sequence: expected `{expected}`, actual `{actual}` MismatchedPacketSequence { expected: Sequence, diff --git a/ibc-eureka-core/ics04-channel/types/src/events/mod.rs b/ibc-eureka-core/ics04-channel/types/src/events/mod.rs index f8ccd293a..457adf6f9 100644 --- a/ibc-eureka-core/ics04-channel/types/src/events/mod.rs +++ b/ibc-eureka-core/ics04-channel/types/src/events/mod.rs @@ -554,9 +554,9 @@ impl SendPacket { timeout_height_attr_on_b: packet.header.timeout_height_on_b.into(), timeout_timestamp_attr_on_b: packet.header.timeout_timestamp_on_b.into(), seq_attr_on_a: packet.header.seq_on_a.into(), - port_id_attr_on_a: payload.header.source_port.1.into(), + port_id_attr_on_a: payload.header.source_port.into(), chan_id_attr_on_a: packet.header.target_client_on_source.into(), - port_id_attr_on_b: payload.header.target_port.1.into(), + port_id_attr_on_b: payload.header.target_port.into(), chan_id_attr_on_b: packet.header.source_client_on_target.into(), } } @@ -652,9 +652,9 @@ impl ReceivePacket { timeout_height_attr_on_b: packet.header.timeout_height_on_b.into(), timeout_timestamp_attr_on_b: packet.header.timeout_timestamp_on_b.into(), seq_attr_on_a: packet.header.seq_on_a.into(), - port_id_attr_on_a: payload.header.source_port.1.into(), + port_id_attr_on_a: payload.header.source_port.into(), chan_id_attr_on_a: packet.header.target_client_on_source.into(), - port_id_attr_on_b: payload.header.target_port.1.into(), + port_id_attr_on_b: payload.header.target_port.into(), chan_id_attr_on_b: packet.header.source_client_on_target.into(), } } @@ -751,9 +751,9 @@ impl WriteAcknowledgement { timeout_height_attr_on_b: packet.header.timeout_height_on_b.into(), timeout_timestamp_attr_on_b: packet.header.timeout_timestamp_on_b.into(), seq_attr_on_a: packet.header.seq_on_a.into(), - port_id_attr_on_a: payload.header.source_port.1.into(), + port_id_attr_on_a: payload.header.source_port.into(), chan_id_attr_on_a: packet.header.target_client_on_source.into(), - port_id_attr_on_b: payload.header.target_port.1.into(), + port_id_attr_on_b: payload.header.target_port.into(), chan_id_attr_on_b: packet.header.source_client_on_target.into(), acknowledgement: acknowledgement.into(), } @@ -853,9 +853,9 @@ impl AcknowledgePacket { timeout_height_attr_on_b: packet.header.timeout_height_on_b.into(), timeout_timestamp_attr_on_b: packet.header.timeout_timestamp_on_b.into(), seq_on_a: packet.header.seq_on_a.into(), - port_id_attr_on_a: payload.header.source_port.1.into(), + port_id_attr_on_a: payload.header.source_port.into(), chan_id_attr_on_a: packet.header.target_client_on_source.into(), - port_id_attr_on_b: payload.header.target_port.1.into(), + port_id_attr_on_b: payload.header.target_port.into(), chan_id_attr_on_b: packet.header.source_client_on_target.into(), } } @@ -943,9 +943,9 @@ impl TimeoutPacket { timeout_height_attr_on_b: packet.header.timeout_height_on_b.into(), timeout_timestamp_attr_on_b: packet.header.timeout_timestamp_on_b.into(), seq_attr_on_a: packet.header.seq_on_a.into(), - port_id_attr_on_a: payload.header.source_port.1.into(), + port_id_attr_on_a: payload.header.source_port.into(), chan_id_attr_on_a: packet.header.target_client_on_source.into(), - port_id_attr_on_b: payload.header.target_port.1.into(), + port_id_attr_on_b: payload.header.target_port.into(), chan_id_attr_on_b: packet.header.source_client_on_target.into(), } } diff --git a/ibc-eureka-core/ics04-channel/types/src/msgs/mod.rs b/ibc-eureka-core/ics04-channel/types/src/msgs/mod.rs index 69981fb5d..158bcc33f 100644 --- a/ibc-eureka-core/ics04-channel/types/src/msgs/mod.rs +++ b/ibc-eureka-core/ics04-channel/types/src/msgs/mod.rs @@ -30,8 +30,8 @@ pub enum PacketMsg { pub fn packet_msg_to_port_id(msg: &PacketMsg) -> &PortId { match msg { - PacketMsg::Recv(msg) => &msg.packet.payloads[0].header.target_port.1, - PacketMsg::Ack(msg) => &msg.packet.payloads[0].header.source_port.1, - PacketMsg::Timeout(msg) => &msg.packet.payloads[0].header.source_port.1, + PacketMsg::Recv(msg) => &msg.packet.payloads[0].header.target_port, + PacketMsg::Ack(msg) => &msg.packet.payloads[0].header.source_port, + PacketMsg::Timeout(msg) => &msg.packet.payloads[0].header.source_port, } } diff --git a/ibc-eureka-core/ics04-channel/types/src/packet.rs b/ibc-eureka-core/ics04-channel/types/src/packet.rs index bec1b78cc..d83d03296 100644 --- a/ibc-eureka-core/ics04-channel/types/src/packet.rs +++ b/ibc-eureka-core/ics04-channel/types/src/packet.rs @@ -1,6 +1,5 @@ //! Defines the packet type use ibc_eureka_core_client_types::Height; -use ibc_eureka_core_commitment_types::commitment::CommitmentPrefix; use ibc_eureka_core_host_types::error::DecodingError; use ibc_eureka_core_host_types::identifiers::{ChannelId, PortId, Sequence}; use ibc_primitives::prelude::*; @@ -105,8 +104,8 @@ pub struct PacketHeader { #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct PayloadHeader { - pub source_port: (CommitmentPrefix, PortId), - pub target_port: (CommitmentPrefix, PortId), + pub source_port: PortId, + pub target_port: PortId, } #[cfg_attr( @@ -196,7 +195,7 @@ impl core::fmt::Display for Packet { write!( f, "src_port:{}, dst_port:{}", - payload.header.source_port.1, payload.header.target_port.1 + payload.header.source_port, payload.header.target_port )?; } Ok(()) @@ -247,8 +246,8 @@ impl TryFrom for Packet { // TODO(rano): support multi payload; currently only one payload is supported payloads: vec![Payload { header: PayloadHeader { - source_port: (CommitmentPrefix::empty(), raw_pkt.source_port.parse()?), - target_port: (CommitmentPrefix::empty(), raw_pkt.destination_port.parse()?), + source_port: raw_pkt.source_port.parse()?, + target_port: raw_pkt.destination_port.parse()?, }, data: raw_pkt.data, }], @@ -265,8 +264,8 @@ impl From for RawPacket { timeout_height: packet.header.timeout_height_on_b.into(), timeout_timestamp: packet.header.timeout_timestamp_on_b.nanoseconds(), // TODO(rano): support multi payload; currently only one payload is supported - source_port: packet.payloads[0].header.source_port.1.to_string(), - destination_port: packet.payloads[0].header.target_port.1.to_string(), + source_port: packet.payloads[0].header.source_port.to_string(), + destination_port: packet.payloads[0].header.target_port.to_string(), data: packet.payloads[0].data.clone(), } } diff --git a/ibc-eureka-core/ics24-host/src/context.rs b/ibc-eureka-core/ics24-host/src/context.rs index 8638a5ec9..c9051eedb 100644 --- a/ibc-eureka-core/ics24-host/src/context.rs +++ b/ibc-eureka-core/ics24-host/src/context.rs @@ -9,7 +9,8 @@ use ibc_eureka_core_handler_types::events::IbcEvent; use ibc_eureka_core_host_types::error::HostError; use ibc_eureka_core_host_types::identifiers::Sequence; use ibc_eureka_core_host_types::path::{ - AckPath, CommitmentPath, ReceiptPath, SeqAckPath, SeqRecvPath, SeqSendPath, + AckPathV2 as AckPath, CommitmentPathV2 as CommitmentPath, ReceiptPathV2 as ReceiptPath, + SeqAckPathV2 as SeqAckPath, SeqRecvPathV2 as SeqRecvPath, SeqSendPathV2 as SeqSendPath, }; use ibc_primitives::prelude::*; use ibc_primitives::{Signer, Timestamp}; diff --git a/ibc-eureka-core/ics24-host/types/src/path.rs b/ibc-eureka-core/ics24-host/types/src/path.rs index 750fb3bf6..050cb81b8 100644 --- a/ibc-eureka-core/ics24-host/types/src/path.rs +++ b/ibc-eureka-core/ics24-host/types/src/path.rs @@ -15,6 +15,10 @@ pub const NEXT_CLIENT_SEQUENCE: &str = "nextClientSequence"; pub const NEXT_CONNECTION_SEQUENCE: &str = "nextConnectionSequence"; pub const NEXT_CHANNEL_SEQUENCE: &str = "nextChannelSequence"; +pub const EUREKA: &str = "eureka"; +pub const SOURCE_CLIENT_ON_TARGET: &str = "sourceClientOnTarget"; +pub const TARGET_CLIENT_ON_SOURCE: &str = "targetClientOnSource"; + pub const CLIENT_PREFIX: &str = "clients"; pub const CLIENT_STATE: &str = "clientState"; pub const CONSENSUS_STATE_PREFIX: &str = "consensusStates"; @@ -98,6 +102,12 @@ pub enum Path { Commitment(CommitmentPath), Ack(AckPath), Receipt(ReceiptPath), + SeqSendV2(SeqSendPathV2), + SeqRecvV2(SeqRecvPathV2), + SeqAckV2(SeqAckPathV2), + CommitmentV2(CommitmentPathV2), + AckV2(AckPathV2), + ReceiptV2(ReceiptPathV2), UpgradeClientState(UpgradeClientStatePath), UpgradeConsensusState(UpgradeConsensusStatePath), } @@ -488,6 +498,37 @@ impl SeqSendPath { } } +#[cfg_attr( + feature = "parity-scale-codec", + derive( + parity_scale_codec::Encode, + parity_scale_codec::Decode, + scale_info::TypeInfo + ) +)] +#[cfg_attr( + feature = "borsh", + derive(borsh::BorshSerialize, borsh::BorshDeserialize) +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)] +#[display( + fmt = "{EUREKA}/{NEXT_SEQ_SEND_PREFIX}/{SOURCE_CLIENT_ON_TARGET}/{source_client_on_target}/{TARGET_CLIENT_ON_SOURCE}/{target_client_on_source}" +)] +pub struct SeqSendPathV2 { + pub source_client_on_target: ClientId, + pub target_client_on_source: ClientId, +} + +impl SeqSendPathV2 { + pub fn new(source_client_on_target: &ClientId, target_client_on_source: &ClientId) -> Self { + Self { + source_client_on_target: source_client_on_target.clone(), + target_client_on_source: target_client_on_source.clone(), + } + } +} + #[cfg_attr( feature = "parity-scale-codec", derive( @@ -511,6 +552,37 @@ impl SeqRecvPath { } } +#[cfg_attr( + feature = "parity-scale-codec", + derive( + parity_scale_codec::Encode, + parity_scale_codec::Decode, + scale_info::TypeInfo + ) +)] +#[cfg_attr( + feature = "borsh", + derive(borsh::BorshSerialize, borsh::BorshDeserialize) +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)] +#[display( + fmt = "{EUREKA}/{NEXT_SEQ_RECV_PREFIX}/{SOURCE_CLIENT_ON_TARGET}/{source_client_on_target}/{TARGET_CLIENT_ON_SOURCE}/{target_client_on_source}" +)] +pub struct SeqRecvPathV2 { + pub source_client_on_target: ClientId, + pub target_client_on_source: ClientId, +} + +impl SeqRecvPathV2 { + pub fn new(source_client_on_target: &ClientId, target_client_on_source: &ClientId) -> Self { + Self { + source_client_on_target: source_client_on_target.clone(), + target_client_on_source: target_client_on_source.clone(), + } + } +} + #[cfg_attr( feature = "parity-scale-codec", derive( @@ -534,6 +606,37 @@ impl SeqAckPath { } } +#[cfg_attr( + feature = "parity-scale-codec", + derive( + parity_scale_codec::Encode, + parity_scale_codec::Decode, + scale_info::TypeInfo + ) +)] +#[cfg_attr( + feature = "borsh", + derive(borsh::BorshSerialize, borsh::BorshDeserialize) +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)] +#[display( + fmt = "{EUREKA}/{NEXT_SEQ_ACK_PREFIX}/{SOURCE_CLIENT_ON_TARGET}/{source_client_on_target}/{TARGET_CLIENT_ON_SOURCE}/{target_client_on_source}" +)] +pub struct SeqAckPathV2 { + pub source_client_on_target: ClientId, + pub target_client_on_source: ClientId, +} + +impl SeqAckPathV2 { + pub fn new(source_client_on_target: &ClientId, target_client_on_source: &ClientId) -> Self { + Self { + source_client_on_target: source_client_on_target.clone(), + target_client_on_source: target_client_on_source.clone(), + } + } +} + #[cfg_attr( feature = "parity-scale-codec", derive( @@ -573,6 +676,51 @@ impl CommitmentPath { } } +#[cfg_attr( + feature = "parity-scale-codec", + derive( + parity_scale_codec::Encode, + parity_scale_codec::Decode, + scale_info::TypeInfo + ) +)] +#[cfg_attr( + feature = "borsh", + derive(borsh::BorshSerialize, borsh::BorshDeserialize) +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)] +#[display( + fmt = "{EUREKA}/{PACKET_COMMITMENT_PREFIX}/{SOURCE_CLIENT_ON_TARGET}/{source_client_on_target}/{TARGET_CLIENT_ON_SOURCE}/{target_client_on_source}/{SEQUENCE_PREFIX}/{sequence}" +)] +pub struct CommitmentPathV2 { + pub source_client_on_target: ClientId, + + pub target_client_on_source: ClientId, + + pub sequence: Sequence, +} + +impl CommitmentPathV2 { + pub fn new( + source_client_on_target: &ClientId, + target_client_on_source: &ClientId, + sequence: &Sequence, + ) -> Self { + Self { + source_client_on_target: source_client_on_target.clone(), + target_client_on_source: target_client_on_source.clone(), + sequence: *sequence, + } + } + + /// Returns the commitment store prefix under which all the packet + /// commitments are stored: "commitments" + pub fn prefix() -> String { + format!("{EUREKA}/{PACKET_COMMITMENT_PREFIX}") + } +} + #[cfg_attr( feature = "parity-scale-codec", derive( @@ -612,6 +760,49 @@ impl AckPath { } } +#[cfg_attr( + feature = "parity-scale-codec", + derive( + parity_scale_codec::Encode, + parity_scale_codec::Decode, + scale_info::TypeInfo + ) +)] +#[cfg_attr( + feature = "borsh", + derive(borsh::BorshSerialize, borsh::BorshDeserialize) +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)] +#[display( + fmt = "{EUREKA}/{PACKET_ACK_PREFIX}/{SOURCE_CLIENT_ON_TARGET}/{source_client_on_target}/{TARGET_CLIENT_ON_SOURCE}/{target_client_on_source}/{SEQUENCE_PREFIX}/{sequence}" +)] +pub struct AckPathV2 { + pub source_client_on_target: ClientId, + pub target_client_on_source: ClientId, + pub sequence: Sequence, +} + +impl AckPathV2 { + pub fn new( + source_client_on_target: &ClientId, + target_client_on_source: &ClientId, + sequence: &Sequence, + ) -> Self { + Self { + source_client_on_target: source_client_on_target.clone(), + target_client_on_source: target_client_on_source.clone(), + sequence: *sequence, + } + } + + /// Returns the ack store prefix under which all the packet acks are stored: + /// "acks" + pub fn prefix() -> String { + format!("{EUREKA}/{PACKET_ACK_PREFIX}") + } +} + #[cfg_attr( feature = "parity-scale-codec", derive( @@ -651,6 +842,49 @@ impl ReceiptPath { } } +#[cfg_attr( + feature = "parity-scale-codec", + derive( + parity_scale_codec::Encode, + parity_scale_codec::Decode, + scale_info::TypeInfo + ) +)] +#[cfg_attr( + feature = "borsh", + derive(borsh::BorshSerialize, borsh::BorshDeserialize) +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)] +#[display( + fmt = "{EUREKA}/{PACKET_RECEIPT_PREFIX}/{SOURCE_CLIENT_ON_TARGET}/{source_client_on_target}/{TARGET_CLIENT_ON_SOURCE}/{target_client_on_source}/{SEQUENCE_PREFIX}/{sequence}" +)] +pub struct ReceiptPathV2 { + pub source_client_on_target: ClientId, + pub target_client_on_source: ClientId, + pub sequence: Sequence, +} + +impl ReceiptPathV2 { + pub fn new( + source_client_on_target: &ClientId, + target_client_on_source: &ClientId, + sequence: &Sequence, + ) -> Self { + Self { + source_client_on_target: source_client_on_target.clone(), + target_client_on_source: target_client_on_source.clone(), + sequence: *sequence, + } + } + + /// Returns the receipt store prefix under which all the packet receipts are + /// stored: "receipts" + pub fn prefix() -> String { + format!("{EUREKA}/{PACKET_RECEIPT_PREFIX}") + } +} + #[cfg_attr( feature = "parity-scale-codec", derive( @@ -768,6 +1002,8 @@ impl FromStr for Path { .or_else(|| parse_commitments(&components)) .or_else(|| parse_acks(&components)) .or_else(|| parse_receipts(&components)) + .or_else(|| parse_commit_ack_receipt_seqs_v2(&components)) + .or_else(|| parse_commit_ack_receipt_v2(&components)) .or_else(|| parse_upgrade_client_state(&components)) .or_else(|| parse_upgrade_consensus_state(&components)) .ok_or(PathError::ParseFailure { @@ -1075,6 +1311,95 @@ fn parse_receipts(components: &[&str]) -> Option { ) } +fn parse_commit_ack_receipt_seqs_v2(components: &[&str]) -> Option { + if components.len() != 6 { + return None; + } + + if !(components[0] == EUREKA + && components[2] == SOURCE_CLIENT_ON_TARGET + && components[4] == TARGET_CLIENT_ON_SOURCE) + { + return None; + } + + if !(components[1] == NEXT_SEQ_SEND_PREFIX + || components[1] == NEXT_SEQ_RECV_PREFIX + || components[1] == NEXT_SEQ_ACK_PREFIX) + { + return None; + } + + let source_client_on_target = ClientId::from_str(components[3]).ok()?; + let target_client_on_source = ClientId::from_str(components[5]).ok()?; + + match components[1] { + NEXT_SEQ_SEND_PREFIX => { + Some(SeqSendPathV2::new(&source_client_on_target, &target_client_on_source).into()) + } + NEXT_SEQ_RECV_PREFIX => { + Some(SeqRecvPathV2::new(&source_client_on_target, &target_client_on_source).into()) + } + NEXT_SEQ_ACK_PREFIX => { + Some(SeqAckPathV2::new(&source_client_on_target, &target_client_on_source).into()) + } + _ => None, + } +} + +fn parse_commit_ack_receipt_v2(components: &[&str]) -> Option { + if components.len() != 8 { + return None; + } + + if !(components[0] == EUREKA + && components[2] == SOURCE_CLIENT_ON_TARGET + && components[4] == TARGET_CLIENT_ON_SOURCE + && components[6] == SEQUENCE_PREFIX) + { + return None; + } + + if !(components[1] == PACKET_COMMITMENT_PREFIX + || components[1] == PACKET_ACK_PREFIX + || components[1] == PACKET_RECEIPT_PREFIX) + { + return None; + } + + let source_client_on_target = ClientId::from_str(components[3]).ok()?; + let target_client_on_source = ClientId::from_str(components[5]).ok()?; + let sequence = Sequence::from_str(components[7]).ok()?; + + match components[1] { + PACKET_COMMITMENT_PREFIX => Some( + CommitmentPathV2::new( + &source_client_on_target, + &target_client_on_source, + &sequence, + ) + .into(), + ), + PACKET_ACK_PREFIX => Some( + AckPathV2::new( + &source_client_on_target, + &target_client_on_source, + &sequence, + ) + .into(), + ), + PACKET_RECEIPT_PREFIX => Some( + ReceiptPathV2::new( + &source_client_on_target, + &target_client_on_source, + &sequence, + ) + .into(), + ), + _ => None, + } +} + fn parse_upgrade_client_state(components: &[&str]) -> Option { if components.len() != 3 { return None; diff --git a/ibc-eureka-core/ics25-handler/src/entrypoint.rs b/ibc-eureka-core/ics25-handler/src/entrypoint.rs index 69010d5d6..6044cab33 100644 --- a/ibc-eureka-core/ics25-handler/src/entrypoint.rs +++ b/ibc-eureka-core/ics25-handler/src/entrypoint.rs @@ -4,7 +4,9 @@ use ibc_eureka_core_channel::handler::{ }; use ibc_eureka_core_channel::types::msgs::{packet_msg_to_port_id, PacketMsg}; use ibc_eureka_core_client::context::{ClientExecutionContext, ClientValidationContext}; -use ibc_eureka_core_client::handler::{create_client, update_client, upgrade_client}; +use ibc_eureka_core_client::handler::{ + create_client, provide_counterparty, update_client, upgrade_client, +}; use ibc_eureka_core_client::types::error::ClientError; use ibc_eureka_core_client::types::msgs::{ClientMsg, MsgUpdateOrMisbehaviour}; use ibc_eureka_core_handler_types::error::HandlerError; @@ -60,6 +62,7 @@ where // Recover client messages are not dispatched by ibc-rs as they can only be // authorized via a passing governance proposal } + ClientMsg::ProvideCounterparty(msg) => provide_counterparty::validate(ctx, msg)?, }, MsgEnvelope::Packet(msg) => { let port_id = packet_msg_to_port_id(&msg); @@ -105,6 +108,7 @@ where // Recover client messages are not dispatched by ibc-rs as they can only be // authorized via a passing governance proposal } + ClientMsg::ProvideCounterparty(msg) => provide_counterparty::execute(ctx, msg)?, }, MsgEnvelope::Packet(msg) => { let port_id = packet_msg_to_port_id(&msg);