diff --git a/.changelog/unreleased/breaking-changes/279-remove-legacy-api.md b/.changelog/unreleased/breaking-changes/279-remove-legacy-api.md new file mode 100644 index 000000000..74e43597b --- /dev/null +++ b/.changelog/unreleased/breaking-changes/279-remove-legacy-api.md @@ -0,0 +1,2 @@ +- Remove Reader and Keeper API ([#279](https://github.com/cosmos/ibc- + rs/issues/279)) \ No newline at end of file diff --git a/crates/ibc/src/clients/ics07_tendermint/client_state.rs b/crates/ibc/src/clients/ics07_tendermint/client_state.rs index f6508091b..7293f2e8d 100644 --- a/crates/ibc/src/clients/ics07_tendermint/client_state.rs +++ b/crates/ibc/src/clients/ics07_tendermint/client_state.rs @@ -25,13 +25,11 @@ use crate::clients::ics07_tendermint::misbehaviour::Misbehaviour as TmMisbehavio use crate::core::ics02_client::client_state::{ClientState as Ics2ClientState, UpdatedState}; use crate::core::ics02_client::client_type::ClientType; use crate::core::ics02_client::consensus_state::ConsensusState; -use crate::core::ics02_client::context::ClientReader; use crate::core::ics02_client::error::ClientError; use crate::core::ics02_client::trust_threshold::TrustThreshold; use crate::core::ics03_connection::connection::ConnectionEnd; use crate::core::ics04_channel::channel::ChannelEnd; use crate::core::ics04_channel::commitment::{AcknowledgementCommitment, PacketCommitment}; -use crate::core::ics04_channel::context::ChannelReader; use crate::core::ics04_channel::packet::Sequence; use crate::core::ics23_commitment::commitment::{ CommitmentPrefix, CommitmentProofBytes, CommitmentRoot, @@ -387,236 +385,7 @@ impl Ics2ClientState for ClientState { TmConsensusState::try_from(consensus_state).map(TmConsensusState::into_box) } - fn check_header_and_update_state( - &self, - ctx: &dyn ClientReader, - client_id: ClientId, - header: Any, - ) -> Result { - fn maybe_consensus_state( - ctx: &dyn ClientReader, - client_cons_state_path: &ClientConsensusStatePath, - ) -> Result>, ClientError> { - match ctx.consensus_state(client_cons_state_path) { - Ok(cs) => Ok(Some(cs)), - Err(e) => match e { - ClientError::ConsensusStateNotFound { - client_id: _, - height: _, - } => Ok(None), - _ => Err(e), - }, - } - } - - let client_state = downcast_tm_client_state(self)?.clone(); - let header = TmHeader::try_from(header)?; - - if header.height().revision_number() != client_state.chain_id().version() { - return Err(ClientError::ClientSpecific { - description: Error::MismatchedRevisions { - current_revision: client_state.chain_id().version(), - update_revision: header.height().revision_number(), - } - .to_string(), - }); - } - - // Check if a consensus state is already installed; if so it should - // match the untrusted header. - let header_consensus_state = TmConsensusState::from(header.clone()); - let client_cons_state_path = ClientConsensusStatePath::new(&client_id, &header.height()); - let existing_consensus_state = match maybe_consensus_state(ctx, &client_cons_state_path)? { - Some(cs) => { - let cs = downcast_tm_consensus_state(cs.as_ref())?; - // If this consensus state matches, skip verification - // (optimization) - if cs == header_consensus_state { - // Header is already installed and matches the incoming - // header (already verified) - return Ok(UpdatedState { - client_state: client_state.into_box(), - consensus_state: cs.into_box(), - }); - } - Some(cs) - } - None => None, - }; - - let trusted_client_cons_state_path = - ClientConsensusStatePath::new(&client_id, &header.trusted_height); - let trusted_consensus_state = downcast_tm_consensus_state( - ctx.consensus_state(&trusted_client_cons_state_path)? - .as_ref(), - )?; - - let trusted_state = TrustedBlockState { - chain_id: &self.chain_id.clone().into(), - header_time: trusted_consensus_state.timestamp, - height: header - .trusted_height - .revision_height() - .try_into() - .map_err(|_| ClientError::ClientSpecific { - description: Error::InvalidHeaderHeight { - height: header.trusted_height.revision_height(), - } - .to_string(), - })?, - next_validators: &header.trusted_validator_set, - next_validators_hash: trusted_consensus_state.next_validators_hash, - }; - - let untrusted_state = UntrustedBlockState { - signed_header: &header.signed_header, - validators: &header.validator_set, - // NB: This will skip the - // VerificationPredicates::next_validators_match check for the - // untrusted state. - next_validators: None, - }; - - let options = client_state.as_light_client_options()?; - - self.verifier - .verify( - untrusted_state, - trusted_state, - &options, - ctx.host_timestamp()?.into_tm_time().unwrap(), - ) - .into_result()?; - - // If the header has verified, but its corresponding consensus state - // differs from the existing consensus state for that height, freeze the - // client and return the installed consensus state. - if let Some(cs) = existing_consensus_state { - if cs != header_consensus_state { - return Ok(UpdatedState { - client_state: client_state.with_frozen_height(header.height()).into_box(), - consensus_state: cs.into_box(), - }); - } - } - let client_cons_state_path = ClientConsensusStatePath::new(&client_id, &header.height()); - // Monotonicity checks for timestamps for in-the-middle updates - // (cs-new, cs-next, cs-latest) - if header.height() < client_state.latest_height() { - let maybe_next_cs = ctx - .next_consensus_state(&client_cons_state_path)? - .as_ref() - .map(|cs| downcast_tm_consensus_state(cs.as_ref())) - .transpose()?; - - if let Some(next_cs) = maybe_next_cs { - // New (untrusted) header timestamp cannot occur after next - // consensus state's height - if header.signed_header.header().time > next_cs.timestamp { - return Err(ClientError::ClientSpecific { - description: Error::HeaderTimestampTooHigh { - actual: header.signed_header.header().time.to_string(), - max: next_cs.timestamp.to_string(), - } - .to_string(), - }); - } - } - } - - // (cs-trusted, cs-prev, cs-new) - if header.trusted_height < header.height() { - let maybe_prev_cs = ctx - .prev_consensus_state(&client_cons_state_path)? - .as_ref() - .map(|cs| downcast_tm_consensus_state(cs.as_ref())) - .transpose()?; - - if let Some(prev_cs) = maybe_prev_cs { - // New (untrusted) header timestamp cannot occur before the - // previous consensus state's height - if header.signed_header.header().time < prev_cs.timestamp { - return Err(ClientError::ClientSpecific { - description: Error::HeaderTimestampTooLow { - actual: header.signed_header.header().time.to_string(), - min: prev_cs.timestamp.to_string(), - } - .to_string(), - }); - } - } - } - - Ok(UpdatedState { - client_state: client_state.with_header(header.clone())?.into_box(), - consensus_state: TmConsensusState::from(header).into_box(), - }) - } - fn check_misbehaviour_and_update_state( - &self, - ctx: &dyn ClientReader, - client_id: ClientId, - misbehaviour: Any, - ) -> Result, ClientError> { - let misbehaviour = TmMisbehaviour::try_from(misbehaviour)?; - let header_1 = misbehaviour.header1(); - let header_2 = misbehaviour.header2(); - - if header_1.height() == header_2.height() { - // Fork - if header_1.signed_header.commit.block_id.hash - == header_2.signed_header.commit.block_id.hash - { - return Err(Error::MisbehaviourHeadersBlockHashesEqual.into()); - } - } else { - // BFT time violation - if header_1.signed_header.header.time > header_2.signed_header.header.time { - return Err(Error::MisbehaviourHeadersNotAtSameHeight.into()); - } - } - let client_cons_state_path_1 = - ClientConsensusStatePath::new(&client_id, &header_1.trusted_height); - let consensus_state_1 = { - let cs = ctx.consensus_state(&client_cons_state_path_1)?; - downcast_tm_consensus_state(cs.as_ref()) - }?; - - let client_cons_state_path_2 = - ClientConsensusStatePath::new(&client_id, &header_2.trusted_height); - let consensus_state_2 = { - let cs = ctx.consensus_state(&client_cons_state_path_2)?; - downcast_tm_consensus_state(cs.as_ref()) - }?; - - let chain_id = self - .chain_id - .clone() - .with_version(header_1.height().revision_number()); - if !misbehaviour.chain_id_matches(&chain_id) { - return Err(Error::MisbehaviourHeadersChainIdMismatch { - header_chain_id: header_1.signed_header.header.chain_id.to_string(), - chain_id: self.chain_id.to_string(), - } - .into()); - } - - let current_timestamp = ctx.host_timestamp()?; - - self.check_header_and_validator_set(header_1, &consensus_state_1, current_timestamp)?; - self.check_header_and_validator_set(header_2, &consensus_state_2, current_timestamp)?; - - self.verify_header_commit_against_trusted(header_1, &consensus_state_1)?; - self.verify_header_commit_against_trusted(header_2, &consensus_state_2)?; - - let client_state = downcast_tm_client_state(self)?.clone(); - Ok(client_state - .with_frozen_height(Height::new(0, 1).unwrap()) - .into_box()) - } - - fn new_check_misbehaviour_and_update_state( &self, ctx: &dyn ValidationContext, client_id: ClientId, @@ -685,7 +454,7 @@ impl Ics2ClientState for ClientState { .into_box()) } - fn new_check_header_and_update_state( + fn check_header_and_update_state( &self, ctx: &dyn ValidationContext, client_id: ClientId, @@ -1117,33 +886,9 @@ impl Ics2ClientState for ClientState { ) } - fn new_verify_packet_data( - &self, - ctx: &dyn ValidationContext, - height: Height, - connection_end: &ConnectionEnd, - proof: &CommitmentProofBytes, - root: &CommitmentRoot, - commitment_path: &CommitmentPath, - commitment: PacketCommitment, - ) -> Result<(), ClientError> { - let client_state = downcast_tm_client_state(self)?; - client_state.verify_height(height)?; - new_verify_delay_passed(ctx, height, connection_end)?; - - verify_membership( - client_state, - connection_end.counterparty().prefix(), - proof, - root, - commitment_path.clone(), - commitment.into_vec(), - ) - } - fn verify_packet_data( &self, - ctx: &dyn ChannelReader, + ctx: &dyn ValidationContext, height: Height, connection_end: &ConnectionEnd, proof: &CommitmentProofBytes, @@ -1165,7 +910,7 @@ impl Ics2ClientState for ClientState { ) } - fn new_verify_packet_acknowledgement( + fn verify_packet_acknowledgement( &self, ctx: &dyn ValidationContext, height: Height, @@ -1174,30 +919,6 @@ impl Ics2ClientState for ClientState { root: &CommitmentRoot, ack_path: &AckPath, ack: AcknowledgementCommitment, - ) -> Result<(), ClientError> { - let client_state = downcast_tm_client_state(self)?; - client_state.verify_height(height)?; - new_verify_delay_passed(ctx, height, connection_end)?; - - verify_membership( - client_state, - connection_end.counterparty().prefix(), - proof, - root, - ack_path.clone(), - ack.into_vec(), - ) - } - - fn verify_packet_acknowledgement( - &self, - ctx: &dyn ChannelReader, - height: Height, - connection_end: &ConnectionEnd, - proof: &CommitmentProofBytes, - root: &CommitmentRoot, - ack_path: &AckPath, - ack_commitment: AcknowledgementCommitment, ) -> Result<(), ClientError> { let client_state = downcast_tm_client_state(self)?; client_state.verify_height(height)?; @@ -1209,43 +930,14 @@ impl Ics2ClientState for ClientState { proof, root, ack_path.clone(), - ack_commitment.into_vec(), + ack.into_vec(), ) } #[allow(clippy::too_many_arguments)] - fn new_verify_next_sequence_recv( - &self, - ctx: &dyn ValidationContext, - height: Height, - connection_end: &ConnectionEnd, - proof: &CommitmentProofBytes, - root: &CommitmentRoot, - seq_recv_path: &SeqRecvPath, - sequence: Sequence, - ) -> Result<(), ClientError> { - let client_state = downcast_tm_client_state(self)?; - client_state.verify_height(height)?; - new_verify_delay_passed(ctx, height, connection_end)?; - - let mut seq_bytes = Vec::new(); - u64::from(sequence) - .encode(&mut seq_bytes) - .expect("buffer size too small"); - - verify_membership( - client_state, - connection_end.counterparty().prefix(), - proof, - root, - seq_recv_path.clone(), - seq_bytes, - ) - } - fn verify_next_sequence_recv( &self, - ctx: &dyn ChannelReader, + ctx: &dyn ValidationContext, height: Height, connection_end: &ConnectionEnd, proof: &CommitmentProofBytes, @@ -1273,31 +965,9 @@ impl Ics2ClientState for ClientState { } #[allow(clippy::too_many_arguments)] - fn new_verify_packet_receipt_absence( - &self, - ctx: &dyn ValidationContext, - height: Height, - connection_end: &ConnectionEnd, - proof: &CommitmentProofBytes, - root: &CommitmentRoot, - receipt_path: &ReceiptPath, - ) -> Result<(), ClientError> { - let client_state = downcast_tm_client_state(self)?; - client_state.verify_height(height)?; - new_verify_delay_passed(ctx, height, connection_end)?; - - verify_non_membership( - client_state, - connection_end.counterparty().prefix(), - proof, - root, - receipt_path.clone(), - ) - } - fn verify_packet_receipt_absence( &self, - ctx: &dyn ChannelReader, + ctx: &dyn ValidationContext, height: Height, connection_end: &ConnectionEnd, proof: &CommitmentProofBytes, @@ -1360,46 +1030,6 @@ fn verify_non_membership( } fn verify_delay_passed( - ctx: &dyn ChannelReader, - height: Height, - connection_end: &ConnectionEnd, -) -> Result<(), ClientError> { - let current_timestamp = ctx.host_timestamp().map_err(|e| ClientError::Other { - description: e.to_string(), - })?; - let current_height = ctx.host_height().map_err(|e| ClientError::Other { - description: e.to_string(), - })?; - - let client_id = connection_end.client_id(); - let processed_time = - ctx.client_update_time(client_id, &height) - .map_err(|_| Error::ProcessedTimeNotFound { - client_id: client_id.clone(), - height, - })?; - let processed_height = ctx.client_update_height(client_id, &height).map_err(|_| { - Error::ProcessedHeightNotFound { - client_id: client_id.clone(), - height, - } - })?; - - let delay_period_time = connection_end.delay_period(); - let delay_period_height = ctx.block_delay(&delay_period_time); - - ClientState::verify_delay_passed( - current_timestamp, - current_height, - processed_time, - processed_height, - delay_period_time, - delay_period_height, - ) - .map_err(|e| e.into()) -} - -fn new_verify_delay_passed( ctx: &dyn ValidationContext, height: Height, connection_end: &ConnectionEnd, diff --git a/crates/ibc/src/core/ics02_client/client_state.rs b/crates/ibc/src/core/ics02_client/client_state.rs index 53978de50..f5dbc103b 100644 --- a/crates/ibc/src/core/ics02_client/client_state.rs +++ b/crates/ibc/src/core/ics02_client/client_state.rs @@ -11,7 +11,6 @@ use crate::core::ics02_client::error::ClientError; use crate::core::ics03_connection::connection::ConnectionEnd; use crate::core::ics04_channel::channel::ChannelEnd; use crate::core::ics04_channel::commitment::{AcknowledgementCommitment, PacketCommitment}; -use crate::core::ics04_channel::context::ChannelReader; use crate::core::ics04_channel::packet::Sequence; use crate::core::ics23_commitment::commitment::{ CommitmentPrefix, CommitmentProofBytes, CommitmentRoot, @@ -27,7 +26,6 @@ use crate::prelude::*; use crate::Height; use super::consensus_state::ConsensusState; -use super::context::ClientReader; use crate::core::{ContextError, ValidationContext}; @@ -79,15 +77,6 @@ pub trait ClientState: fn initialise(&self, consensus_state: Any) -> Result, ClientError>; fn check_header_and_update_state( - &self, - ctx: &dyn ClientReader, - client_id: ClientId, - header: Any, - ) -> Result; - - /// XXX: temporary solution until we get rid of `ClientReader` - - fn new_check_header_and_update_state( &self, ctx: &dyn ValidationContext, client_id: ClientId, @@ -95,15 +84,6 @@ pub trait ClientState: ) -> Result; fn check_misbehaviour_and_update_state( - &self, - ctx: &dyn ClientReader, - client_id: ClientId, - misbehaviour: Any, - ) -> Result, ClientError>; - - /// XXX: temporary solution until we get rid of `ClientReader` - - fn new_check_misbehaviour_and_update_state( &self, ctx: &dyn ValidationContext, client_id: ClientId, @@ -186,25 +166,11 @@ pub trait ClientState: expected_client_state: Any, ) -> Result<(), ClientError>; - /// Verify a `proof` that a packet has been committed. - - #[allow(clippy::too_many_arguments)] - fn new_verify_packet_data( - &self, - ctx: &dyn ValidationContext, - height: Height, - connection_end: &ConnectionEnd, - proof: &CommitmentProofBytes, - root: &CommitmentRoot, - commitment_path: &CommitmentPath, - commitment: PacketCommitment, - ) -> Result<(), ClientError>; - /// Verify a `proof` that a packet has been committed. #[allow(clippy::too_many_arguments)] fn verify_packet_data( &self, - ctx: &dyn ChannelReader, + ctx: &dyn ValidationContext, height: Height, connection_end: &ConnectionEnd, proof: &CommitmentProofBytes, @@ -213,25 +179,11 @@ pub trait ClientState: commitment: PacketCommitment, ) -> Result<(), ClientError>; - /// Verify a `proof` that a packet has been committed. - - #[allow(clippy::too_many_arguments)] - fn new_verify_packet_acknowledgement( - &self, - ctx: &dyn ValidationContext, - height: Height, - connection_end: &ConnectionEnd, - proof: &CommitmentProofBytes, - root: &CommitmentRoot, - ack_path: &AckPath, - ack: AcknowledgementCommitment, - ) -> Result<(), ClientError>; - /// Verify a `proof` that a packet has been committed. #[allow(clippy::too_many_arguments)] fn verify_packet_acknowledgement( &self, - ctx: &dyn ChannelReader, + ctx: &dyn ValidationContext, height: Height, connection_end: &ConnectionEnd, proof: &CommitmentProofBytes, @@ -240,25 +192,11 @@ pub trait ClientState: ack: AcknowledgementCommitment, ) -> Result<(), ClientError>; - /// Verify a `proof` that of the next_seq_received. - - #[allow(clippy::too_many_arguments)] - fn new_verify_next_sequence_recv( - &self, - ctx: &dyn ValidationContext, - height: Height, - connection_end: &ConnectionEnd, - proof: &CommitmentProofBytes, - root: &CommitmentRoot, - seq_recv_path: &SeqRecvPath, - sequence: Sequence, - ) -> Result<(), ClientError>; - /// Verify a `proof` that of the next_seq_received. #[allow(clippy::too_many_arguments)] fn verify_next_sequence_recv( &self, - ctx: &dyn ChannelReader, + ctx: &dyn ValidationContext, height: Height, connection_end: &ConnectionEnd, proof: &CommitmentProofBytes, @@ -267,21 +205,10 @@ pub trait ClientState: sequence: Sequence, ) -> Result<(), ClientError>; - /// Verify a `proof` that a packet has not been received. - fn new_verify_packet_receipt_absence( - &self, - ctx: &dyn ValidationContext, - height: Height, - connection_end: &ConnectionEnd, - proof: &CommitmentProofBytes, - root: &CommitmentRoot, - receipt_path: &ReceiptPath, - ) -> Result<(), ClientError>; - /// Verify a `proof` that a packet has not been received. fn verify_packet_receipt_absence( &self, - ctx: &dyn ChannelReader, + ctx: &dyn ValidationContext, height: Height, connection_end: &ConnectionEnd, proof: &CommitmentProofBytes, diff --git a/crates/ibc/src/core/ics02_client/context.rs b/crates/ibc/src/core/ics02_client/context.rs deleted file mode 100644 index 434d3ae3e..000000000 --- a/crates/ibc/src/core/ics02_client/context.rs +++ /dev/null @@ -1,179 +0,0 @@ -//! ICS2 (client) context. The two traits `ClientReader` and `ClientKeeper` define the interface -//! that any host chain must implement to be able to process any `ClientMsg`. See -//! "ADR 003: IBC protocol implementation" for more details. - -use alloc::boxed::Box; - -use ibc_proto::google::protobuf::Any; - -use crate::core::ics02_client::client_state::ClientState; -use crate::core::ics02_client::client_type::ClientType; -use crate::core::ics02_client::consensus_state::ConsensusState; -use crate::core::ics02_client::error::ClientError; -use crate::core::ics02_client::handler::ClientResult::{self, Create, Update, Upgrade}; -use crate::core::ics24_host::identifier::ClientId; -use crate::core::ics24_host::path::ClientConsensusStatePath; -use crate::timestamp::Timestamp; -use crate::Height; - -/// Defines the read-only part of ICS2 (client functions) context. -pub trait ClientReader { - /// Returns the ClientType for the given identifier `client_id`. - fn client_type(&self, client_id: &ClientId) -> Result; - - /// Returns the ClientState for the given identifier `client_id`. - fn client_state(&self, client_id: &ClientId) -> Result, ClientError>; - - /// Tries to decode the given `client_state` into a concrete light client state. - fn decode_client_state(&self, client_state: Any) -> Result, ClientError>; - - /// Retrieve the consensus state for the given client ID at the specified - /// height. - /// - /// Returns an error if no such state exists. - fn consensus_state( - &self, - client_cons_state_path: &ClientConsensusStatePath, - ) -> Result, ClientError>; - - /// Search for the lowest consensus state higher than `height`. - fn next_consensus_state( - &self, - next_client_cons_state_path: &ClientConsensusStatePath, - ) -> Result>, ClientError>; - - /// Search for the highest consensus state lower than `height`. - fn prev_consensus_state( - &self, - prev_client_cons_state_path: &ClientConsensusStatePath, - ) -> Result>, ClientError>; - - /// Returns the current height of the local chain. - fn host_height(&self) -> Result; - - /// Returns the current timestamp of the local chain. - fn host_timestamp(&self) -> Result { - let pending_consensus_state = self - .pending_host_consensus_state() - .expect("host must have pending consensus state"); - Ok(pending_consensus_state.timestamp()) - } - - /// Returns the `ConsensusState` of the host (local) chain at a specific height. - fn host_consensus_state(&self, height: &Height) - -> Result, ClientError>; - - /// Returns the pending `ConsensusState` of the host (local) chain. - fn pending_host_consensus_state(&self) -> Result, ClientError>; - - /// Returns a natural number, counting how many clients have been created thus far. - /// The value of this counter should increase only via method `ClientKeeper::increase_client_counter`. - fn client_counter(&self) -> Result; -} - -/// Defines the write-only part of ICS2 (client functions) context. -pub trait ClientKeeper { - fn store_client_result(&mut self, handler_res: ClientResult) -> Result<(), ClientError> { - match handler_res { - Create(res) => { - self.store_client_type(res.client_id.clone(), res.client_type)?; - self.store_client_state(res.client_id.clone(), res.client_state.clone())?; - self.store_consensus_state( - res.client_id.clone(), - res.client_state.latest_height(), - res.consensus_state, - )?; - self.increase_client_counter(); - self.store_update_time( - res.client_id.clone(), - res.client_state.latest_height(), - res.processed_time, - )?; - self.store_update_height( - res.client_id, - res.client_state.latest_height(), - res.processed_height, - )?; - Ok(()) - } - Update(res) => { - self.store_client_state(res.client_id.clone(), res.client_state.clone())?; - self.store_consensus_state( - res.client_id.clone(), - res.client_state.latest_height(), - res.consensus_state, - )?; - self.store_update_time( - res.client_id.clone(), - res.client_state.latest_height(), - res.processed_time, - )?; - self.store_update_height( - res.client_id, - res.client_state.latest_height(), - res.processed_height, - )?; - Ok(()) - } - Upgrade(res) => { - self.store_client_state(res.client_id.clone(), res.client_state.clone())?; - self.store_consensus_state( - res.client_id.clone(), - res.client_state.latest_height(), - res.consensus_state, - )?; - Ok(()) - } - ClientResult::Misbehaviour(res) => { - self.store_client_state(res.client_id, res.client_state) - } - } - } - - /// Called upon successful client creation - fn store_client_type( - &mut self, - client_id: ClientId, - client_type: ClientType, - ) -> Result<(), ClientError>; - - /// Called upon successful client creation and update - fn store_client_state( - &mut self, - client_id: ClientId, - client_state: Box, - ) -> Result<(), ClientError>; - - /// Called upon successful client creation and update - fn store_consensus_state( - &mut self, - client_id: ClientId, - height: Height, - consensus_state: Box, - ) -> Result<(), ClientError>; - - /// Called upon client creation. - /// Increases the counter which keeps track of how many clients have been created. - /// Should never fail. - fn increase_client_counter(&mut self); - - /// Called upon successful client update. - /// Implementations are expected to use this to record the specified time as the time at which - /// this update (or header) was processed. - fn store_update_time( - &mut self, - client_id: ClientId, - height: Height, - timestamp: Timestamp, - ) -> Result<(), ClientError>; - - /// Called upon successful client update. - /// Implementations are expected to use this to record the specified height as the height at - /// at which this update (or header) was processed. - fn store_update_height( - &mut self, - client_id: ClientId, - height: Height, - host_height: Height, - ) -> Result<(), ClientError>; -} diff --git a/crates/ibc/src/core/ics02_client/handler.rs b/crates/ibc/src/core/ics02_client/handler.rs index 2bb86f7b7..d9a165dfd 100644 --- a/crates/ibc/src/core/ics02_client/handler.rs +++ b/crates/ibc/src/core/ics02_client/handler.rs @@ -1,35 +1,6 @@ //! This module implements the processing logic for ICS2 (client abstractions and functions) msgs. -use crate::core::ics02_client::context::ClientReader; -use crate::core::ics02_client::error::ClientError; -use crate::core::ics02_client::msgs::ClientMsg; -use crate::handler::HandlerOutput; - pub mod create_client; pub mod misbehaviour; pub mod update_client; pub mod upgrade_client; - -#[derive(Clone, Debug, PartialEq)] -pub enum ClientResult { - Create(create_client::CreateClientResult), - Update(update_client::UpdateClientResult), - Upgrade(upgrade_client::UpgradeClientResult), - Misbehaviour(misbehaviour::MisbehaviourResult), -} - -/// General entry point for processing any message related to ICS2 (client functions) protocols. -pub(crate) fn dispatch( - ctx: &Ctx, - msg: ClientMsg, -) -> Result, ClientError> -where - Ctx: ClientReader, -{ - match msg { - ClientMsg::CreateClient(msg) => create_client::process(ctx, msg), - ClientMsg::UpdateClient(msg) => update_client::process(ctx, msg), - ClientMsg::UpgradeClient(msg) => upgrade_client::process(ctx, msg), - ClientMsg::Misbehaviour(msg) => misbehaviour::process(ctx, msg), - } -} diff --git a/crates/ibc/src/core/ics02_client/handler/create_client.rs b/crates/ibc/src/core/ics02_client/handler/create_client.rs index 2dab2a709..33073e102 100644 --- a/crates/ibc/src/core/ics02_client/handler/create_client.rs +++ b/crates/ibc/src/core/ics02_client/handler/create_client.rs @@ -14,30 +14,11 @@ use crate::core::ExecutionContext; use crate::core::ValidationContext; -use crate::core::ics02_client::client_state::ClientState; -use crate::core::ics02_client::client_type::ClientType; -use crate::core::ics02_client::consensus_state::ConsensusState; -use crate::core::ics02_client::context::ClientReader; use crate::core::ics02_client::error::ClientError; use crate::core::ics02_client::events::CreateClient; -use crate::core::ics02_client::handler::ClientResult; -use crate::core::ics02_client::height::Height; use crate::core::ics02_client::msgs::create_client::MsgCreateClient; use crate::core::ics24_host::identifier::ClientId; use crate::events::IbcEvent; -use crate::handler::{HandlerOutput, HandlerResult}; -use crate::timestamp::Timestamp; - -/// The result following the successful processing of a `MsgCreateClient` message. -#[derive(Clone, Debug, PartialEq)] -pub struct CreateClientResult { - pub client_id: ClientId, - pub client_type: ClientType, - pub client_state: Box, - pub consensus_state: Box, - pub processed_time: Timestamp, - pub processed_height: Height, -} pub(crate) fn validate(ctx: &Ctx, msg: MsgCreateClient) -> Result<(), ContextError> where @@ -124,59 +105,6 @@ where Ok(()) } -pub(crate) fn process( - ctx: &dyn ClientReader, - msg: MsgCreateClient, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - let MsgCreateClient { - client_state, - consensus_state, - signer: _, - } = msg; - - // Construct this client's identifier - let id_counter = ctx.client_counter()?; - - let client_state = ctx.decode_client_state(client_state)?; - - let client_type = client_state.client_type(); - - let client_id = ClientId::new(client_type.clone(), id_counter).map_err(|e| { - ClientError::ClientIdentifierConstructor { - client_type: client_state.client_type(), - counter: id_counter, - validation_error: e, - } - })?; - - let consensus_state = client_state.initialise(consensus_state)?; - - let consensus_height = client_state.latest_height(); - - let result = ClientResult::Create(CreateClientResult { - client_id: client_id.clone(), - client_type: client_type.clone(), - client_state, - consensus_state, - processed_time: ctx.host_timestamp()?, - processed_height: ctx.host_height()?, - }); - - output.emit(IbcEvent::CreateClient(CreateClient::new( - client_id.clone(), - client_type, - consensus_height, - ))); - - output.log(format!( - "success: generated new client identifier: {client_id}" - )); - - Ok(output.with_result(result)) -} - #[cfg(test)] mod tests { use crate::clients::ics07_tendermint::client_type as tm_client_type; diff --git a/crates/ibc/src/core/ics02_client/handler/misbehaviour.rs b/crates/ibc/src/core/ics02_client/handler/misbehaviour.rs index 93f7acbfe..12bd600ae 100644 --- a/crates/ibc/src/core/ics02_client/handler/misbehaviour.rs +++ b/crates/ibc/src/core/ics02_client/handler/misbehaviour.rs @@ -2,27 +2,15 @@ //! use crate::prelude::*; -use crate::core::ics02_client::client_state::ClientState; -use crate::core::ics02_client::context::ClientReader; use crate::core::ics02_client::error::ClientError; use crate::core::ics02_client::events::ClientMisbehaviour; -use crate::core::ics02_client::handler::ClientResult; use crate::core::ics02_client::msgs::misbehaviour::MsgSubmitMisbehaviour; -use crate::core::ics24_host::identifier::ClientId; use crate::events::IbcEvent; -use crate::handler::{HandlerOutput, HandlerResult}; use crate::core::ics24_host::path::ClientStatePath; use crate::core::{ContextError, ExecutionContext, ValidationContext}; -/// The result following the successful processing of a `MsgSubmitMisbehaviour` message. -#[derive(Clone, Debug, PartialEq)] -pub struct MisbehaviourResult { - pub client_id: ClientId, - pub client_state: Box, -} - pub(crate) fn validate(ctx: &Ctx, msg: MsgSubmitMisbehaviour) -> Result<(), ContextError> where Ctx: ValidationContext, @@ -41,7 +29,7 @@ where } let _ = client_state - .new_check_misbehaviour_and_update_state(ctx, client_id.clone(), misbehaviour) + .check_misbehaviour_and_update_state(ctx, client_id.clone(), misbehaviour) .map_err(|e| ClientError::MisbehaviourHandlingFailure { reason: e.to_string(), })?; @@ -67,7 +55,7 @@ where } let client_state = client_state - .new_check_misbehaviour_and_update_state(ctx, client_id.clone(), misbehaviour) + .check_misbehaviour_and_update_state(ctx, client_id.clone(), misbehaviour) .map_err(|e| ClientError::MisbehaviourHandlingFailure { reason: e.to_string(), })?; @@ -80,44 +68,6 @@ where ctx.store_client_state(ClientStatePath::new(&client_id), client_state) } -pub(crate) fn process( - ctx: &dyn ClientReader, - msg: MsgSubmitMisbehaviour, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - let MsgSubmitMisbehaviour { - client_id, - misbehaviour, - signer: _, - } = msg; - - // Read client state from the host chain store. - let client_state = ctx.client_state(&client_id)?; - - if client_state.is_frozen() { - return Err(ClientError::ClientFrozen { client_id }); - } - - let client_state = client_state - .check_misbehaviour_and_update_state(ctx, client_id.clone(), misbehaviour) - .map_err(|e| ClientError::MisbehaviourHandlingFailure { - reason: e.to_string(), - })?; - - output.emit(IbcEvent::ClientMisbehaviour(ClientMisbehaviour::new( - client_id.clone(), - client_state.client_type(), - ))); - - let result = ClientResult::Misbehaviour(MisbehaviourResult { - client_id, - client_state, - }); - - Ok(output.with_result(result)) -} - #[cfg(test)] mod tests { use core::str::FromStr; diff --git a/crates/ibc/src/core/ics02_client/handler/update_client.rs b/crates/ibc/src/core/ics02_client/handler/update_client.rs index 964427b55..b6d05f43c 100644 --- a/crates/ibc/src/core/ics02_client/handler/update_client.rs +++ b/crates/ibc/src/core/ics02_client/handler/update_client.rs @@ -4,18 +4,11 @@ use tracing::debug; use crate::prelude::*; -use crate::core::ics02_client::client_state::{ClientState, UpdatedState}; -use crate::core::ics02_client::consensus_state::ConsensusState; -use crate::core::ics02_client::context::ClientReader; +use crate::core::ics02_client::client_state::UpdatedState; use crate::core::ics02_client::error::ClientError; use crate::core::ics02_client::events::UpdateClient; -use crate::core::ics02_client::handler::ClientResult; -use crate::core::ics02_client::height::Height; use crate::core::ics02_client::msgs::update_client::MsgUpdateClient; -use crate::core::ics24_host::identifier::ClientId; use crate::events::IbcEvent; -use crate::handler::{HandlerOutput, HandlerResult}; -use crate::timestamp::Timestamp; use crate::core::context::ContextError; @@ -23,16 +16,6 @@ use crate::core::ics24_host::path::{ClientConsensusStatePath, ClientStatePath}; use crate::core::{ExecutionContext, ValidationContext}; -/// The result following the successful processing of a `MsgUpdateAnyClient` message. -#[derive(Clone, Debug, PartialEq)] -pub struct UpdateClientResult { - pub client_id: ClientId, - pub client_state: Box, - pub consensus_state: Box, - pub processed_time: Timestamp, - pub processed_height: Height, -} - pub(crate) fn validate(ctx: &Ctx, msg: MsgUpdateClient) -> Result<(), ContextError> where Ctx: ValidationContext, @@ -80,7 +63,7 @@ where } let _ = client_state - .new_check_header_and_update_state(ctx, client_id.clone(), header) + .check_header_and_update_state(ctx, client_id.clone(), header) .map_err(|e| ClientError::HeaderVerificationFailure { reason: e.to_string(), })?; @@ -106,7 +89,7 @@ where client_state, consensus_state, } = client_state - .new_check_header_and_update_state(ctx, client_id.clone(), header.clone()) + .check_header_and_update_state(ctx, client_id.clone(), header.clone()) .map_err(|e| ClientError::HeaderVerificationFailure { reason: e.to_string(), })?; @@ -142,86 +125,6 @@ where Ok(()) } -pub(crate) fn process( - ctx: &Ctx, - msg: MsgUpdateClient, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - let MsgUpdateClient { - client_id, - header, - signer: _, - } = msg; - - // Read client type from the host chain store. The client should already exist. - // Read client state from the host chain store. - let client_state = ctx.client_state(&client_id)?; - - if client_state.is_frozen() { - return Err(ClientError::ClientFrozen { client_id }); - } - - // Read consensus state from the host chain store. - let client_cons_state_path = - ClientConsensusStatePath::new(&client_id, &client_state.latest_height()); - let latest_consensus_state = ClientReader::consensus_state(ctx, &client_cons_state_path) - .map_err(|_| ClientError::ConsensusStateNotFound { - client_id: client_id.clone(), - height: client_state.latest_height(), - })?; - - debug!("latest consensus state: {:?}", latest_consensus_state); - - let now = ClientReader::host_timestamp(ctx)?; - let duration = now - .duration_since(&latest_consensus_state.timestamp()) - .ok_or_else(|| ClientError::InvalidConsensusStateTimestamp { - time1: latest_consensus_state.timestamp(), - time2: now, - })?; - - if client_state.expired(duration) { - return Err(ClientError::HeaderNotWithinTrustPeriod { - latest_time: latest_consensus_state.timestamp(), - update_time: now, - }); - } - - // Use client_state to validate the new header against the latest consensus_state. - // This function will return the new client_state (its latest_height changed) and a - // consensus_state obtained from header. These will be later persisted by the keeper. - let UpdatedState { - client_state, - consensus_state, - } = client_state - .check_header_and_update_state(ctx, client_id.clone(), header.clone()) - .map_err(|e| ClientError::HeaderVerificationFailure { - reason: e.to_string(), - })?; - - let client_type = client_state.client_type(); - let consensus_height = client_state.latest_height(); - - let result = ClientResult::Update(UpdateClientResult { - client_id: client_id.clone(), - client_state, - consensus_state, - processed_time: ClientReader::host_timestamp(ctx)?, - processed_height: ctx.host_height()?, - }); - - output.emit(IbcEvent::UpdateClient(UpdateClient::new( - client_id, - client_type, - consensus_height, - vec![consensus_height], - header, - ))); - - Ok(output.with_result(result)) -} - #[cfg(test)] mod tests { use core::str::FromStr; diff --git a/crates/ibc/src/core/ics02_client/handler/upgrade_client.rs b/crates/ibc/src/core/ics02_client/handler/upgrade_client.rs index 40245bca7..92d039184 100644 --- a/crates/ibc/src/core/ics02_client/handler/upgrade_client.rs +++ b/crates/ibc/src/core/ics02_client/handler/upgrade_client.rs @@ -2,16 +2,11 @@ //! use crate::prelude::*; -use crate::core::ics02_client::client_state::{ClientState, UpdatedState}; -use crate::core::ics02_client::consensus_state::ConsensusState; -use crate::core::ics02_client::context::ClientReader; +use crate::core::ics02_client::client_state::UpdatedState; use crate::core::ics02_client::error::ClientError; use crate::core::ics02_client::events::UpgradeClient; -use crate::core::ics02_client::handler::ClientResult; use crate::core::ics02_client::msgs::upgrade_client::MsgUpgradeClient; -use crate::core::ics24_host::identifier::ClientId; use crate::events::IbcEvent; -use crate::handler::{HandlerOutput, HandlerResult}; use crate::core::context::ContextError; @@ -19,14 +14,6 @@ use crate::core::ics24_host::path::{ClientConsensusStatePath, ClientStatePath}; use crate::core::{ExecutionContext, ValidationContext}; -/// The result following the successful processing of a `MsgUpgradeAnyClient` message. -#[derive(Clone, Debug, PartialEq)] -pub struct UpgradeClientResult { - pub client_id: ClientId, - pub client_state: Box, - pub consensus_state: Box, -} - pub(crate) fn validate(ctx: &Ctx, msg: MsgUpgradeClient) -> Result<(), ContextError> where Ctx: ValidationContext, @@ -119,85 +106,6 @@ where Ok(()) } -pub(crate) fn process( - ctx: &dyn ClientReader, - msg: MsgUpgradeClient, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - let MsgUpgradeClient { client_id, .. } = msg; - - // Temporary has been disabled until we have a better understanding of some design implications - if !cfg!(feature = "upgrade_client") { - return Err(ClientError::Other { - description: "upgrade_client feature is not supported".to_string(), - }); - } - - // Read the current latest client state from the host chain store. - let old_client_state = ctx.client_state(&client_id)?; - - // Check if the client is frozen. - if old_client_state.is_frozen() { - return Err(ClientError::ClientFrozen { client_id }); - } - - // Read the latest consensus state from the host chain store. - let old_client_cons_state_path = - ClientConsensusStatePath::new(&client_id, &old_client_state.latest_height()); - let old_consensus_state = ctx - .consensus_state(&old_client_cons_state_path) - .map_err(|_| ClientError::ConsensusStateNotFound { - client_id: client_id.clone(), - height: old_client_state.latest_height(), - })?; - - let now = ctx.host_timestamp()?; - let duration = now - .duration_since(&old_consensus_state.timestamp()) - .ok_or_else(|| ClientError::InvalidConsensusStateTimestamp { - time1: old_consensus_state.timestamp(), - time2: now, - })?; - - // Check if the latest consensus state is within the trust period. - if old_client_state.expired(duration) { - return Err(ClientError::HeaderNotWithinTrustPeriod { - latest_time: old_consensus_state.timestamp(), - update_time: now, - }); - }; - - // Validate the upgraded client state and consensus state and verify proofs against the root - old_client_state.verify_upgrade_client( - msg.client_state.clone(), - msg.consensus_state.clone(), - msg.proof_upgrade_client.clone(), - msg.proof_upgrade_consensus_state.clone(), - old_consensus_state.root(), - )?; - - // Create updated new client state and consensus state - let UpdatedState { - client_state, - consensus_state, - } = old_client_state - .update_state_with_upgrade_client(msg.client_state.clone(), msg.consensus_state)?; - - let result = ClientResult::Upgrade(UpgradeClientResult { - client_id: client_id.clone(), - client_state: client_state.clone(), - consensus_state, - }); - - output.emit(IbcEvent::UpgradeClient(UpgradeClient::new( - client_id, - client_state.client_type(), - client_state.latest_height(), - ))); - - Ok(output.with_result(result)) -} - #[cfg(feature = "upgrade_client")] #[cfg(test)] mod tests { diff --git a/crates/ibc/src/core/ics02_client/mod.rs b/crates/ibc/src/core/ics02_client/mod.rs index 3e9dec583..6033015f2 100644 --- a/crates/ibc/src/core/ics02_client/mod.rs +++ b/crates/ibc/src/core/ics02_client/mod.rs @@ -3,7 +3,6 @@ pub mod client_state; pub mod client_type; pub mod consensus_state; -pub mod context; pub mod error; pub mod events; pub mod handler; diff --git a/crates/ibc/src/core/ics03_connection/context.rs b/crates/ibc/src/core/ics03_connection/context.rs deleted file mode 100644 index da56af66c..000000000 --- a/crates/ibc/src/core/ics03_connection/context.rs +++ /dev/null @@ -1,131 +0,0 @@ -//! ICS3 (connection) context. The two traits `ConnectionReader` and `ConnectionKeeper` define -//! the interface that any host chain must implement to be able to process any `ConnectionMsg`. -//! See "ADR 003: IBC protocol implementation" for more details. - -use crate::core::ics02_client::client_state::ClientState; -use crate::core::ics02_client::consensus_state::ConsensusState; -use crate::core::ics03_connection::connection::ConnectionEnd; -use crate::core::ics03_connection::error::ConnectionError; -use crate::core::ics03_connection::handler::ConnectionResult; -use crate::core::ics03_connection::version::{get_compatible_versions, pick_version, Version}; -use crate::core::ics23_commitment::commitment::CommitmentPrefix; -use crate::core::ics24_host::identifier::{ClientId, ConnectionId}; -use crate::core::ics24_host::path::ClientConsensusStatePath; -use crate::prelude::*; -use crate::Height; -use ibc_proto::google::protobuf::Any; - -use super::handler::ConnectionIdState; - -/// A context supplying all the necessary read-only dependencies for processing any `ConnectionMsg`. -pub trait ConnectionReader { - /// Returns the ConnectionEnd for the given identifier `conn_id`. - fn connection_end(&self, conn_id: &ConnectionId) -> Result; - - /// Returns the ClientState for the given identifier `client_id`. - fn client_state(&self, client_id: &ClientId) -> Result, ConnectionError>; - - /// Tries to decode the given `client_state` into a concrete light client state. - fn decode_client_state( - &self, - client_state: Any, - ) -> Result, ConnectionError>; - - /// Returns the current height of the local chain. - fn host_current_height(&self) -> Result; - - #[deprecated(since = "0.20.0")] - /// Returns the oldest height available on the local chain. - fn host_oldest_height(&self) -> Result; - - /// Returns the prefix that the local chain uses in the KV store. - fn commitment_prefix(&self) -> CommitmentPrefix; - - /// Returns the ConsensusState that the given client stores at a specific height. - fn client_consensus_state( - &self, - client_cons_state_path: &ClientConsensusStatePath, - ) -> Result, ConnectionError>; - - /// Returns the ConsensusState of the host (local) chain at a specific height. - fn host_consensus_state( - &self, - height: &Height, - ) -> Result, ConnectionError>; - - /// Function required by ICS 03. Returns the list of all possible versions that the connection - /// handshake protocol supports. - fn get_compatible_versions(&self) -> Vec { - get_compatible_versions() - } - - /// Function required by ICS 03. Returns one version out of the supplied list of versions, which the - /// connection handshake protocol prefers. - fn pick_version( - &self, - supported_versions: &[Version], - counterparty_candidate_versions: &[Version], - ) -> Result { - pick_version(supported_versions, counterparty_candidate_versions) - } - - /// Returns a counter on how many connections have been created thus far. - /// The value of this counter should increase only via method - /// `ConnectionKeeper::increase_connection_counter`. - fn connection_counter(&self) -> Result; - - /// Validates the client state of the host chain that is stored on the - /// counterparty chain. - /// - /// For more information on the specific requirements for validating the - /// client state of a host chain, please refer to the [ICS24 host - /// requirements](https://github.com/cosmos/ibc/tree/main/spec/core/ics-024-host-requirements#client-state-validation) - /// - /// Additionally, implementations specific to individual chains can be found - /// in the [hosts](crate::hosts) module. - fn validate_self_client( - &self, - client_state_of_host_on_counterparty: Any, - ) -> Result<(), ConnectionError>; -} - -/// A context supplying all the necessary write-only dependencies (i.e., storage writing facility) -/// for processing any `ConnectionMsg`. -pub trait ConnectionKeeper { - fn store_connection_result(&mut self, result: ConnectionResult) -> Result<(), ConnectionError> { - self.store_connection(result.connection_id.clone(), result.connection_end.clone())?; - - // If we generated an identifier, increase the counter & associate this new identifier - // with the client id. - if matches!(result.connection_id_state, ConnectionIdState::Generated) { - self.increase_connection_counter(); - - // Also associate the connection end to its client identifier. - self.store_connection_to_client( - result.connection_id.clone(), - result.connection_end.client_id().clone(), - )?; - } - - Ok(()) - } - - /// Stores the given connection_end at a path associated with the connection_id. - fn store_connection( - &mut self, - connection_id: ConnectionId, - connection_end: ConnectionEnd, - ) -> Result<(), ConnectionError>; - - /// Stores the given connection_id at a path associated with the client_id. - fn store_connection_to_client( - &mut self, - connection_id: ConnectionId, - client_id: ClientId, - ) -> Result<(), ConnectionError>; - - /// Called upon connection identifier creation (Init or Try process). - /// Increases the counter which keeps track of how many connections have been created. - /// Should never fail. - fn increase_connection_counter(&mut self); -} diff --git a/crates/ibc/src/core/ics03_connection/handler.rs b/crates/ibc/src/core/ics03_connection/handler.rs index 597b6ccd1..8946943c6 100644 --- a/crates/ibc/src/core/ics03_connection/handler.rs +++ b/crates/ibc/src/core/ics03_connection/handler.rs @@ -1,60 +1,11 @@ //! This module implements the processing logic for ICS3 (connection open //! handshake) messages. -use crate::core::ics03_connection::connection::ConnectionEnd; -use crate::core::ics03_connection::context::ConnectionReader; -use crate::core::ics03_connection::error::ConnectionError; -use crate::core::ics03_connection::msgs::ConnectionMsg; -use crate::core::ics24_host::identifier::ConnectionId; -use crate::handler::HandlerOutput; - pub mod conn_open_ack; pub mod conn_open_confirm; pub mod conn_open_init; pub mod conn_open_try; -/// Defines the possible states of a connection identifier in a `ConnectionResult`. -#[derive(Clone, Debug)] -pub enum ConnectionIdState { - /// Specifies that the handler allocated a new connection identifier. This happens during the - /// processing of either the `MsgConnectionOpenInit` or `MsgConnectionOpenTry` message. - Generated, - - /// Specifies that the handler reused a previously-allocated connection identifier. - Reused, -} - -#[derive(Clone, Debug)] -pub struct ConnectionResult { - /// The identifier for the connection which the handler processed. Typically this represents the - /// newly-generated connection id (e.g., when processing `MsgConnectionOpenInit`) or - /// an existing connection id (e.g., for `MsgConnectionOpenAck`). - pub connection_id: ConnectionId, - - /// The state of the connection identifier (whether it was newly-generated or not). - pub connection_id_state: ConnectionIdState, - - /// The connection end, which the handler produced as a result of processing the message. - pub connection_end: ConnectionEnd, -} - -/// General entry point for processing any type of message related to the ICS3 connection open -/// handshake protocol. -pub(crate) fn dispatch( - ctx: &Ctx, - msg: ConnectionMsg, -) -> Result, ConnectionError> -where - Ctx: ConnectionReader, -{ - match msg { - ConnectionMsg::OpenInit(msg) => conn_open_init::process(ctx, msg), - ConnectionMsg::OpenTry(msg) => conn_open_try::process(ctx, msg), - ConnectionMsg::OpenAck(msg) => conn_open_ack::process(ctx, msg), - ConnectionMsg::OpenConfirm(msg) => conn_open_confirm::process(ctx, msg), - } -} - #[cfg(test)] pub mod test_util { use core::fmt::Debug; diff --git a/crates/ibc/src/core/ics03_connection/handler/conn_open_ack.rs b/crates/ibc/src/core/ics03_connection/handler/conn_open_ack.rs index cedb0d5aa..2b8ecec1f 100644 --- a/crates/ibc/src/core/ics03_connection/handler/conn_open_ack.rs +++ b/crates/ibc/src/core/ics03_connection/handler/conn_open_ack.rs @@ -2,13 +2,10 @@ use crate::prelude::*; use crate::core::ics03_connection::connection::{ConnectionEnd, Counterparty, State}; -use crate::core::ics03_connection::context::ConnectionReader; use crate::core::ics03_connection::error::ConnectionError; use crate::core::ics03_connection::events::OpenAck; -use crate::core::ics03_connection::handler::ConnectionResult; use crate::core::ics03_connection::msgs::conn_open_ack::MsgConnectionOpenAck; use crate::events::IbcEvent; -use crate::handler::{HandlerOutput, HandlerResult}; use crate::core::context::ContextError; @@ -18,8 +15,6 @@ use crate::core::ics24_host::path::{ClientConsensusStatePath, ClientStatePath, C use crate::core::{ExecutionContext, ValidationContext}; -use super::ConnectionIdState; - pub(crate) fn validate(ctx_a: &Ctx, msg: MsgConnectionOpenAck) -> Result<(), ContextError> where Ctx: ValidationContext, @@ -209,137 +204,6 @@ impl LocalVars { } } -/// Per our convention, this message is processed on chain A. -pub(crate) fn process( - ctx_a: &dyn ConnectionReader, - msg: MsgConnectionOpenAck, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - if msg.consensus_height_of_a_on_b > ctx_a.host_current_height()? { - return Err(ConnectionError::InvalidConsensusHeight { - target_height: msg.consensus_height_of_a_on_b, - current_height: ctx_a.host_current_height()?, - }); - } - - ctx_a.validate_self_client(msg.client_state_of_a_on_b.clone())?; - - let conn_end_on_a = ctx_a.connection_end(&msg.conn_id_on_a)?; - if !(conn_end_on_a.state_matches(&State::Init) - && conn_end_on_a.versions().contains(&msg.version)) - { - return Err(ConnectionError::ConnectionMismatch { - connection_id: msg.conn_id_on_a, - }); - } - - let client_id_on_a = conn_end_on_a.client_id(); - let client_id_on_b = conn_end_on_a.counterparty().client_id(); - - // Proof verification. - { - let client_state_of_b_on_a = ctx_a.client_state(client_id_on_a)?; - let client_cons_state_path_on_a = - ClientConsensusStatePath::new(conn_end_on_a.client_id(), &msg.proofs_height_on_b); - let consensus_state_of_b_on_a = - ctx_a.client_consensus_state(&client_cons_state_path_on_a)?; - - let prefix_on_a = ctx_a.commitment_prefix(); - let prefix_on_b = conn_end_on_a.counterparty().prefix(); - - { - let expected_conn_end_on_b = ConnectionEnd::new( - State::TryOpen, - client_id_on_b.clone(), - Counterparty::new( - client_id_on_a.clone(), - Some(msg.conn_id_on_a.clone()), - prefix_on_a, - ), - vec![msg.version.clone()], - conn_end_on_a.delay_period(), - ); - - client_state_of_b_on_a - .verify_connection_state( - msg.proofs_height_on_b, - prefix_on_b, - &msg.proof_conn_end_on_b, - consensus_state_of_b_on_a.root(), - &ConnectionPath::new(&msg.conn_id_on_b), - &expected_conn_end_on_b, - ) - .map_err(ConnectionError::VerifyConnectionState)?; - } - - client_state_of_b_on_a - .verify_client_full_state( - msg.proofs_height_on_b, - prefix_on_b, - &msg.proof_client_state_of_a_on_b, - consensus_state_of_b_on_a.root(), - &ClientStatePath::new(client_id_on_b), - msg.client_state_of_a_on_b, - ) - .map_err(|e| ConnectionError::ClientStateVerificationFailure { - client_id: conn_end_on_a.client_id().clone(), - client_error: e, - })?; - - let expected_consensus_state_of_a_on_b = - ctx_a.host_consensus_state(&msg.consensus_height_of_a_on_b)?; - - let client_cons_state_path_on_b = ClientConsensusStatePath::new( - conn_end_on_a.counterparty().client_id(), - &msg.consensus_height_of_a_on_b, - ); - client_state_of_b_on_a - .verify_client_consensus_state( - msg.proofs_height_on_b, - prefix_on_b, - &msg.proof_consensus_state_of_a_on_b, - consensus_state_of_b_on_a.root(), - &client_cons_state_path_on_b, - expected_consensus_state_of_a_on_b.as_ref(), - ) - .map_err(|e| ConnectionError::ConsensusStateVerificationFailure { - height: msg.proofs_height_on_b, - client_error: e, - })?; - } - - // Success - output.emit(IbcEvent::OpenAckConnection(OpenAck::new( - msg.conn_id_on_a.clone(), - client_id_on_a.clone(), - msg.conn_id_on_b.clone(), - client_id_on_b.clone(), - ))); - output.log("success: conn_open_ack verification passed"); - - let result = { - let new_conn_end_on_a = { - let mut counterparty = conn_end_on_a.counterparty().clone(); - counterparty.connection_id = Some(msg.conn_id_on_b.clone()); - - let mut new_conn_end_on_a = conn_end_on_a; - new_conn_end_on_a.set_state(State::Open); - new_conn_end_on_a.set_version(msg.version.clone()); - new_conn_end_on_a.set_counterparty(counterparty); - new_conn_end_on_a - }; - - ConnectionResult { - connection_id: msg.conn_id_on_a, - connection_id_state: ConnectionIdState::Reused, - connection_end: new_conn_end_on_a, - } - }; - - Ok(output.with_result(result)) -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/ibc/src/core/ics03_connection/handler/conn_open_confirm.rs b/crates/ibc/src/core/ics03_connection/handler/conn_open_confirm.rs index b68d68c77..ce9f173e5 100644 --- a/crates/ibc/src/core/ics03_connection/handler/conn_open_confirm.rs +++ b/crates/ibc/src/core/ics03_connection/handler/conn_open_confirm.rs @@ -2,13 +2,10 @@ use crate::prelude::*; use crate::core::ics03_connection::connection::{ConnectionEnd, Counterparty, State}; -use crate::core::ics03_connection::context::ConnectionReader; use crate::core::ics03_connection::error::ConnectionError; use crate::core::ics03_connection::events::OpenConfirm; -use crate::core::ics03_connection::handler::{ConnectionIdState, ConnectionResult}; use crate::core::ics03_connection::msgs::conn_open_confirm::MsgConnectionOpenConfirm; use crate::events::IbcEvent; -use crate::handler::{HandlerOutput, HandlerResult}; use crate::core::context::ContextError; @@ -171,88 +168,6 @@ impl LocalVars { } } -/// Per our convention, this message is processed on chain B. -pub(crate) fn process( - ctx_b: &dyn ConnectionReader, - msg: MsgConnectionOpenConfirm, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - let conn_end_on_b = ctx_b.connection_end(&msg.conn_id_on_b)?; - if !conn_end_on_b.state_matches(&State::TryOpen) { - return Err(ConnectionError::ConnectionMismatch { - connection_id: msg.conn_id_on_b, - }); - } - let client_id_on_a = conn_end_on_b.counterparty().client_id(); - let client_id_on_b = conn_end_on_b.client_id(); - let conn_id_on_a = conn_end_on_b - .counterparty() - .connection_id() - .ok_or(ConnectionError::InvalidCounterparty)?; - - // Verify proofs - { - let client_state_of_a_on_b = ctx_b.client_state(client_id_on_b)?; - let client_cons_state_path_on_b = - ClientConsensusStatePath::new(client_id_on_b, &msg.proof_height_on_a); - let consensus_state_of_a_on_b = - ctx_b.client_consensus_state(&client_cons_state_path_on_b)?; - - let prefix_on_a = conn_end_on_b.counterparty().prefix(); - let prefix_on_b = ctx_b.commitment_prefix(); - - let expected_conn_end_on_a = ConnectionEnd::new( - State::Open, - client_id_on_a.clone(), - Counterparty::new( - client_id_on_b.clone(), - Some(msg.conn_id_on_b.clone()), - prefix_on_b, - ), - conn_end_on_b.versions().to_vec(), - conn_end_on_b.delay_period(), - ); - - client_state_of_a_on_b - .verify_connection_state( - msg.proof_height_on_a, - prefix_on_a, - &msg.proof_conn_end_on_a, - consensus_state_of_a_on_b.root(), - &ConnectionPath::new(conn_id_on_a), - &expected_conn_end_on_a, - ) - .map_err(ConnectionError::VerifyConnectionState)?; - } - - // Success - output.emit(IbcEvent::OpenConfirmConnection(OpenConfirm::new( - msg.conn_id_on_b.clone(), - client_id_on_b.clone(), - conn_id_on_a.clone(), - client_id_on_a.clone(), - ))); - output.log("success: conn_open_confirm verification passed"); - - let result = { - let new_conn_end_on_b = { - let mut new_conn_end_on_b = conn_end_on_b; - - new_conn_end_on_b.set_state(State::Open); - new_conn_end_on_b - }; - - ConnectionResult { - connection_id: msg.conn_id_on_b, - connection_id_state: ConnectionIdState::Reused, - connection_end: new_conn_end_on_b, - } - }; - - Ok(output.with_result(result)) -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/ibc/src/core/ics03_connection/handler/conn_open_init.rs b/crates/ibc/src/core/ics03_connection/handler/conn_open_init.rs index cb112889e..66129bf2a 100644 --- a/crates/ibc/src/core/ics03_connection/handler/conn_open_init.rs +++ b/crates/ibc/src/core/ics03_connection/handler/conn_open_init.rs @@ -3,18 +3,13 @@ use crate::prelude::*; use crate::core::context::ContextError; use crate::core::ics03_connection::connection::{ConnectionEnd, Counterparty, State}; -use crate::core::ics03_connection::context::ConnectionReader; use crate::core::ics03_connection::error::ConnectionError; use crate::core::ics03_connection::events::OpenInit; -use crate::core::ics03_connection::handler::ConnectionResult; use crate::core::ics03_connection::msgs::conn_open_init::MsgConnectionOpenInit; use crate::core::ics24_host::identifier::ConnectionId; use crate::core::ics24_host::path::{ClientConnectionPath, ConnectionPath}; use crate::core::{ExecutionContext, ValidationContext}; use crate::events::IbcEvent; -use crate::handler::{HandlerOutput, HandlerResult}; - -use super::ConnectionIdState; pub(crate) fn validate(ctx_a: &Ctx, msg: MsgConnectionOpenInit) -> Result<(), ContextError> where @@ -86,65 +81,6 @@ where Ok(()) } -/// Per our convention, this message is processed on chain A. -pub(crate) fn process( - ctx_a: &dyn ConnectionReader, - msg: MsgConnectionOpenInit, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - // An IBC client running on the local (host) chain should exist. - ctx_a.client_state(&msg.client_id_on_a)?; - - let versions = match msg.version { - Some(version) => { - if ctx_a.get_compatible_versions().contains(&version) { - Ok(vec![version]) - } else { - Err(ConnectionError::VersionNotSupported { version }) - } - } - None => Ok(ctx_a.get_compatible_versions()), - }?; - - let conn_end_on_a = ConnectionEnd::new( - State::Init, - msg.client_id_on_a.clone(), - Counterparty::new( - msg.counterparty.client_id().clone(), - None, - msg.counterparty.prefix().clone(), - ), - versions, - msg.delay_period, - ); - - // Construct the identifier for the new connection. - let conn_id_on_a = ConnectionId::new(ctx_a.connection_counter()?); - - let result = ConnectionResult { - connection_id: conn_id_on_a.clone(), - connection_end: conn_end_on_a, - connection_id_state: ConnectionIdState::Generated, - }; - - output.log(format!( - "success: conn_open_init: generated new connection identifier: {conn_id_on_a}", - )); - - { - let client_id_on_b = msg.counterparty.client_id().clone(); - - output.emit(IbcEvent::OpenInitConnection(OpenInit::new( - conn_id_on_a, - msg.client_id_on_a, - client_id_on_b, - ))); - } - - Ok(output.with_result(result)) -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/ibc/src/core/ics03_connection/handler/conn_open_try.rs b/crates/ibc/src/core/ics03_connection/handler/conn_open_try.rs index 29c51f8ca..9d87a6e2d 100644 --- a/crates/ibc/src/core/ics03_connection/handler/conn_open_try.rs +++ b/crates/ibc/src/core/ics03_connection/handler/conn_open_try.rs @@ -2,16 +2,11 @@ use crate::prelude::*; use crate::core::ics03_connection::connection::{ConnectionEnd, Counterparty, State}; -use crate::core::ics03_connection::context::ConnectionReader; use crate::core::ics03_connection::error::ConnectionError; use crate::core::ics03_connection::events::OpenTry; -use crate::core::ics03_connection::handler::ConnectionResult; use crate::core::ics03_connection::msgs::conn_open_try::MsgConnectionOpenTry; use crate::core::ics24_host::identifier::ConnectionId; use crate::events::IbcEvent; -use crate::handler::{HandlerOutput, HandlerResult}; - -use super::ConnectionIdState; use crate::core::context::ContextError; @@ -208,126 +203,6 @@ impl LocalVars { } } -/// Per our convention, this message is processed on chain B. -pub(crate) fn process( - ctx_b: &dyn ConnectionReader, - msg: MsgConnectionOpenTry, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - let conn_id_on_b = ConnectionId::new(ctx_b.connection_counter()?); - - ctx_b.validate_self_client(msg.client_state_of_b_on_a.clone())?; - - if msg.consensus_height_of_b_on_a > ctx_b.host_current_height()? { - // Fail if the consensus height is too advanced. - return Err(ConnectionError::InvalidConsensusHeight { - target_height: msg.consensus_height_of_b_on_a, - current_height: ctx_b.host_current_height()?, - }); - } - - let version_on_b = ctx_b.pick_version(&ctx_b.get_compatible_versions(), &msg.versions_on_a)?; - - let conn_end_on_b = ConnectionEnd::new( - State::TryOpen, - msg.client_id_on_b.clone(), - msg.counterparty.clone(), - vec![version_on_b], - msg.delay_period, - ); - - let client_id_on_a = msg.counterparty.client_id(); - let conn_id_on_a = conn_end_on_b - .counterparty() - .connection_id() - .ok_or(ConnectionError::InvalidCounterparty)?; - - // Verify proofs - { - let client_state_of_a_on_b = ctx_b.client_state(conn_end_on_b.client_id())?; - let client_cons_state_path_on_b = - ClientConsensusStatePath::new(&msg.client_id_on_b, &msg.proofs_height_on_a); - let consensus_state_of_a_on_b = - ctx_b.client_consensus_state(&client_cons_state_path_on_b)?; - - let prefix_on_a = conn_end_on_b.counterparty().prefix(); - let prefix_on_b = ctx_b.commitment_prefix(); - - { - let versions_on_a = msg.versions_on_a; - let expected_conn_end_on_a = ConnectionEnd::new( - State::Init, - client_id_on_a.clone(), - Counterparty::new(msg.client_id_on_b.clone(), None, prefix_on_b), - versions_on_a, - msg.delay_period, - ); - - client_state_of_a_on_b - .verify_connection_state( - msg.proofs_height_on_a, - prefix_on_a, - &msg.proof_conn_end_on_a, - consensus_state_of_a_on_b.root(), - &ConnectionPath::new(conn_id_on_a), - &expected_conn_end_on_a, - ) - .map_err(ConnectionError::VerifyConnectionState)?; - } - - client_state_of_a_on_b - .verify_client_full_state( - msg.proofs_height_on_a, - prefix_on_a, - &msg.proof_client_state_of_b_on_a, - consensus_state_of_a_on_b.root(), - &ClientStatePath::new(client_id_on_a), - msg.client_state_of_b_on_a, - ) - .map_err(|e| ConnectionError::ClientStateVerificationFailure { - client_id: conn_end_on_b.client_id().clone(), - client_error: e, - })?; - - let expected_consensus_state_of_b_on_a = - ctx_b.host_consensus_state(&msg.consensus_height_of_b_on_a)?; - - let client_cons_state_path_on_a = - ClientConsensusStatePath::new(client_id_on_a, &msg.consensus_height_of_b_on_a); - client_state_of_a_on_b - .verify_client_consensus_state( - msg.proofs_height_on_a, - prefix_on_a, - &msg.proof_consensus_state_of_b_on_a, - consensus_state_of_a_on_b.root(), - &client_cons_state_path_on_a, - expected_consensus_state_of_b_on_a.as_ref(), - ) - .map_err(|e| ConnectionError::ConsensusStateVerificationFailure { - height: msg.proofs_height_on_a, - client_error: e, - })?; - } - - // Success - output.emit(IbcEvent::OpenTryConnection(OpenTry::new( - conn_id_on_b.clone(), - msg.client_id_on_b, - conn_id_on_a.clone(), - client_id_on_a.clone(), - ))); - output.log("success: conn_open_try verification passed"); - - let result = ConnectionResult { - connection_id: conn_id_on_b, - connection_end: conn_end_on_b, - connection_id_state: ConnectionIdState::Generated, - }; - - Ok(output.with_result(result)) -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/ibc/src/core/ics03_connection/mod.rs b/crates/ibc/src/core/ics03_connection/mod.rs index b3e9cf77c..5718a1bff 100644 --- a/crates/ibc/src/core/ics03_connection/mod.rs +++ b/crates/ibc/src/core/ics03_connection/mod.rs @@ -2,8 +2,6 @@ //! on the local chain with a client on a remote chain. pub mod connection; -/// Context definitions (dependencies for the protocol). -pub mod context; pub mod error; pub mod events; /// Message processing logic (protocol) for ICS 03. diff --git a/crates/ibc/src/core/ics04_channel/context.rs b/crates/ibc/src/core/ics04_channel/context.rs index 21d0dbdec..e721aceca 100644 --- a/crates/ibc/src/core/ics04_channel/context.rs +++ b/crates/ibc/src/core/ics04_channel/context.rs @@ -1,155 +1,22 @@ //! ICS4 (channel) context. The two traits `ChannelReader ` and `ChannelKeeper` define //! the interface that any host chain must implement to be able to process any `ChannelMsg`. -//! use crate::core::ics02_client::client_state::ClientState; -use crate::core::ics24_host::path::{ - AckPath, ChannelEndPath, ClientConsensusStatePath, CommitmentPath, ReceiptPath, SeqAckPath, - SeqRecvPath, SeqSendPath, -}; +use crate::core::ics24_host::path::{ChannelEndPath, ClientConsensusStatePath, SeqSendPath}; use crate::core::{ContextError, ValidationContext}; +use crate::prelude::*; use core::time::Duration; use num_traits::float::FloatCore; use crate::core::ics02_client::consensus_state::ConsensusState; use crate::core::ics03_connection::connection::ConnectionEnd; use crate::core::ics04_channel::channel::ChannelEnd; -use crate::core::ics04_channel::commitment::{AcknowledgementCommitment, PacketCommitment}; -use crate::core::ics04_channel::handler::recv_packet::RecvPacketResult; -use crate::core::ics04_channel::handler::{ChannelIdState, ChannelResult}; -use crate::core::ics04_channel::msgs::acknowledgement::Acknowledgement; -use crate::core::ics04_channel::{ - error::{ChannelError, PacketError}, - packet::Receipt, -}; -use crate::core::ics24_host::identifier::{ChannelId, ClientId, ConnectionId, PortId}; -use crate::prelude::*; +use crate::core::ics04_channel::commitment::PacketCommitment; +use crate::core::ics24_host::identifier::{ClientId, ConnectionId}; use crate::timestamp::Timestamp; -use crate::Height; -use super::packet::{PacketResult, Sequence}; +use super::packet::Sequence; use super::timeout::TimeoutHeight; -/// A context supplying all the necessary read-only dependencies for processing any `ChannelMsg`. -pub trait ChannelReader { - /// Returns the ChannelEnd for the given `port_id` and `chan_id`. - fn channel_end(&self, chan_end_path: &ChannelEndPath) -> Result; - - /// Returns the ConnectionState for the given identifier `connection_id`. - fn connection_end(&self, connection_id: &ConnectionId) -> Result; - - fn connection_channels( - &self, - cid: &ConnectionId, - ) -> Result, ChannelError>; - - /// Returns the ClientState for the given identifier `client_id`. Necessary dependency towards - /// proof verification. - fn client_state(&self, client_id: &ClientId) -> Result, ChannelError>; - - fn client_consensus_state( - &self, - client_cons_state_path: &ClientConsensusStatePath, - ) -> Result, ChannelError>; - - fn get_next_sequence_send(&self, seq_send_path: &SeqSendPath) -> Result; - - fn get_next_sequence_recv(&self, seq_recv_path: &SeqRecvPath) -> Result; - - fn get_next_sequence_ack(&self, seq_ack_path: &SeqAckPath) -> Result; - - fn get_packet_commitment( - &self, - commitment_path: &CommitmentPath, - ) -> Result; - - fn get_packet_receipt(&self, receipt_path: &ReceiptPath) -> Result; - - fn get_packet_acknowledgement( - &self, - ack_path: &AckPath, - ) -> Result; - - /// Compute the commitment for a packet. - /// Note that the absence of `timeout_height` is treated as - /// `{revision_number: 0, revision_height: 0}` to be consistent with ibc-go, - /// where this value is used to mean "no timeout height": - /// - fn packet_commitment( - &self, - packet_data: &[u8], - timeout_height: &TimeoutHeight, - timeout_timestamp: &Timestamp, - ) -> PacketCommitment { - let mut hash_input = timeout_timestamp.nanoseconds().to_be_bytes().to_vec(); - - let revision_number = timeout_height.commitment_revision_number().to_be_bytes(); - hash_input.append(&mut revision_number.to_vec()); - - let revision_height = timeout_height.commitment_revision_height().to_be_bytes(); - hash_input.append(&mut revision_height.to_vec()); - - let packet_data_hash = self.hash(packet_data); - hash_input.append(&mut packet_data_hash.to_vec()); - - self.hash(&hash_input).into() - } - - fn ack_commitment(&self, ack: &Acknowledgement) -> AcknowledgementCommitment { - self.hash(ack.as_ref()).into() - } - - /// A hashing function for packet commitments - fn hash(&self, value: &[u8]) -> Vec; - - /// Returns the current height of the local chain. - fn host_height(&self) -> Result; - - /// Returns the current timestamp of the local chain. - fn host_timestamp(&self) -> Result { - let pending_consensus_state = self - .pending_host_consensus_state() - .expect("host must have pending consensus state"); - Ok(pending_consensus_state.timestamp()) - } - - /// Returns the `ConsensusState` of the host (local) chain at a specific height. - fn host_consensus_state( - &self, - height: &Height, - ) -> Result, ChannelError>; - - /// Returns the pending `ConsensusState` of the host (local) chain. - fn pending_host_consensus_state(&self) -> Result, ChannelError>; - - /// Returns the time when the client state for the given [`ClientId`] was updated with a header for the given [`Height`] - fn client_update_time( - &self, - client_id: &ClientId, - height: &Height, - ) -> Result; - - /// Returns the height when the client state for the given [`ClientId`] was updated with a header for the given [`Height`] - fn client_update_height( - &self, - client_id: &ClientId, - height: &Height, - ) -> Result; - - /// Returns a counter on the number of channel ids have been created thus far. - /// The value of this counter should increase only via method - /// `ChannelKeeper::increase_channel_counter`. - fn channel_counter(&self) -> Result; - - /// Returns the maximum expected time per block - fn max_expected_time_per_block(&self) -> Duration; - - /// Calculates the block delay period using the connection's delay period and the maximum - /// expected time per block. - fn block_delay(&self, delay_period_time: &Duration) -> u64 { - calculate_block_delay(delay_period_time, &self.max_expected_time_per_block()) - } -} - pub trait SendPacketReader { /// Returns the ChannelEnd for the given `port_id` and `chan_id`. fn channel_end(&self, channel_end_path: &ChannelEndPath) -> Result; @@ -227,182 +94,6 @@ where } } -/// A context supplying all the necessary write-only dependencies (i.e., storage writing facility) -/// for processing any `ChannelMsg`. -pub trait ChannelKeeper { - fn store_channel_result(&mut self, result: ChannelResult) -> Result<(), PacketError> { - let connection_id = result.channel_end.connection_hops()[0].clone(); - - // The handler processed this channel & some modifications occurred, store the new end. - self.store_channel( - result.port_id.clone(), - result.channel_id.clone(), - result.channel_end, - ) - .map_err(PacketError::Channel)?; - - // The channel identifier was freshly brewed. - // Increase counter & initialize seq. nrs. - if matches!(result.channel_id_state, ChannelIdState::Generated) { - self.increase_channel_counter(); - - // Associate also the channel end to its connection. - self.store_connection_channels( - connection_id, - result.port_id.clone(), - result.channel_id.clone(), - ) - .map_err(PacketError::Channel)?; - - // Initialize send, recv, and ack sequence numbers. - self.store_next_sequence_send( - result.port_id.clone(), - result.channel_id.clone(), - 1.into(), - )?; - self.store_next_sequence_recv( - result.port_id.clone(), - result.channel_id.clone(), - 1.into(), - )?; - self.store_next_sequence_ack(result.port_id, result.channel_id, 1.into())?; - } - - Ok(()) - } - - fn store_packet_result(&mut self, general_result: PacketResult) -> Result<(), PacketError> { - match general_result { - PacketResult::Send(res) => { - self.store_next_sequence_send( - res.port_id.clone(), - res.channel_id.clone(), - res.seq_number, - )?; - - self.store_packet_commitment(res.port_id, res.channel_id, res.seq, res.commitment)?; - } - PacketResult::Recv(res) => match res { - RecvPacketResult::Ordered { - port_id, - channel_id, - next_seq_recv, - } => self.store_next_sequence_recv(port_id, channel_id, next_seq_recv)?, - RecvPacketResult::Unordered { - port_id, - channel_id, - sequence, - receipt, - } => self.store_packet_receipt(port_id, channel_id, sequence, receipt)?, - RecvPacketResult::NoOp => unreachable!(), - }, - PacketResult::WriteAck(res) => { - self.store_packet_acknowledgement( - res.port_id, - res.channel_id, - res.seq, - res.ack_commitment, - )?; - } - PacketResult::Ack(res) => { - self.delete_packet_commitment(&res.port_id, &res.channel_id, &res.seq)?; - if let Some(s) = res.seq_number { - //Ordered Channel - self.store_next_sequence_ack(res.port_id, res.channel_id, s)?; - } - } - PacketResult::Timeout(res) => { - self.delete_packet_commitment(&res.port_id, &res.channel_id, &res.seq)?; - if let Some(c) = res.channel { - // Ordered Channel: closes channel - self.store_channel(res.port_id, res.channel_id, c) - .map_err(PacketError::Channel)?; - } - } - } - Ok(()) - } - - fn store_packet_commitment( - &mut self, - port_id: PortId, - channel_id: ChannelId, - sequence: Sequence, - commitment: PacketCommitment, - ) -> Result<(), PacketError>; - - fn delete_packet_commitment( - &mut self, - port_id: &PortId, - channel_id: &ChannelId, - seq: &Sequence, - ) -> Result<(), PacketError>; - - fn store_packet_receipt( - &mut self, - port_id: PortId, - channel_id: ChannelId, - sequence: Sequence, - receipt: Receipt, - ) -> Result<(), PacketError>; - - fn store_packet_acknowledgement( - &mut self, - port_id: PortId, - channel_id: ChannelId, - sequence: Sequence, - ack_commitment: AcknowledgementCommitment, - ) -> Result<(), PacketError>; - - fn delete_packet_acknowledgement( - &mut self, - port_id: &PortId, - channel_id: &ChannelId, - sequence: &Sequence, - ) -> Result<(), PacketError>; - - fn store_connection_channels( - &mut self, - conn_id: ConnectionId, - port_id: PortId, - channel_id: ChannelId, - ) -> Result<(), ChannelError>; - - /// Stores the given channel_end at a path associated with the port_id and channel_id. - fn store_channel( - &mut self, - port_id: PortId, - channel_id: ChannelId, - channel_end: ChannelEnd, - ) -> Result<(), ChannelError>; - - fn store_next_sequence_send( - &mut self, - port_id: PortId, - channel_id: ChannelId, - seq: Sequence, - ) -> Result<(), PacketError>; - - fn store_next_sequence_recv( - &mut self, - port_id: PortId, - channel_id: ChannelId, - seq: Sequence, - ) -> Result<(), PacketError>; - - fn store_next_sequence_ack( - &mut self, - port_id: PortId, - channel_id: ChannelId, - seq: Sequence, - ) -> Result<(), PacketError>; - - /// Called upon channel identifier creation (Init or Try message processing). - /// Increases the counter which keeps track of how many channels have been created. - /// Should never fail. - fn increase_channel_counter(&mut self); -} - pub fn calculate_block_delay( delay_period_time: &Duration, max_expected_time_per_block: &Duration, diff --git a/crates/ibc/src/core/ics04_channel/handler.rs b/crates/ibc/src/core/ics04_channel/handler.rs index 576a3cd6d..bb04f0b67 100644 --- a/crates/ibc/src/core/ics04_channel/handler.rs +++ b/crates/ibc/src/core/ics04_channel/handler.rs @@ -1,22 +1,7 @@ //! This module implements the processing logic for ICS4 (channel) messages. -use crate::events::{IbcEvent, ModuleEvent}; +use crate::events::ModuleEvent; use crate::prelude::*; -use crate::core::ics04_channel::channel::ChannelEnd; -use crate::core::ics04_channel::context::ChannelReader; -use crate::core::ics04_channel::error::{ChannelError, PacketError}; -use crate::core::ics04_channel::msgs::ChannelMsg; -use crate::core::ics04_channel::packet::Packet; -use crate::core::ics04_channel::{msgs::PacketMsg, packet::PacketResult}; -use crate::core::ics24_host::identifier::{ChannelId, ConnectionId, PortId}; -use crate::core::ics26_routing::context::{ModuleId, ModuleOutputBuilder, Router, RouterContext}; -use crate::handler::{HandlerOutput, HandlerOutputBuilder}; - -use super::channel::Counterparty; -use super::events::{CloseConfirm, CloseInit, OpenAck, OpenConfirm, OpenInit, OpenTry}; -use super::msgs::acknowledgement::Acknowledgement; -use super::Version; - pub mod acknowledgement; pub mod chan_close_confirm; pub mod chan_close_init; @@ -28,26 +13,6 @@ pub mod recv_packet; pub mod send_packet; pub mod timeout; pub mod timeout_on_close; -pub mod write_acknowledgement; - -/// Defines the possible states of a channel identifier in a `ChannelResult`. -#[derive(Clone, Debug)] -pub enum ChannelIdState { - /// Specifies that the channel handshake handler allocated a new channel identifier. This - /// happens during the processing of either the `MsgChannelOpenInit` or `MsgChannelOpenTry`. - Generated, - - /// Specifies that the handler reused a previously-allocated channel identifier. - Reused, -} - -#[derive(Clone, Debug)] -pub struct ChannelResult { - pub port_id: PortId, - pub channel_id: ChannelId, - pub channel_id_state: ChannelIdState, - pub channel_end: ChannelEnd, -} #[derive(Clone, Debug)] pub struct ModuleExtras { @@ -63,270 +28,3 @@ impl ModuleExtras { } } } - -pub(crate) fn channel_validate(ctx: &Ctx, msg: &ChannelMsg) -> Result -where - Ctx: RouterContext, -{ - let module_id = msg.lookup_module(ctx)?; - if ctx.router().has_route(&module_id) { - Ok(module_id) - } else { - Err(ChannelError::RouteNotFound) - } -} - -/// General entry point for processing any type of message related to the ICS4 channel open and -/// channel close handshake protocols. -pub(crate) fn channel_dispatch( - ctx: &Ctx, - msg: &ChannelMsg, -) -> Result<(Vec, ChannelResult), ChannelError> -where - Ctx: ChannelReader, -{ - let output = match msg { - ChannelMsg::OpenInit(msg) => chan_open_init::process(ctx, msg), - ChannelMsg::OpenTry(msg) => chan_open_try::process(ctx, msg), - ChannelMsg::OpenAck(msg) => chan_open_ack::process(ctx, msg), - ChannelMsg::OpenConfirm(msg) => chan_open_confirm::process(ctx, msg), - ChannelMsg::CloseInit(msg) => chan_close_init::process(ctx, msg), - ChannelMsg::CloseConfirm(msg) => chan_close_confirm::process(ctx, msg), - }?; - - let HandlerOutput { result, log, .. } = output; - Ok((log, result)) -} - -pub(crate) fn channel_callback( - ctx: &mut Ctx, - module_id: &ModuleId, - msg: &ChannelMsg, - result: &mut ChannelResult, -) -> Result -where - Ctx: RouterContext, -{ - let cb = ctx - .router_mut() - .get_route_mut(module_id) - .ok_or(ChannelError::RouteNotFound)?; - - match msg { - ChannelMsg::OpenInit(msg) => { - let (extras, version) = cb.on_chan_open_init( - msg.ordering, - &msg.connection_hops_on_a, - &msg.port_id_on_a, - &result.channel_id, - &Counterparty::new(msg.port_id_on_b.clone(), None), - &msg.version_proposal, - )?; - result.channel_end.version = version; - - Ok(extras) - } - ChannelMsg::OpenTry(msg) => { - let (extras, version) = cb.on_chan_open_try( - msg.ordering, - &msg.connection_hops_on_b, - &msg.port_id_on_b, - &result.channel_id, - &Counterparty::new(msg.port_id_on_a.clone(), Some(msg.chan_id_on_a.clone())), - &msg.version_supported_on_a, - )?; - result.channel_end.version = version; - - Ok(extras) - } - ChannelMsg::OpenAck(msg) => { - cb.on_chan_open_ack(&msg.port_id_on_a, &result.channel_id, &msg.version_on_b) - } - ChannelMsg::OpenConfirm(msg) => { - cb.on_chan_open_confirm(&msg.port_id_on_b, &result.channel_id) - } - ChannelMsg::CloseInit(msg) => cb.on_chan_close_init(&msg.port_id_on_a, &result.channel_id), - ChannelMsg::CloseConfirm(msg) => { - cb.on_chan_close_confirm(&msg.port_id_on_b, &result.channel_id) - } - } -} - -/// Constructs the proper channel event -pub(crate) fn channel_events( - msg: &ChannelMsg, - channel_id: ChannelId, - counterparty: Counterparty, - connection_id: ConnectionId, - version: &Version, -) -> Vec { - let event = match msg { - ChannelMsg::OpenInit(msg) => IbcEvent::OpenInitChannel(OpenInit::new( - msg.port_id_on_a.clone(), - channel_id, - counterparty.port_id, - connection_id, - version.clone(), - )), - ChannelMsg::OpenTry(msg) => IbcEvent::OpenTryChannel(OpenTry::new( - msg.port_id_on_b.clone(), - channel_id, - counterparty.port_id, - counterparty - .channel_id - .expect("counterparty channel id must exist after channel open try"), - connection_id, - version.clone(), - )), - ChannelMsg::OpenAck(msg) => IbcEvent::OpenAckChannel(OpenAck::new( - msg.port_id_on_a.clone(), - channel_id, - counterparty.port_id, - counterparty - .channel_id - .expect("counterparty channel id must exist after channel open ack"), - connection_id, - )), - ChannelMsg::OpenConfirm(msg) => IbcEvent::OpenConfirmChannel(OpenConfirm::new( - msg.port_id_on_b.clone(), - channel_id, - counterparty.port_id, - counterparty - .channel_id - .expect("counterparty channel id must exist after channel open confirm"), - connection_id, - )), - ChannelMsg::CloseInit(msg) => IbcEvent::CloseInitChannel(CloseInit::new( - msg.port_id_on_a.clone(), - channel_id, - counterparty.port_id, - counterparty - .channel_id - .expect("counterparty channel id must exist after channel open ack"), - connection_id, - )), - ChannelMsg::CloseConfirm(msg) => IbcEvent::CloseConfirmChannel(CloseConfirm::new( - msg.port_id_on_b.clone(), - channel_id, - counterparty.port_id, - counterparty - .channel_id - .expect("counterparty channel id must exist after channel open ack"), - connection_id, - )), - }; - - vec![event] -} - -pub(crate) fn get_module_for_packet_msg( - ctx: &Ctx, - msg: &PacketMsg, -) -> Result -where - Ctx: RouterContext, -{ - let module_id = msg.lookup_module(ctx)?; - if ctx.router().has_route(&module_id) { - Ok(module_id) - } else { - Err(ChannelError::RouteNotFound) - } -} - -/// Dispatcher for processing any type of message related to the ICS4 packet protocols. -pub(crate) fn packet_dispatch( - ctx: &Ctx, - msg: &PacketMsg, -) -> Result<(HandlerOutputBuilder<()>, PacketResult), PacketError> -where - Ctx: ChannelReader, -{ - let output = match msg { - PacketMsg::Recv(msg) => recv_packet::process(ctx, msg), - PacketMsg::Ack(msg) => acknowledgement::process(ctx, msg), - PacketMsg::Timeout(msg) => timeout::process(ctx, msg), - PacketMsg::TimeoutOnClose(msg) => timeout_on_close::process(ctx, msg), - }?; - let HandlerOutput { - result, - log, - events, - } = output; - let builder = HandlerOutput::builder().with_log(log).with_events(events); - Ok((builder, result)) -} - -pub(crate) fn packet_callback( - ctx: &mut Ctx, - module_id: &ModuleId, - msg: &PacketMsg, - output: &mut HandlerOutputBuilder<()>, -) -> Result<(), PacketError> -where - Ctx: RouterContext, -{ - let mut module_output = ModuleOutputBuilder::new(); - let mut core_output = HandlerOutputBuilder::new(); - - let result = do_packet_callback(ctx, module_id, msg, &mut module_output, &mut core_output); - output.merge(module_output); - output.merge(core_output); - - result -} - -fn do_packet_callback( - ctx: &mut impl RouterContext, - module_id: &ModuleId, - msg: &PacketMsg, - module_output: &mut ModuleOutputBuilder, - core_output: &mut HandlerOutputBuilder<()>, -) -> Result<(), PacketError> { - let cb = ctx - .router_mut() - .get_route_mut(module_id) - .ok_or(PacketError::RouteNotFound)?; - - match msg { - PacketMsg::Recv(msg) => { - let ack = cb.on_recv_packet(module_output, &msg.packet, &msg.signer); - process_write_ack(ctx, msg.packet.clone(), ack, core_output) - } - PacketMsg::Ack(msg) => cb.on_acknowledgement_packet( - module_output, - &msg.packet, - &msg.acknowledgement, - &msg.signer, - ), - PacketMsg::Timeout(msg) => cb.on_timeout_packet(module_output, &msg.packet, &msg.signer), - PacketMsg::TimeoutOnClose(msg) => { - cb.on_timeout_packet(module_output, &msg.packet, &msg.signer) - } - } -} - -fn process_write_ack( - ctx: &mut impl RouterContext, - packet: Packet, - acknowledgement: Acknowledgement, - core_output: &mut HandlerOutputBuilder<()>, -) -> Result<(), PacketError> { - let HandlerOutput { - result, - log, - events, - } = write_acknowledgement::process(ctx, packet, acknowledgement)?; - - // store write ack result - ctx.store_packet_result(result)?; - - core_output.merge_output( - HandlerOutput::builder() - .with_log(log) - .with_events(events) - .with_result(()), - ); - - Ok(()) -} diff --git a/crates/ibc/src/core/ics04_channel/handler/acknowledgement.rs b/crates/ibc/src/core/ics04_channel/handler/acknowledgement.rs index 782e63e82..309fdbfe6 100644 --- a/crates/ibc/src/core/ics04_channel/handler/acknowledgement.rs +++ b/crates/ibc/src/core/ics04_channel/handler/acknowledgement.rs @@ -2,16 +2,11 @@ use crate::core::ics03_connection::connection::State as ConnectionState; use crate::core::ics04_channel::channel::State; use crate::core::ics04_channel::channel::{Counterparty, Order}; use crate::core::ics04_channel::error::ChannelError; -use crate::core::ics04_channel::events::AcknowledgePacket; +use crate::core::ics04_channel::error::PacketError; use crate::core::ics04_channel::msgs::acknowledgement::MsgAcknowledgement; -use crate::core::ics04_channel::packet::{PacketResult, Sequence}; -use crate::core::ics04_channel::{context::ChannelReader, error::PacketError}; -use crate::core::ics24_host::identifier::{ChannelId, PortId}; use crate::core::ics24_host::path::{ AckPath, ChannelEndPath, ClientConsensusStatePath, CommitmentPath, SeqAckPath, }; -use crate::events::IbcEvent; -use crate::handler::{HandlerOutput, HandlerResult}; use crate::prelude::*; use crate::core::{ContextError, ValidationContext}; @@ -108,110 +103,6 @@ where let ack_commitment = ctx_a.ack_commitment(&msg.acknowledgement); let ack_path_on_b = AckPath::new(&packet.port_on_b, &packet.chan_on_b, packet.sequence); // Verify the proof for the packet against the chain store. - client_state_on_a - .new_verify_packet_acknowledgement( - ctx_a, - msg.proof_height_on_b, - &conn_end_on_a, - &msg.proof_acked_on_b, - consensus_state.root(), - &ack_path_on_b, - ack_commitment, - ) - .map_err(|e| ChannelError::PacketVerificationFailed { - sequence: packet.sequence, - client_error: e, - }) - .map_err(PacketError::Channel)?; - } - - Ok(()) -} -#[derive(Clone, Debug)] -pub struct AckPacketResult { - pub port_id: PortId, - pub channel_id: ChannelId, - pub seq: Sequence, - pub seq_number: Option, -} - -pub(crate) fn process( - ctx_a: &Ctx, - msg: &MsgAcknowledgement, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - let packet = &msg.packet; - let chan_end_path_on_a = ChannelEndPath::new(&packet.port_on_a, &packet.chan_on_a); - let chan_end_on_a = ctx_a - .channel_end(&chan_end_path_on_a) - .map_err(PacketError::Channel)?; - - if !chan_end_on_a.state_matches(&State::Open) { - return Err(PacketError::ChannelClosed { - channel_id: packet.chan_on_a.clone(), - }); - } - - let counterparty = Counterparty::new(packet.port_on_b.clone(), Some(packet.chan_on_b.clone())); - - if !chan_end_on_a.counterparty_matches(&counterparty) { - return Err(PacketError::InvalidPacketCounterparty { - port_id: packet.port_on_b.clone(), - channel_id: packet.chan_on_b.clone(), - }); - } - - let conn_id_on_a = &chan_end_on_a.connection_hops()[0]; - let conn_end_on_a = ctx_a - .connection_end(conn_id_on_a) - .map_err(PacketError::Channel)?; - - if !conn_end_on_a.state_matches(&ConnectionState::Open) { - return Err(PacketError::ConnectionNotOpen { - connection_id: chan_end_on_a.connection_hops()[0].clone(), - }); - } - - let commitment_path_on_a = - CommitmentPath::new(&packet.port_on_a, &packet.chan_on_a, packet.sequence); - // Verify packet commitment - let packet_commitment = ctx_a.get_packet_commitment(&commitment_path_on_a)?; - - if packet_commitment - != ctx_a.packet_commitment( - &packet.data, - &packet.timeout_height_on_b, - &packet.timeout_timestamp_on_b, - ) - { - return Err(PacketError::IncorrectPacketCommitment { - sequence: packet.sequence, - }); - } - - // Verify proofs - { - let client_id_on_a = conn_end_on_a.client_id(); - let client_state_on_a = ctx_a - .client_state(client_id_on_a) - .map_err(PacketError::Channel)?; - - // The client must not be frozen. - if client_state_on_a.is_frozen() { - return Err(PacketError::FrozenClient { - client_id: client_id_on_a.clone(), - }); - } - - let client_cons_state_path_on_a = - ClientConsensusStatePath::new(client_id_on_a, &msg.proof_height_on_b); - let consensus_state = ctx_a - .client_consensus_state(&client_cons_state_path_on_a) - .map_err(PacketError::Channel)?; - let ack_commitment = ctx_a.ack_commitment(&msg.acknowledgement); - let ack_path_on_b = AckPath::new(&packet.port_on_b, &packet.chan_on_b, packet.sequence); - // Verify the proof for the packet against the chain store. client_state_on_a .verify_packet_acknowledgement( ctx_a, @@ -229,41 +120,7 @@ pub(crate) fn process( .map_err(PacketError::Channel)?; } - let result = if chan_end_on_a.order_matches(&Order::Ordered) { - let ack_path_on_a = SeqAckPath::new(&packet.port_on_a, &packet.chan_on_a); - let next_seq_ack = ctx_a.get_next_sequence_ack(&ack_path_on_a)?; - - if packet.sequence != next_seq_ack { - return Err(PacketError::InvalidPacketSequence { - given_sequence: packet.sequence, - next_sequence: next_seq_ack, - }); - } - - PacketResult::Ack(AckPacketResult { - port_id: packet.port_on_a.clone(), - channel_id: packet.chan_on_a.clone(), - seq: packet.sequence, - seq_number: Some(next_seq_ack.increment()), - }) - } else { - PacketResult::Ack(AckPacketResult { - port_id: packet.port_on_a.clone(), - channel_id: packet.chan_on_a.clone(), - seq: packet.sequence, - seq_number: None, - }) - }; - - output.log("success: packet ack"); - - output.emit(IbcEvent::AcknowledgePacket(AcknowledgePacket::new( - packet.clone(), - chan_end_on_a.ordering, - conn_id_on_a.clone(), - ))); - - Ok(output.with_result(result)) + Ok(()) } #[cfg(test)] diff --git a/crates/ibc/src/core/ics04_channel/handler/chan_close_confirm.rs b/crates/ibc/src/core/ics04_channel/handler/chan_close_confirm.rs index adb4df7dd..0080def11 100644 --- a/crates/ibc/src/core/ics04_channel/handler/chan_close_confirm.rs +++ b/crates/ibc/src/core/ics04_channel/handler/chan_close_confirm.rs @@ -1,12 +1,9 @@ //! Protocol logic specific to ICS4 messages of type `MsgChannelCloseConfirm`. use crate::core::ics03_connection::connection::State as ConnectionState; use crate::core::ics04_channel::channel::{ChannelEnd, Counterparty, State}; -use crate::core::ics04_channel::context::ChannelReader; use crate::core::ics04_channel::error::ChannelError; -use crate::core::ics04_channel::handler::{ChannelIdState, ChannelResult}; use crate::core::ics04_channel::msgs::chan_close_confirm::MsgChannelCloseConfirm; use crate::core::ics24_host::path::{ChannelEndPath, ClientConsensusStatePath}; -use crate::handler::{HandlerOutput, HandlerResult}; use crate::prelude::*; use crate::core::{ContextError, ValidationContext}; @@ -98,108 +95,6 @@ where Ok(()) } -/// Per our convention, this message is processed on chain B. -pub(crate) fn process( - ctx_b: &Ctx, - msg: &MsgChannelCloseConfirm, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - // Retrieve the old channel end and validate it against the message. - let chan_end_path_on_b = ChannelEndPath::new(&msg.port_id_on_b, &msg.chan_id_on_b); - let chan_end_on_b = ctx_b.channel_end(&chan_end_path_on_b)?; - - // Validate that the channel end is in a state where it can be closed. - if chan_end_on_b.state_matches(&State::Closed) { - return Err(ChannelError::ChannelClosed { - channel_id: msg.chan_id_on_b.clone(), - }); - } - - // An OPEN IBC connection running on the local (host) chain should exist. - if chan_end_on_b.connection_hops().len() != 1 { - return Err(ChannelError::InvalidConnectionHopsLength { - expected: 1, - actual: chan_end_on_b.connection_hops().len(), - }); - } - - let conn_end_on_b = ctx_b.connection_end(&chan_end_on_b.connection_hops()[0])?; - - if !conn_end_on_b.state_matches(&ConnectionState::Open) { - return Err(ChannelError::ConnectionNotOpen { - connection_id: chan_end_on_b.connection_hops()[0].clone(), - }); - } - - // Verify proofs - { - let client_id_on_b = conn_end_on_b.client_id(); - let client_state_of_a_on_b = ctx_b.client_state(client_id_on_b)?; - let client_cons_state_path_on_b = - ClientConsensusStatePath::new(client_id_on_b, &msg.proof_height_on_a); - let consensus_state_of_a_on_b = - ctx_b.client_consensus_state(&client_cons_state_path_on_b)?; - let prefix_on_a = conn_end_on_b.counterparty().prefix(); - let port_id_on_a = &chan_end_on_b.counterparty().port_id; - let chan_id_on_a = chan_end_on_b - .counterparty() - .channel_id() - .ok_or(ChannelError::InvalidCounterpartyChannelId)?; - let conn_id_on_a = conn_end_on_b.counterparty().connection_id().ok_or( - ChannelError::UndefinedConnectionCounterparty { - connection_id: chan_end_on_b.connection_hops()[0].clone(), - }, - )?; - - // The client must not be frozen. - if client_state_of_a_on_b.is_frozen() { - return Err(ChannelError::FrozenClient { - client_id: client_id_on_b.clone(), - }); - } - - let expected_chan_end_on_a = ChannelEnd::new( - State::Closed, - *chan_end_on_b.ordering(), - Counterparty::new(msg.port_id_on_b.clone(), Some(msg.chan_id_on_b.clone())), - vec![conn_id_on_a.clone()], - chan_end_on_b.version().clone(), - ); - let chan_end_path_on_a = ChannelEndPath::new(port_id_on_a, chan_id_on_a); - - // Verify the proof for the channel state against the expected channel end. - // A counterparty channel id of None in not possible, and is checked by validate_basic in msg. - client_state_of_a_on_b - .verify_channel_state( - msg.proof_height_on_a, - prefix_on_a, - &msg.proof_chan_end_on_a, - consensus_state_of_a_on_b.root(), - &chan_end_path_on_a, - &expected_chan_end_on_a, - ) - .map_err(ChannelError::VerifyChannelFailed)?; - } - - output.log("success: channel close confirm"); - - let new_chan_end_on_b = { - let mut chan_end_on_b = chan_end_on_b; - chan_end_on_b.set_state(State::Closed); - chan_end_on_b - }; - - let result = ChannelResult { - port_id: msg.port_id_on_b.clone(), - channel_id: msg.chan_id_on_b.clone(), - channel_id_state: ChannelIdState::Reused, - channel_end: new_chan_end_on_b, - }; - - Ok(output.with_result(result)) -} - #[cfg(test)] mod tests { use crate::core::ics04_channel::msgs::chan_close_confirm::test_util::get_dummy_raw_msg_chan_close_confirm; diff --git a/crates/ibc/src/core/ics04_channel/handler/chan_close_init.rs b/crates/ibc/src/core/ics04_channel/handler/chan_close_init.rs index 3aab22468..2d69816a0 100644 --- a/crates/ibc/src/core/ics04_channel/handler/chan_close_init.rs +++ b/crates/ibc/src/core/ics04_channel/handler/chan_close_init.rs @@ -1,12 +1,9 @@ //! Protocol logic specific to ICS4 messages of type `MsgChannelCloseInit`. use crate::core::ics03_connection::connection::State as ConnectionState; use crate::core::ics04_channel::channel::State; -use crate::core::ics04_channel::context::ChannelReader; use crate::core::ics04_channel::error::ChannelError; -use crate::core::ics04_channel::handler::{ChannelIdState, ChannelResult}; use crate::core::ics04_channel::msgs::chan_close_init::MsgChannelCloseInit; use crate::core::ics24_host::path::ChannelEndPath; -use crate::handler::{HandlerOutput, HandlerResult}; use crate::core::{ContextError, ValidationContext}; @@ -47,58 +44,6 @@ where Ok(()) } -/// Per our convention, this message is processed on chain A. -pub(crate) fn process( - ctx_a: &Ctx, - msg: &MsgChannelCloseInit, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - let chan_end_path_on_a = ChannelEndPath::new(&msg.port_id_on_a, &msg.chan_id_on_a); - let chan_end_on_a = ctx_a.channel_end(&chan_end_path_on_a)?; - - // Validate that the channel end is in a state where it can be closed. - if chan_end_on_a.state_matches(&State::Closed) { - return Err(ChannelError::InvalidChannelState { - channel_id: msg.chan_id_on_a.clone(), - state: chan_end_on_a.state, - }); - } - - // An OPEN IBC connection running on the local (host) chain should exist. - if chan_end_on_a.connection_hops().len() != 1 { - return Err(ChannelError::InvalidConnectionHopsLength { - expected: 1, - actual: chan_end_on_a.connection_hops().len(), - }); - } - - let conn_end_on_a = ctx_a.connection_end(&chan_end_on_a.connection_hops()[0])?; - - if !conn_end_on_a.state_matches(&ConnectionState::Open) { - return Err(ChannelError::ConnectionNotOpen { - connection_id: chan_end_on_a.connection_hops()[0].clone(), - }); - } - - output.log("success: channel close init"); - - let new_chan_end_on_a = { - let mut chan_end_on_a = chan_end_on_a; - chan_end_on_a.set_state(State::Closed); - chan_end_on_a - }; - - let result = ChannelResult { - port_id: msg.port_id_on_a.clone(), - channel_id: msg.chan_id_on_a.clone(), - channel_id_state: ChannelIdState::Reused, - channel_end: new_chan_end_on_a, - }; - - Ok(output.with_result(result)) -} - #[cfg(test)] mod tests { use crate::core::ics04_channel::msgs::chan_close_init::test_util::get_dummy_raw_msg_chan_close_init; diff --git a/crates/ibc/src/core/ics04_channel/handler/chan_open_ack.rs b/crates/ibc/src/core/ics04_channel/handler/chan_open_ack.rs index 5a0eff9fd..feb3f7fe9 100644 --- a/crates/ibc/src/core/ics04_channel/handler/chan_open_ack.rs +++ b/crates/ibc/src/core/ics04_channel/handler/chan_open_ack.rs @@ -1,12 +1,9 @@ //! Protocol logic specific to ICS4 messages of type `MsgChannelOpenAck`. use crate::core::ics03_connection::connection::State as ConnectionState; use crate::core::ics04_channel::channel::{ChannelEnd, Counterparty, State}; -use crate::core::ics04_channel::context::ChannelReader; use crate::core::ics04_channel::error::ChannelError; -use crate::core::ics04_channel::handler::{ChannelIdState, ChannelResult}; use crate::core::ics04_channel::msgs::chan_open_ack::MsgChannelOpenAck; use crate::core::ics24_host::path::{ChannelEndPath, ClientConsensusStatePath}; -use crate::handler::{HandlerOutput, HandlerResult}; use crate::prelude::*; use crate::core::{ContextError, ValidationContext}; @@ -97,113 +94,6 @@ where Ok(()) } -/// Per our convention, this message is processed on chain A. -pub(crate) fn process( - ctx_a: &Ctx, - msg: &MsgChannelOpenAck, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - // Unwrap the old channel end and validate it against the message. - let chan_end_path_on_a = &ChannelEndPath::new(&msg.port_id_on_a, &msg.chan_id_on_a); - let chan_end_on_a = ctx_a.channel_end(chan_end_path_on_a)?; - - // Validate that the channel end is in a state where it can be ack. - if !chan_end_on_a.state_matches(&State::Init) { - return Err(ChannelError::InvalidChannelState { - channel_id: msg.chan_id_on_a.clone(), - state: chan_end_on_a.state, - }); - } - - // An OPEN IBC connection running on the local (host) chain should exist. - - if chan_end_on_a.connection_hops().len() != 1 { - return Err(ChannelError::InvalidConnectionHopsLength { - expected: 1, - actual: chan_end_on_a.connection_hops().len(), - }); - } - - let conn_end_on_a = ctx_a.connection_end(&chan_end_on_a.connection_hops()[0])?; - - if !conn_end_on_a.state_matches(&ConnectionState::Open) { - return Err(ChannelError::ConnectionNotOpen { - connection_id: chan_end_on_a.connection_hops()[0].clone(), - }); - } - - // Verify proofs - { - let client_id_on_a = conn_end_on_a.client_id(); - let client_state_of_b_on_a = ctx_a.client_state(client_id_on_a)?; - let client_cons_state_path_on_a = - ClientConsensusStatePath::new(client_id_on_a, &msg.proof_height_on_b); - let consensus_state_of_b_on_a = - ctx_a.client_consensus_state(&client_cons_state_path_on_a)?; - let prefix_on_b = conn_end_on_a.counterparty().prefix(); - let port_id_on_b = &chan_end_on_a.counterparty().port_id; - let conn_id_on_b = conn_end_on_a.counterparty().connection_id().ok_or( - ChannelError::UndefinedConnectionCounterparty { - connection_id: chan_end_on_a.connection_hops()[0].clone(), - }, - )?; - - // The client must not be frozen. - if client_state_of_b_on_a.is_frozen() { - return Err(ChannelError::FrozenClient { - client_id: client_id_on_a.clone(), - }); - } - - let expected_chan_end_on_b = ChannelEnd::new( - State::TryOpen, - // Note: Both ends of a channel must have the same ordering, so it's - // fine to use A's ordering here - *chan_end_on_a.ordering(), - Counterparty::new(msg.port_id_on_a.clone(), Some(msg.chan_id_on_a.clone())), - vec![conn_id_on_b.clone()], - msg.version_on_b.clone(), - ); - let chan_end_path_on_b = ChannelEndPath::new(port_id_on_b, &msg.chan_id_on_b); - - // Verify the proof for the channel state against the expected channel end. - // A counterparty channel id of None in not possible, and is checked by validate_basic in msg. - client_state_of_b_on_a - .verify_channel_state( - msg.proof_height_on_b, - prefix_on_b, - &msg.proof_chan_end_on_b, - consensus_state_of_b_on_a.root(), - &chan_end_path_on_b, - &expected_chan_end_on_b, - ) - .map_err(ChannelError::VerifyChannelFailed)?; - } - - output.log("success: channel open ack"); - - // Transition the channel end to the new state & pick a version. - let new_chan_end_on_a = { - let mut chan_end_on_a = chan_end_on_a; - - chan_end_on_a.set_state(State::Open); - chan_end_on_a.set_version(msg.version_on_b.clone()); - chan_end_on_a.set_counterparty_channel_id(msg.chan_id_on_b.clone()); - - chan_end_on_a - }; - - let result = ChannelResult { - port_id: msg.port_id_on_a.clone(), - channel_id: msg.chan_id_on_a.clone(), - channel_id_state: ChannelIdState::Reused, - channel_end: new_chan_end_on_a, - }; - - Ok(output.with_result(result)) -} - #[cfg(test)] mod tests { diff --git a/crates/ibc/src/core/ics04_channel/handler/chan_open_confirm.rs b/crates/ibc/src/core/ics04_channel/handler/chan_open_confirm.rs index d8f096a2a..df4bdda32 100644 --- a/crates/ibc/src/core/ics04_channel/handler/chan_open_confirm.rs +++ b/crates/ibc/src/core/ics04_channel/handler/chan_open_confirm.rs @@ -1,12 +1,9 @@ //! Protocol logic specific to ICS4 messages of type `MsgChannelOpenConfirm`. use crate::core::ics03_connection::connection::State as ConnectionState; use crate::core::ics04_channel::channel::{ChannelEnd, Counterparty, State}; -use crate::core::ics04_channel::context::ChannelReader; use crate::core::ics04_channel::error::ChannelError; -use crate::core::ics04_channel::handler::{ChannelIdState, ChannelResult}; use crate::core::ics04_channel::msgs::chan_open_confirm::MsgChannelOpenConfirm; use crate::core::ics24_host::path::{ChannelEndPath, ClientConsensusStatePath}; -use crate::handler::{HandlerOutput, HandlerResult}; use crate::prelude::*; use crate::core::{ContextError, ValidationContext}; @@ -99,106 +96,6 @@ where Ok(()) } -/// Per our convention, this message is processed on chain B. -pub(crate) fn process( - ctx_b: &Ctx, - msg: &MsgChannelOpenConfirm, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - // Unwrap the old channel end and validate it against the message. - let chan_end_path_on_b = ChannelEndPath::new(&msg.port_id_on_b, &msg.chan_id_on_b); - let mut chan_end_on_b = ctx_b.channel_end(&chan_end_path_on_b)?; - - // Validate that the channel end is in a state where it can be confirmed. - if !chan_end_on_b.state_matches(&State::TryOpen) { - return Err(ChannelError::InvalidChannelState { - channel_id: msg.chan_id_on_b.clone(), - state: chan_end_on_b.state, - }); - } - - // An OPEN IBC connection running on the local (host) chain should exist. - if chan_end_on_b.connection_hops().len() != 1 { - return Err(ChannelError::InvalidConnectionHopsLength { - expected: 1, - actual: chan_end_on_b.connection_hops().len(), - }); - } - - let conn_end_on_b = ctx_b.connection_end(&chan_end_on_b.connection_hops()[0])?; - - if !conn_end_on_b.state_matches(&ConnectionState::Open) { - return Err(ChannelError::ConnectionNotOpen { - connection_id: chan_end_on_b.connection_hops()[0].clone(), - }); - } - - // Verify proofs - { - let client_id_on_b = conn_end_on_b.client_id(); - let client_state_of_a_on_b = ctx_b.client_state(client_id_on_b)?; - let client_cons_state_path_on_b = - ClientConsensusStatePath::new(client_id_on_b, &msg.proof_height_on_a); - let consensus_state_of_a_on_b = - ctx_b.client_consensus_state(&client_cons_state_path_on_b)?; - let prefix_on_a = conn_end_on_b.counterparty().prefix(); - let port_id_on_a = &chan_end_on_b.counterparty().port_id; - let chan_id_on_a = chan_end_on_b - .counterparty() - .channel_id() - .ok_or(ChannelError::InvalidCounterpartyChannelId)?; - let conn_id_on_a = conn_end_on_b.counterparty().connection_id().ok_or( - ChannelError::UndefinedConnectionCounterparty { - connection_id: chan_end_on_b.connection_hops()[0].clone(), - }, - )?; - - // The client must not be frozen. - if client_state_of_a_on_b.is_frozen() { - return Err(ChannelError::FrozenClient { - client_id: client_id_on_b.clone(), - }); - } - - let expected_chan_end_on_a = ChannelEnd::new( - State::Open, - *chan_end_on_b.ordering(), - Counterparty::new(msg.port_id_on_b.clone(), Some(msg.chan_id_on_b.clone())), - vec![conn_id_on_a.clone()], - chan_end_on_b.version.clone(), - ); - let chan_end_path_on_a = ChannelEndPath::new(port_id_on_a, chan_id_on_a); - - // Verify the proof for the channel state against the expected channel end. - // A counterparty channel id of None in not possible, and is checked in msg. - client_state_of_a_on_b - .verify_channel_state( - msg.proof_height_on_a, - prefix_on_a, - &msg.proof_chan_end_on_a, - consensus_state_of_a_on_b.root(), - &chan_end_path_on_a, - &expected_chan_end_on_a, - ) - .map_err(ChannelError::VerifyChannelFailed)?; - } - - output.log("success: channel open confirm "); - - // Transition the channel end to the new state. - chan_end_on_b.set_state(State::Open); - - let result = ChannelResult { - port_id: msg.port_id_on_b.clone(), - channel_id: msg.chan_id_on_b.clone(), - channel_id_state: ChannelIdState::Reused, - channel_end: chan_end_on_b, - }; - - Ok(output.with_result(result)) -} - #[cfg(test)] mod tests { use crate::core::ics04_channel::handler::chan_open_confirm::validate; diff --git a/crates/ibc/src/core/ics04_channel/handler/chan_open_init.rs b/crates/ibc/src/core/ics04_channel/handler/chan_open_init.rs index 77f0cfe52..d6c2f191f 100644 --- a/crates/ibc/src/core/ics04_channel/handler/chan_open_init.rs +++ b/crates/ibc/src/core/ics04_channel/handler/chan_open_init.rs @@ -1,12 +1,7 @@ //! Protocol logic specific to ICS4 messages of type `MsgChannelOpenInit`. -use crate::core::ics04_channel::channel::{ChannelEnd, Counterparty, State}; -use crate::core::ics04_channel::context::ChannelReader; use crate::core::ics04_channel::error::ChannelError; -use crate::core::ics04_channel::handler::{ChannelIdState, ChannelResult}; use crate::core::ics04_channel::msgs::chan_open_init::MsgChannelOpenInit; -use crate::core::ics24_host::identifier::ChannelId; -use crate::handler::{HandlerOutput, HandlerResult}; use crate::prelude::*; use crate::core::{ContextError, ValidationContext}; @@ -39,57 +34,6 @@ where Ok(()) } -/// Per our convention, this message is processed on chain A. -pub(crate) fn process( - ctx_a: &Ctx, - msg: &MsgChannelOpenInit, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - if msg.connection_hops_on_a.len() != 1 { - return Err(ChannelError::InvalidConnectionHopsLength { - expected: 1, - actual: msg.connection_hops_on_a.len(), - }); - } - - // An IBC connection running on the local (host) chain should exist. - let conn_end_on_a = ctx_a.connection_end(&msg.connection_hops_on_a[0])?; - - let conn_version = match conn_end_on_a.versions() { - [version] => version, - _ => return Err(ChannelError::InvalidVersionLengthConnection), - }; - - let channel_feature = msg.ordering.to_string(); - if !conn_version.is_supported_feature(channel_feature) { - return Err(ChannelError::ChannelFeatureNotSuportedByConnection); - } - - let chan_end_on_a = ChannelEnd::new( - State::Init, - msg.ordering, - Counterparty::new(msg.port_id_on_b.clone(), None), - msg.connection_hops_on_a.clone(), - msg.version_proposal.clone(), - ); - - let chan_id_on_a = ChannelId::new(ctx_a.channel_counter()?); - - output.log(format!( - "success: channel open init with channel identifier: {chan_id_on_a}" - )); - - let result = ChannelResult { - port_id: msg.port_id_on_a.clone(), - channel_id: chan_id_on_a, - channel_end: chan_end_on_a, - channel_id_state: ChannelIdState::Generated, - }; - - Ok(output.with_result(result)) -} - #[cfg(test)] mod tests { use crate::core::ics04_channel::handler::chan_open_init::validate; diff --git a/crates/ibc/src/core/ics04_channel/handler/chan_open_try.rs b/crates/ibc/src/core/ics04_channel/handler/chan_open_try.rs index 794bf3146..af92e452b 100644 --- a/crates/ibc/src/core/ics04_channel/handler/chan_open_try.rs +++ b/crates/ibc/src/core/ics04_channel/handler/chan_open_try.rs @@ -2,14 +2,9 @@ use crate::core::ics03_connection::connection::State as ConnectionState; use crate::core::ics04_channel::channel::{ChannelEnd, Counterparty, State}; -use crate::core::ics04_channel::context::ChannelReader; use crate::core::ics04_channel::error::ChannelError; -use crate::core::ics04_channel::handler::{ChannelIdState, ChannelResult}; use crate::core::ics04_channel::msgs::chan_open_try::MsgChannelOpenTry; -use crate::core::ics04_channel::Version; -use crate::core::ics24_host::identifier::ChannelId; use crate::core::ics24_host::path::{ChannelEndPath, ClientConsensusStatePath}; -use crate::handler::{HandlerOutput, HandlerResult}; use crate::prelude::*; use crate::core::{ContextError, ValidationContext}; @@ -99,110 +94,6 @@ where Ok(()) } -/// Per our convention, this message is processed on chain B. -pub(crate) fn process( - ctx_b: &Ctx, - msg: &MsgChannelOpenTry, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - // An IBC connection running on the local (host) chain should exist. - if msg.connection_hops_on_b.len() != 1 { - return Err(ChannelError::InvalidConnectionHopsLength { - expected: 1, - actual: msg.connection_hops_on_b.len(), - }); - } - - let conn_end_on_b = ctx_b.connection_end(&msg.connection_hops_on_b[0])?; - if !conn_end_on_b.state_matches(&ConnectionState::Open) { - return Err(ChannelError::ConnectionNotOpen { - connection_id: msg.connection_hops_on_b[0].clone(), - }); - } - - let conn_version = match conn_end_on_b.versions() { - [version] => version, - _ => return Err(ChannelError::InvalidVersionLengthConnection), - }; - - let channel_feature = msg.ordering.to_string(); - if !conn_version.is_supported_feature(channel_feature) { - return Err(ChannelError::ChannelFeatureNotSuportedByConnection); - } - - // Verify proofs - { - let client_id_on_b = conn_end_on_b.client_id(); - let client_state_of_a_on_b = ctx_b.client_state(client_id_on_b)?; - let client_cons_state_path_on_b = - ClientConsensusStatePath::new(client_id_on_b, &msg.proof_height_on_a); - let consensus_state_of_a_on_b = - ctx_b.client_consensus_state(&client_cons_state_path_on_b)?; - let prefix_on_a = conn_end_on_b.counterparty().prefix(); - let port_id_on_a = msg.port_id_on_a.clone(); - let chan_id_on_a = msg.chan_id_on_a.clone(); - let conn_id_on_a = conn_end_on_b.counterparty().connection_id().ok_or( - ChannelError::UndefinedConnectionCounterparty { - connection_id: msg.connection_hops_on_b[0].clone(), - }, - )?; - - // The client must not be frozen. - if client_state_of_a_on_b.is_frozen() { - return Err(ChannelError::FrozenClient { - client_id: client_id_on_b.clone(), - }); - } - - let expected_chan_end_on_a = ChannelEnd::new( - State::Init, - msg.ordering, - Counterparty::new(msg.port_id_on_b.clone(), None), - vec![conn_id_on_a.clone()], - msg.version_supported_on_a.clone(), - ); - let chan_end_path_on_a = ChannelEndPath::new(&port_id_on_a, &chan_id_on_a); - - // Verify the proof for the channel state against the expected channel end. - // A counterparty channel id of None in not possible, and is checked by validate_basic in msg. - client_state_of_a_on_b - .verify_channel_state( - msg.proof_height_on_a, - prefix_on_a, - &msg.proof_chan_end_on_a, - consensus_state_of_a_on_b.root(), - &chan_end_path_on_a, - &expected_chan_end_on_a, - ) - .map_err(ChannelError::VerifyChannelFailed)?; - } - - let chan_end_on_b = ChannelEnd::new( - State::TryOpen, - msg.ordering, - Counterparty::new(msg.port_id_on_a.clone(), Some(msg.chan_id_on_a.clone())), - msg.connection_hops_on_b.clone(), - // Note: This will be rewritten by the module callback - Version::empty(), - ); - - let chan_id_on_b = ChannelId::new(ctx_b.channel_counter()?); - - output.log(format!( - "success: channel open try with channel identifier: {chan_id_on_b}" - )); - - let result = ChannelResult { - port_id: msg.port_id_on_b.clone(), - channel_id: chan_id_on_b, - channel_end: chan_end_on_b, - channel_id_state: ChannelIdState::Generated, - }; - - Ok(output.with_result(result)) -} - #[cfg(test)] mod tests { use crate::prelude::*; diff --git a/crates/ibc/src/core/ics04_channel/handler/recv_packet.rs b/crates/ibc/src/core/ics04_channel/handler/recv_packet.rs index 3cec8733e..62c67d569 100644 --- a/crates/ibc/src/core/ics04_channel/handler/recv_packet.rs +++ b/crates/ibc/src/core/ics04_channel/handler/recv_packet.rs @@ -1,17 +1,11 @@ use crate::core::ics03_connection::connection::State as ConnectionState; use crate::core::ics04_channel::channel::{Counterparty, Order, State}; -use crate::core::ics04_channel::context::ChannelReader; use crate::core::ics04_channel::error::ChannelError; use crate::core::ics04_channel::error::PacketError; -use crate::core::ics04_channel::events::ReceivePacket; use crate::core::ics04_channel::msgs::recv_packet::MsgRecvPacket; -use crate::core::ics04_channel::packet::{PacketResult, Receipt, Sequence}; -use crate::core::ics24_host::identifier::{ChannelId, PortId}; use crate::core::ics24_host::path::{ AckPath, ChannelEndPath, ClientConsensusStatePath, CommitmentPath, ReceiptPath, SeqRecvPath, }; -use crate::events::IbcEvent; -use crate::handler::{HandlerOutput, HandlerResult}; use crate::timestamp::Expiry; use crate::core::{ContextError, ValidationContext}; @@ -98,7 +92,7 @@ where // Verify the proof for the packet against the chain store. client_state_of_a_on_b - .new_verify_packet_data( + .verify_packet_data( ctx_b, msg.proof_height_on_a, &conn_end_on_b, @@ -167,181 +161,6 @@ where Ok(()) } -#[derive(Clone, Debug)] -pub enum RecvPacketResult { - NoOp, - Unordered { - port_id: PortId, - channel_id: ChannelId, - sequence: Sequence, - receipt: Receipt, - }, - Ordered { - port_id: PortId, - channel_id: ChannelId, - next_seq_recv: Sequence, - }, -} - -/// Per our convention, this message is processed on chain B. -pub(crate) fn process( - ctx_b: &Ctx, - msg: &MsgRecvPacket, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - let chan_end_path_on_b = ChannelEndPath::new(&msg.packet.port_on_b, &msg.packet.chan_on_b); - let chan_end_on_b = ctx_b - .channel_end(&chan_end_path_on_b) - .map_err(PacketError::Channel)?; - - if !chan_end_on_b.state_matches(&State::Open) { - return Err(PacketError::InvalidChannelState { - channel_id: msg.packet.chan_on_a.clone(), - state: chan_end_on_b.state, - }); - } - - let counterparty = Counterparty::new( - msg.packet.port_on_a.clone(), - Some(msg.packet.chan_on_a.clone()), - ); - - if !chan_end_on_b.counterparty_matches(&counterparty) { - return Err(PacketError::InvalidPacketCounterparty { - port_id: msg.packet.port_on_a.clone(), - channel_id: msg.packet.chan_on_a.clone(), - }); - } - - let conn_id_on_b = &chan_end_on_b.connection_hops()[0]; - let conn_end_on_b = ctx_b - .connection_end(conn_id_on_b) - .map_err(PacketError::Channel)?; - - if !conn_end_on_b.state_matches(&ConnectionState::Open) { - return Err(PacketError::ConnectionNotOpen { - connection_id: chan_end_on_b.connection_hops()[0].clone(), - }); - } - - let latest_height = ChannelReader::host_height(ctx_b).map_err(PacketError::Channel)?; - if msg.packet.timeout_height_on_b.has_expired(latest_height) { - return Err(PacketError::LowPacketHeight { - chain_height: latest_height, - timeout_height: msg.packet.timeout_height_on_b, - }); - } - - let latest_timestamp = ChannelReader::host_timestamp(ctx_b).map_err(PacketError::Channel)?; - if let Expiry::Expired = latest_timestamp.check_expiry(&msg.packet.timeout_timestamp_on_b) { - return Err(PacketError::LowPacketTimestamp); - } - - // Verify proofs - { - let client_id_on_b = conn_end_on_b.client_id(); - let client_state_of_a_on_b = ctx_b - .client_state(client_id_on_b) - .map_err(PacketError::Channel)?; - - // The client must not be frozen. - if client_state_of_a_on_b.is_frozen() { - return Err(PacketError::FrozenClient { - client_id: client_id_on_b.clone(), - }); - } - - let client_cons_state_path_on_b = - ClientConsensusStatePath::new(client_id_on_b, &msg.proof_height_on_a); - let consensus_state_of_a_on_b = ctx_b - .client_consensus_state(&client_cons_state_path_on_b) - .map_err(PacketError::Channel)?; - - let expected_commitment_on_a = ctx_b.packet_commitment( - &msg.packet.data, - &msg.packet.timeout_height_on_b, - &msg.packet.timeout_timestamp_on_b, - ); - - let commitment_path_on_a = CommitmentPath::new( - &msg.packet.port_on_a, - &msg.packet.chan_on_a, - msg.packet.sequence, - ); - - // Verify the proof for the packet against the chain store. - client_state_of_a_on_b - .verify_packet_data( - ctx_b, - msg.proof_height_on_a, - &conn_end_on_b, - &msg.proof_commitment_on_a, - consensus_state_of_a_on_b.root(), - &commitment_path_on_a, - expected_commitment_on_a, - ) - .map_err(|e| ChannelError::PacketVerificationFailed { - sequence: msg.packet.sequence, - client_error: e, - }) - .map_err(PacketError::Channel)?; - } - - let result = if chan_end_on_b.order_matches(&Order::Ordered) { - let seq_recv_path_on_b = SeqRecvPath::new(&msg.packet.port_on_b, &msg.packet.chan_on_b); - let next_seq_recv = ctx_b.get_next_sequence_recv(&seq_recv_path_on_b)?; - if msg.packet.sequence > next_seq_recv { - return Err(PacketError::InvalidPacketSequence { - given_sequence: msg.packet.sequence, - next_sequence: next_seq_recv, - }); - } - - if msg.packet.sequence < next_seq_recv { - PacketResult::Recv(RecvPacketResult::NoOp) - } else { - PacketResult::Recv(RecvPacketResult::Ordered { - port_id: msg.packet.port_on_b.clone(), - channel_id: msg.packet.chan_on_b.clone(), - next_seq_recv: next_seq_recv.increment(), - }) - } - } else { - let receipt_path_on_b = ReceiptPath::new( - &msg.packet.port_on_b, - &msg.packet.chan_on_b, - msg.packet.sequence, - ); - let packet_rec = ctx_b.get_packet_receipt(&receipt_path_on_b); - match packet_rec { - Ok(_receipt) => PacketResult::Recv(RecvPacketResult::NoOp), - Err(PacketError::PacketReceiptNotFound { sequence }) - if sequence == msg.packet.sequence => - { - // store a receipt that does not contain any data - PacketResult::Recv(RecvPacketResult::Unordered { - port_id: msg.packet.port_on_b.clone(), - channel_id: msg.packet.chan_on_b.clone(), - sequence: msg.packet.sequence, - receipt: Receipt::Ok, - }) - } - Err(e) => return Err(e), - } - }; - - output.log("success: packet receive"); - - output.emit(IbcEvent::ReceivePacket(ReceivePacket::new( - msg.packet.clone(), - chan_end_on_b.ordering, - conn_id_on_b.clone(), - ))); - - Ok(output.with_result(result)) -} - #[cfg(test)] mod tests { use crate::core::ics04_channel::handler::recv_packet::validate; diff --git a/crates/ibc/src/core/ics04_channel/handler/timeout.rs b/crates/ibc/src/core/ics04_channel/handler/timeout.rs index 9f3f7089c..095d82dcd 100644 --- a/crates/ibc/src/core/ics04_channel/handler/timeout.rs +++ b/crates/ibc/src/core/ics04_channel/handler/timeout.rs @@ -1,16 +1,11 @@ use crate::core::ics04_channel::channel::State; -use crate::core::ics04_channel::channel::{ChannelEnd, Counterparty, Order}; +use crate::core::ics04_channel::channel::{Counterparty, Order}; use crate::core::ics04_channel::error::ChannelError; -use crate::core::ics04_channel::events::{ChannelClosed, TimeoutPacket}; +use crate::core::ics04_channel::error::PacketError; use crate::core::ics04_channel::msgs::timeout::MsgTimeout; -use crate::core::ics04_channel::packet::{PacketResult, Sequence}; -use crate::core::ics04_channel::{context::ChannelReader, error::PacketError}; -use crate::core::ics24_host::identifier::{ChannelId, PortId}; use crate::core::ics24_host::path::{ ChannelEndPath, ClientConsensusStatePath, CommitmentPath, ReceiptPath, SeqRecvPath, }; -use crate::events::IbcEvent; -use crate::handler::{HandlerOutput, HandlerResult}; use crate::prelude::*; use crate::timestamp::Expiry; @@ -118,150 +113,6 @@ where .into()); } let seq_recv_path_on_b = SeqRecvPath::new(&msg.packet.port_on_b, &msg.packet.chan_on_b); - client_state_of_b_on_a.new_verify_next_sequence_recv( - ctx_a, - msg.proof_height_on_b, - &conn_end_on_a, - &msg.proof_unreceived_on_b, - consensus_state_of_b_on_a.root(), - &seq_recv_path_on_b, - msg.packet.sequence, - ) - } else { - let receipt_path_on_b = ReceiptPath::new( - &msg.packet.port_on_b, - &msg.packet.chan_on_b, - msg.packet.sequence, - ); - client_state_of_b_on_a.new_verify_packet_receipt_absence( - ctx_a, - msg.proof_height_on_b, - &conn_end_on_a, - &msg.proof_unreceived_on_b, - consensus_state_of_b_on_a.root(), - &receipt_path_on_b, - ) - }; - next_seq_recv_verification_result - .map_err(|e| ChannelError::PacketVerificationFailed { - sequence: msg.next_seq_recv_on_b, - client_error: e, - }) - .map_err(PacketError::Channel)?; - } - - Ok(()) -} - -#[derive(Clone, Debug)] -pub struct TimeoutPacketResult { - pub port_id: PortId, - pub channel_id: ChannelId, - pub seq: Sequence, - pub channel: Option, -} - -/// TimeoutPacket is called by a module which originally attempted to send a -/// packet to a counterparty module, where the timeout height has passed on the -/// counterparty chain without the packet being committed, to prove that the -/// packet can no longer be executed and to allow the calling module to safely -/// perform appropriate state transitions. -/// Per our convention, this message is processed on chain A. -pub(crate) fn process( - ctx_a: &Ctx, - msg: &MsgTimeout, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - let chan_end_path_on_a = ChannelEndPath::new(&msg.packet.port_on_a, &msg.packet.chan_on_a); - let mut chan_end_on_a = ctx_a - .channel_end(&chan_end_path_on_a) - .map_err(PacketError::Channel)?; - - if !chan_end_on_a.state_matches(&State::Open) { - return Err(PacketError::ChannelClosed { - channel_id: msg.packet.chan_on_a.clone(), - }); - } - - let counterparty = Counterparty::new( - msg.packet.port_on_b.clone(), - Some(msg.packet.chan_on_b.clone()), - ); - - if !chan_end_on_a.counterparty_matches(&counterparty) { - return Err(PacketError::InvalidPacketCounterparty { - port_id: msg.packet.port_on_b.clone(), - channel_id: msg.packet.chan_on_b.clone(), - }); - } - - let conn_id_on_a = chan_end_on_a.connection_hops()[0].clone(); - let conn_end_on_a = ctx_a - .connection_end(&conn_id_on_a) - .map_err(PacketError::Channel)?; - - //verify packet commitment - let commitment_path_on_a = CommitmentPath::new( - &msg.packet.port_on_a, - &msg.packet.chan_on_a, - msg.packet.sequence, - ); - let commitment_on_a = ctx_a.get_packet_commitment(&commitment_path_on_a)?; - let expected_commitment_on_a = ctx_a.packet_commitment( - &msg.packet.data, - &msg.packet.timeout_height_on_b, - &msg.packet.timeout_timestamp_on_b, - ); - if commitment_on_a != expected_commitment_on_a { - return Err(PacketError::IncorrectPacketCommitment { - sequence: msg.packet.sequence, - }); - } - - // Verify proofs - { - let client_id_on_a = conn_end_on_a.client_id(); - let client_state_of_b_on_a = ctx_a - .client_state(client_id_on_a) - .map_err(PacketError::Channel)?; - - // check that timeout height or timeout timestamp has passed on the other end - if msg - .packet - .timeout_height_on_b - .has_expired(msg.proof_height_on_b) - { - return Err(PacketError::PacketTimeoutHeightNotReached { - timeout_height: msg.packet.timeout_height_on_b, - chain_height: msg.proof_height_on_b, - }); - } - - let client_cons_state_path = - ClientConsensusStatePath::new(client_id_on_a, &msg.proof_height_on_b); - let consensus_state_of_b_on_a = ctx_a - .client_consensus_state(&client_cons_state_path) - .map_err(PacketError::Channel)?; - let timestamp_of_b = consensus_state_of_b_on_a.timestamp(); - - if let Expiry::Expired = msg - .packet - .timeout_timestamp_on_b - .check_expiry(×tamp_of_b) - { - return Err(PacketError::PacketTimeoutTimestampNotReached { - timeout_timestamp: msg.packet.timeout_timestamp_on_b, - chain_timestamp: timestamp_of_b, - }); - } - let next_seq_recv_verification_result = if chan_end_on_a.order_matches(&Order::Ordered) { - if msg.packet.sequence < msg.next_seq_recv_on_b { - return Err(PacketError::InvalidPacketSequence { - given_sequence: msg.packet.sequence, - next_sequence: msg.next_seq_recv_on_b, - }); - } - let seq_recv_path_on_b = SeqRecvPath::new(&msg.packet.port_on_b, &msg.packet.chan_on_b); client_state_of_b_on_a.verify_next_sequence_recv( ctx_a, msg.proof_height_on_b, @@ -294,36 +145,7 @@ pub(crate) fn process( .map_err(PacketError::Channel)?; } - output.log("success: packet timeout "); - - output.emit(IbcEvent::TimeoutPacket(TimeoutPacket::new( - msg.packet.clone(), - chan_end_on_a.ordering, - ))); - - let packet_res_chan = if chan_end_on_a.order_matches(&Order::Ordered) { - output.emit(IbcEvent::ChannelClosed(ChannelClosed::new( - msg.packet.port_on_a.clone(), - msg.packet.chan_on_a.clone(), - chan_end_on_a.counterparty().port_id.clone(), - chan_end_on_a.counterparty().channel_id.clone(), - conn_id_on_a, - chan_end_on_a.ordering, - ))); - chan_end_on_a.state = State::Closed; - Some(chan_end_on_a) - } else { - None - }; - - let result = PacketResult::Timeout(TimeoutPacketResult { - port_id: msg.packet.port_on_a.clone(), - channel_id: msg.packet.chan_on_a.clone(), - seq: msg.packet.sequence, - channel: packet_res_chan, - }); - - Ok(output.with_result(result)) + Ok(()) } #[cfg(test)] diff --git a/crates/ibc/src/core/ics04_channel/handler/timeout_on_close.rs b/crates/ibc/src/core/ics04_channel/handler/timeout_on_close.rs index 8409e0f32..650d2684f 100644 --- a/crates/ibc/src/core/ics04_channel/handler/timeout_on_close.rs +++ b/crates/ibc/src/core/ics04_channel/handler/timeout_on_close.rs @@ -1,17 +1,10 @@ use crate::core::ics04_channel::channel::State; use crate::core::ics04_channel::channel::{ChannelEnd, Counterparty, Order}; -use crate::core::ics04_channel::error::ChannelError; -use crate::core::ics04_channel::events::{ChannelClosed, TimeoutPacket}; +use crate::core::ics04_channel::error::{ChannelError, PacketError}; use crate::core::ics04_channel::msgs::timeout_on_close::MsgTimeoutOnClose; -use crate::core::ics04_channel::packet::PacketResult; -use crate::core::ics04_channel::{ - context::ChannelReader, error::PacketError, handler::timeout::TimeoutPacketResult, -}; use crate::core::ics24_host::path::{ ChannelEndPath, ClientConsensusStatePath, CommitmentPath, ReceiptPath, SeqRecvPath, }; -use crate::events::IbcEvent; -use crate::handler::{HandlerOutput, HandlerResult}; use crate::prelude::*; use crate::core::{ContextError, ValidationContext}; @@ -131,153 +124,6 @@ where .into()); } let seq_recv_path_on_b = SeqRecvPath::new(&packet.port_on_b, &packet.chan_on_b); - client_state_of_b_on_a.new_verify_next_sequence_recv( - ctx_a, - msg.proof_height_on_b, - &conn_end_on_a, - &msg.proof_unreceived_on_b, - consensus_state_of_b_on_a.root(), - &seq_recv_path_on_b, - packet.sequence, - ) - } else { - let receipt_path_on_b = ReceiptPath::new( - &msg.packet.port_on_b, - &msg.packet.chan_on_b, - msg.packet.sequence, - ); - client_state_of_b_on_a.new_verify_packet_receipt_absence( - ctx_a, - msg.proof_height_on_b, - &conn_end_on_a, - &msg.proof_unreceived_on_b, - consensus_state_of_b_on_a.root(), - &receipt_path_on_b, - ) - }; - next_seq_recv_verification_result - .map_err(|e| ChannelError::PacketVerificationFailed { - sequence: msg.next_seq_recv_on_b, - client_error: e, - }) - .map_err(PacketError::Channel)?; - }; - - Ok(()) -} - -/// Per our convention, this message is processed on chain A. -pub(crate) fn process( - ctx_a: &Ctx, - msg: &MsgTimeoutOnClose, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - - let packet = &msg.packet; - - let chan_end_path_on_a = ChannelEndPath::new(&packet.port_on_a, &packet.chan_on_a); - let chan_end_on_a = ctx_a - .channel_end(&chan_end_path_on_a) - .map_err(PacketError::Channel)?; - - let counterparty = Counterparty::new(packet.port_on_b.clone(), Some(packet.chan_on_b.clone())); - - if !chan_end_on_a.counterparty_matches(&counterparty) { - return Err(PacketError::InvalidPacketCounterparty { - port_id: packet.port_on_b.clone(), - channel_id: packet.chan_on_b.clone(), - }); - } - - let commitment_path_on_a = - CommitmentPath::new(&packet.port_on_a, &packet.chan_on_a, packet.sequence); - - //verify the packet was sent, check the store - let commitment_on_a = ctx_a.get_packet_commitment(&commitment_path_on_a)?; - - let expected_commitment_on_a = ctx_a.packet_commitment( - &packet.data, - &packet.timeout_height_on_b, - &packet.timeout_timestamp_on_b, - ); - if commitment_on_a != expected_commitment_on_a { - return Err(PacketError::IncorrectPacketCommitment { - sequence: packet.sequence, - }); - } - - let conn_id_on_a = chan_end_on_a.connection_hops()[0].clone(); - let conn_end_on_a = ctx_a - .connection_end(&conn_id_on_a) - .map_err(PacketError::Channel)?; - - // Verify proofs - { - let client_id_on_a = conn_end_on_a.client_id(); - let client_state_of_b_on_a = ctx_a - .client_state(client_id_on_a) - .map_err(PacketError::Channel)?; - - // The client must not be frozen. - if client_state_of_b_on_a.is_frozen() { - return Err(PacketError::FrozenClient { - client_id: client_id_on_a.clone(), - }); - } - let client_cons_state_on_a = - ClientConsensusStatePath::new(client_id_on_a, &msg.proof_height_on_b); - let consensus_state_of_b_on_a = ctx_a - .client_consensus_state(&client_cons_state_on_a) - .map_err(PacketError::Channel)?; - let prefix_on_b = conn_end_on_a.counterparty().prefix(); - let port_id_on_b = chan_end_on_a.counterparty().port_id.clone(); - let chan_id_on_b = - chan_end_on_a - .counterparty() - .channel_id() - .ok_or(PacketError::Channel( - ChannelError::InvalidCounterpartyChannelId, - ))?; - let conn_id_on_b = conn_end_on_a.counterparty().connection_id().ok_or( - PacketError::UndefinedConnectionCounterparty { - connection_id: chan_end_on_a.connection_hops()[0].clone(), - }, - )?; - let expected_conn_hops_on_b = vec![conn_id_on_b.clone()]; - let expected_counterparty = - Counterparty::new(packet.port_on_a.clone(), Some(packet.chan_on_a.clone())); - let expected_chan_end_on_b = ChannelEnd::new( - State::Closed, - *chan_end_on_a.ordering(), - expected_counterparty, - expected_conn_hops_on_b, - chan_end_on_a.version().clone(), - ); - - let chan_end_path_on_b = ChannelEndPath::new(&port_id_on_b, chan_id_on_b); - - // Verify the proof for the channel state against the expected channel end. - // A counterparty channel id of None in not possible, and is checked by validate_basic in msg. - client_state_of_b_on_a - .verify_channel_state( - msg.proof_height_on_b, - prefix_on_b, - &msg.proof_unreceived_on_b, - consensus_state_of_b_on_a.root(), - &chan_end_path_on_b, - &expected_chan_end_on_b, - ) - .map_err(ChannelError::VerifyChannelFailed) - .map_err(PacketError::Channel)?; - - let next_seq_recv_verification_result = if chan_end_on_a.order_matches(&Order::Ordered) { - if packet.sequence < msg.next_seq_recv_on_b { - return Err(PacketError::InvalidPacketSequence { - given_sequence: packet.sequence, - next_sequence: msg.next_seq_recv_on_b, - }); - } - let seq_recv_path_on_b = SeqRecvPath::new(&packet.port_on_b, &packet.chan_on_b); client_state_of_b_on_a.verify_next_sequence_recv( ctx_a, msg.proof_height_on_b, @@ -310,35 +156,7 @@ pub(crate) fn process( .map_err(PacketError::Channel)?; }; - output.log("success: packet timeout"); - - output.emit(IbcEvent::TimeoutPacket(TimeoutPacket::new( - packet.clone(), - chan_end_on_a.ordering, - ))); - - let packet_res_chan = if chan_end_on_a.order_matches(&Order::Ordered) { - output.emit(IbcEvent::ChannelClosed(ChannelClosed::new( - msg.packet.port_on_a.clone(), - msg.packet.chan_on_a.clone(), - chan_end_on_a.counterparty().port_id.clone(), - chan_end_on_a.counterparty().channel_id.clone(), - conn_id_on_a, - chan_end_on_a.ordering, - ))); - Some(chan_end_on_a) - } else { - None - }; - - let result = PacketResult::Timeout(TimeoutPacketResult { - port_id: packet.port_on_a.clone(), - channel_id: packet.chan_on_a.clone(), - seq: packet.sequence, - channel: packet_res_chan, - }); - - Ok(output.with_result(result)) + Ok(()) } #[cfg(test)] diff --git a/crates/ibc/src/core/ics04_channel/handler/write_acknowledgement.rs b/crates/ibc/src/core/ics04_channel/handler/write_acknowledgement.rs deleted file mode 100644 index fed5b1c2f..000000000 --- a/crates/ibc/src/core/ics04_channel/handler/write_acknowledgement.rs +++ /dev/null @@ -1,81 +0,0 @@ -use crate::core::ics04_channel::channel::State; -use crate::core::ics04_channel::commitment::AcknowledgementCommitment; -use crate::core::ics04_channel::events::WriteAcknowledgement; -use crate::core::ics04_channel::msgs::acknowledgement::Acknowledgement; -use crate::core::ics04_channel::packet::{Packet, PacketResult, Sequence}; -use crate::core::ics04_channel::{context::ChannelReader, error::PacketError}; -use crate::core::ics24_host::identifier::{ChannelId, PortId}; -use crate::core::ics24_host::path::{AckPath, ChannelEndPath}; -use crate::prelude::*; -use crate::{ - events::IbcEvent, - handler::{HandlerOutput, HandlerResult}, -}; - -#[derive(Clone, Debug)] -pub struct WriteAckPacketResult { - pub port_id: PortId, - pub channel_id: ChannelId, - pub seq: Sequence, - pub ack_commitment: AcknowledgementCommitment, -} - -/// Per our convention, this message is processed on chain B. -pub fn process( - ctx_b: &Ctx, - packet: Packet, - ack: Acknowledgement, -) -> HandlerResult { - let mut output = HandlerOutput::builder(); - let chan_end_path_on_b = ChannelEndPath::new(&packet.port_on_b, &packet.chan_on_b); - let chan_end_on_b = ctx_b - .channel_end(&chan_end_path_on_b) - .map_err(PacketError::Channel)?; - - if !chan_end_on_b.state_matches(&State::Open) { - return Err(PacketError::InvalidChannelState { - channel_id: packet.chan_on_a, - state: chan_end_on_b.state, - }); - } - - // NOTE: IBC app modules might have written the acknowledgement synchronously on - // the OnRecvPacket callback so we need to check if the acknowledgement is already - // set on the store and return an error if so. - let ack_path_on_b = AckPath::new(&packet.port_on_b, &packet.chan_on_b, packet.sequence); - match ctx_b.get_packet_acknowledgement(&ack_path_on_b) { - Ok(_) => { - return Err(PacketError::AcknowledgementExists { - sequence: packet.sequence, - }) - } - Err(e) - if e.to_string() - == PacketError::PacketAcknowledgementNotFound { - sequence: packet.sequence, - } - .to_string() => {} - Err(e) => return Err(e), - } - - let result = PacketResult::WriteAck(WriteAckPacketResult { - port_id: packet.port_on_b.clone(), - channel_id: packet.chan_on_b.clone(), - seq: packet.sequence, - ack_commitment: ctx_b.ack_commitment(&ack), - }); - - output.log("success: packet write acknowledgement"); - - { - let conn_id_on_b = chan_end_on_b.connection_hops()[0].clone(); - - output.emit(IbcEvent::WriteAcknowledgement(WriteAcknowledgement::new( - packet, - ack, - conn_id_on_b, - ))); - } - - Ok(output.with_result(result)) -} diff --git a/crates/ibc/src/core/ics04_channel/msgs.rs b/crates/ibc/src/core/ics04_channel/msgs.rs index 5c34cee2c..d0f43b02a 100644 --- a/crates/ibc/src/core/ics04_channel/msgs.rs +++ b/crates/ibc/src/core/ics04_channel/msgs.rs @@ -1,7 +1,6 @@ //! Message definitions for all ICS4 domain types: channel open & close handshake datagrams, as well //! as packets. -use crate::core::ics04_channel::error::ChannelError; use crate::core::ics04_channel::msgs::acknowledgement::MsgAcknowledgement; use crate::core::ics04_channel::msgs::chan_close_confirm::MsgChannelCloseConfirm; use crate::core::ics04_channel::msgs::chan_close_init::MsgChannelCloseInit; @@ -12,7 +11,6 @@ use crate::core::ics04_channel::msgs::chan_open_try::MsgChannelOpenTry; use crate::core::ics04_channel::msgs::recv_packet::MsgRecvPacket; use crate::core::ics04_channel::msgs::timeout::MsgTimeout; use crate::core::ics04_channel::msgs::timeout_on_close::MsgTimeoutOnClose; -use crate::core::ics26_routing::context::{ModuleId, RouterContext}; // Opening handshake messages. pub mod chan_open_ack; @@ -41,23 +39,6 @@ pub enum ChannelMsg { CloseConfirm(MsgChannelCloseConfirm), } -impl ChannelMsg { - pub(super) fn lookup_module(&self, ctx: &impl RouterContext) -> Result { - let port_id = match self { - ChannelMsg::OpenInit(msg) => &msg.port_id_on_a, - ChannelMsg::OpenTry(msg) => &msg.port_id_on_b, - ChannelMsg::OpenAck(msg) => &msg.port_id_on_a, - ChannelMsg::OpenConfirm(msg) => &msg.port_id_on_b, - ChannelMsg::CloseInit(msg) => &msg.port_id_on_a, - ChannelMsg::CloseConfirm(msg) => &msg.port_id_on_b, - }; - let module_id = ctx - .lookup_module_by_port(port_id) - .map_err(ChannelError::Port)?; - Ok(module_id) - } -} - #[derive(Clone, Debug, PartialEq, Eq)] pub enum PacketMsg { Recv(MsgRecvPacket), @@ -65,18 +46,3 @@ pub enum PacketMsg { Timeout(MsgTimeout), TimeoutOnClose(MsgTimeoutOnClose), } - -impl PacketMsg { - pub(super) fn lookup_module(&self, ctx: &impl RouterContext) -> Result { - let port_id = match self { - PacketMsg::Recv(msg) => &msg.packet.port_on_b, - PacketMsg::Ack(msg) => &msg.packet.port_on_a, - PacketMsg::Timeout(msg) => &msg.packet.port_on_a, - PacketMsg::TimeoutOnClose(msg) => &msg.packet.port_on_a, - }; - let module_id = ctx - .lookup_module_by_port(port_id) - .map_err(ChannelError::Port)?; - Ok(module_id) - } -} diff --git a/crates/ibc/src/core/ics04_channel/packet.rs b/crates/ibc/src/core/ics04_channel/packet.rs index c943ab220..c42736609 100644 --- a/crates/ibc/src/core/ics04_channel/packet.rs +++ b/crates/ibc/src/core/ics04_channel/packet.rs @@ -4,10 +4,6 @@ use core::str::FromStr; use ibc_proto::ibc::core::channel::v1::Packet as RawPacket; -use super::handler::{ - acknowledgement::AckPacketResult, recv_packet::RecvPacketResult, send_packet::SendPacketResult, - timeout::TimeoutPacketResult, write_acknowledgement::WriteAckPacketResult, -}; use super::timeout::TimeoutHeight; use crate::core::ics04_channel::error::{ChannelError, PacketError}; use crate::core::ics24_host::identifier::{ChannelId, PortId}; @@ -24,15 +20,6 @@ pub enum PacketMsgType { TimeoutOnClose, } -#[derive(Clone, Debug)] -pub enum PacketResult { - Send(SendPacketResult), - Recv(RecvPacketResult), - WriteAck(WriteAckPacketResult), - Ack(AckPacketResult), - Timeout(TimeoutPacketResult), -} - #[cfg_attr( feature = "parity-scale-codec", derive( diff --git a/crates/ibc/src/core/ics26_routing/context.rs b/crates/ibc/src/core/ics26_routing/context.rs index 05043d864..7e554013f 100644 --- a/crates/ibc/src/core/ics26_routing/context.rs +++ b/crates/ibc/src/core/ics26_routing/context.rs @@ -8,39 +8,16 @@ use core::{ str::FromStr, }; -use crate::core::ics02_client::context::{ClientKeeper, ClientReader}; -use crate::core::ics03_connection::context::{ConnectionKeeper, ConnectionReader}; use crate::core::ics04_channel::channel::{Counterparty, Order}; -use crate::core::ics04_channel::context::{ChannelKeeper, ChannelReader}; use crate::core::ics04_channel::error::{ChannelError, PacketError}; use crate::core::ics04_channel::msgs::acknowledgement::Acknowledgement; use crate::core::ics04_channel::packet::Packet; use crate::core::ics04_channel::Version; -use crate::core::ics05_port::context::PortReader; use crate::core::ics24_host::identifier::{ChannelId, ConnectionId, PortId}; use crate::events::ModuleEvent; use crate::handler::HandlerOutputBuilder; use crate::signer::Signer; -/// This trait captures all the functional dependencies (i.e., context) which the ICS26 module -/// requires to be able to dispatch and process IBC messages. In other words, this is the -/// representation of a chain from the perspective of the IBC module of that chain. -pub trait RouterContext: - ClientReader - + ClientKeeper - + ConnectionReader - + ConnectionKeeper - + ChannelKeeper - + ChannelReader - + PortReader -{ - type Router: Router; - - fn router(&self) -> &Self::Router; - - fn router_mut(&mut self) -> &mut Self::Router; -} - #[derive(Debug, PartialEq, Eq)] pub struct InvalidModuleId; diff --git a/crates/ibc/src/core/ics26_routing/handler.rs b/crates/ibc/src/core/ics26_routing/handler.rs deleted file mode 100644 index 1e82b9745..000000000 --- a/crates/ibc/src/core/ics26_routing/handler.rs +++ /dev/null @@ -1,153 +0,0 @@ -use crate::handler::HandlerOutputBuilder; -use crate::prelude::*; - -use ibc_proto::google::protobuf::Any; - -use crate::core::ics02_client::handler::dispatch as ics2_msg_dispatcher; -use crate::core::ics03_connection::handler::dispatch as ics3_msg_dispatcher; -use crate::core::ics04_channel::handler::{ - channel_callback, channel_dispatch, channel_validate, recv_packet::RecvPacketResult, -}; -use crate::core::ics04_channel::handler::{ - channel_events, get_module_for_packet_msg, packet_callback as ics4_packet_callback, - packet_dispatch as ics4_packet_msg_dispatcher, -}; -use crate::core::ics04_channel::packet::PacketResult; -use crate::core::ics26_routing::context::RouterContext; -use crate::core::ics26_routing::error::RouterError; -use crate::core::ics26_routing::msgs::MsgEnvelope::{self, Channel, Client, Connection, Packet}; -use crate::{events::IbcEvent, handler::HandlerOutput}; - -/// Result of message execution - comprises of events emitted and logs entries created during the -/// execution of a transaction message. -pub struct MsgReceipt { - pub events: Vec, - pub log: Vec, -} - -/// Mimics the DeliverTx ABCI interface, but for a single message and at a slightly lower level. -/// No need for authentication info or signature checks here. -/// Returns a vector of all events that got generated as a byproduct of processing `message`. -pub fn deliver(ctx: &mut Ctx, message: Any) -> Result -where - Ctx: RouterContext, -{ - // Decode the proto message into a domain message, creating an ICS26 envelope. - let envelope = decode(message)?; - - // Process the envelope, and accumulate any events that were generated. - let HandlerOutput { log, events, .. } = dispatch(ctx, envelope)?; - - Ok(MsgReceipt { events, log }) -} - -/// Attempts to convert a message into a [MsgEnvelope] message -pub fn decode(message: Any) -> Result { - message.try_into() -} - -/// Top-level ICS dispatch function. Routes incoming IBC messages to their corresponding module. -/// Returns a handler output with empty result of type `HandlerOutput<()>` which contains the log -/// and events produced after processing the input `msg`. -/// If this method returns an error, the runtime is expected to rollback all state modifications to -/// the `Ctx` caused by all messages from the transaction that this `msg` is a part of. -pub fn dispatch(ctx: &mut Ctx, msg: MsgEnvelope) -> Result, RouterError> -where - Ctx: RouterContext, -{ - let output = match msg { - Client(msg) => { - let handler_output = - ics2_msg_dispatcher(ctx, msg).map_err(|e| RouterError::ContextError(e.into()))?; - - // Apply the result to the context (host chain store). - ctx.store_client_result(handler_output.result) - .map_err(|e| RouterError::ContextError(e.into()))?; - - HandlerOutput::builder() - .with_log(handler_output.log) - .with_events(handler_output.events) - .with_result(()) - } - - Connection(msg) => { - let handler_output = - ics3_msg_dispatcher(ctx, msg).map_err(|e| RouterError::ContextError(e.into()))?; - - // Apply any results to the host chain store. - ctx.store_connection_result(handler_output.result) - .map_err(|e| RouterError::ContextError(e.into()))?; - - HandlerOutput::builder() - .with_log(handler_output.log) - .with_events(handler_output.events) - .with_result(()) - } - - Channel(msg) => { - let module_id = - channel_validate(ctx, &msg).map_err(|e| RouterError::ContextError(e.into()))?; - let dispatch_output = HandlerOutputBuilder::<()>::new(); - - let (dispatch_log, mut channel_result) = - channel_dispatch(ctx, &msg).map_err(|e| RouterError::ContextError(e.into()))?; - - // Note: `OpenInit` and `OpenTry` modify the `version` field of the `channel_result`, - // so we must pass it mutably. We intend to clean this up with the implementation of - // ADR 5. - // See issue [#190](https://github.com/cosmos/ibc-rs/issues/190) - let callback_extras = channel_callback(ctx, &module_id, &msg, &mut channel_result) - .map_err(|e| RouterError::ContextError(e.into()))?; - - // We need to construct events here instead of directly in the - // `process` functions because we need to wait for the callback to - // give us the `version` in the case of `OpenInit` and `OpenTry`. - let dispatch_events = channel_events( - &msg, - channel_result.channel_id.clone(), - channel_result.channel_end.counterparty().clone(), - channel_result.channel_end.connection_hops[0].clone(), - &channel_result.channel_end.version, - ); - - // Apply any results to the host chain store. - ctx.store_channel_result(channel_result) - .map_err(|e| RouterError::ContextError(e.into()))?; - - dispatch_output - .with_events(dispatch_events) - .with_events( - callback_extras - .events - .into_iter() - .map(IbcEvent::AppModule) - .collect(), - ) - .with_log(dispatch_log) - .with_log(callback_extras.log) - .with_result(()) - } - - Packet(msg) => { - let module_id = get_module_for_packet_msg(ctx, &msg) - .map_err(|e| RouterError::ContextError(e.into()))?; - let (mut handler_builder, packet_result) = ics4_packet_msg_dispatcher(ctx, &msg) - .map_err(|e| RouterError::ContextError(e.into()))?; - - if matches!(packet_result, PacketResult::Recv(RecvPacketResult::NoOp)) { - return Ok(handler_builder.with_result(())); - } - - let cb_result = ics4_packet_callback(ctx, &module_id, &msg, &mut handler_builder); - cb_result.map_err(|e| RouterError::ContextError(e.into()))?; - - // Apply any results to the host chain store. - ctx.store_packet_result(packet_result) - .map_err(|e| RouterError::ContextError(e.into()))?; - - handler_builder.with_result(()) - } - }; - - Ok(output) -} diff --git a/crates/ibc/src/core/ics26_routing/mod.rs b/crates/ibc/src/core/ics26_routing/mod.rs index 79e5a5ff2..7eb9ec719 100644 --- a/crates/ibc/src/core/ics26_routing/mod.rs +++ b/crates/ibc/src/core/ics26_routing/mod.rs @@ -3,5 +3,4 @@ pub mod context; pub mod error; -pub mod handler; pub mod msgs; diff --git a/crates/ibc/src/core/mod.rs b/crates/ibc/src/core/mod.rs index ea032abac..51666784c 100644 --- a/crates/ibc/src/core/mod.rs +++ b/crates/ibc/src/core/mod.rs @@ -1,5 +1,4 @@ -//! The designs and logic pertaining to the transport, authentication, and -//! ordering layers of the IBC protocol. +//! Implementation of the core IBC protocol. //! //! Naming is hard in the IBC handlers, since we deal with a client on a //! *counterparty* chain, which is itself a light client of *self* (the chain diff --git a/crates/ibc/src/mock/client_state.rs b/crates/ibc/src/mock/client_state.rs index 52f7b57cd..1724f2a7e 100644 --- a/crates/ibc/src/mock/client_state.rs +++ b/crates/ibc/src/mock/client_state.rs @@ -11,12 +11,10 @@ use ibc_proto::protobuf::Protobuf; use crate::core::ics02_client::client_state::{ClientState, UpdatedState}; use crate::core::ics02_client::client_type::ClientType; use crate::core::ics02_client::consensus_state::ConsensusState; -use crate::core::ics02_client::context::ClientReader; use crate::core::ics02_client::error::ClientError; use crate::core::ics03_connection::connection::ConnectionEnd; use crate::core::ics04_channel::channel::ChannelEnd; use crate::core::ics04_channel::commitment::{AcknowledgementCommitment, PacketCommitment}; -use crate::core::ics04_channel::context::ChannelReader; use crate::core::ics04_channel::packet::Sequence; use crate::core::ics23_commitment::commitment::{ CommitmentPrefix, CommitmentProofBytes, CommitmentRoot, @@ -181,27 +179,6 @@ impl ClientState for MockClientState { } fn check_header_and_update_state( - &self, - _ctx: &dyn ClientReader, - _client_id: ClientId, - header: Any, - ) -> Result { - let header = MockHeader::try_from(header)?; - - if self.latest_height() >= header.height() { - return Err(ClientError::LowHeaderHeight { - header_height: header.height(), - latest_height: self.latest_height(), - }); - } - - Ok(UpdatedState { - client_state: MockClientState::new(header).into_box(), - consensus_state: MockConsensusState::new(header).into_box(), - }) - } - - fn new_check_header_and_update_state( &self, _ctx: &dyn ValidationContext, _client_id: ClientId, @@ -223,33 +200,6 @@ impl ClientState for MockClientState { } fn check_misbehaviour_and_update_state( - &self, - _ctx: &dyn ClientReader, - _client_id: ClientId, - misbehaviour: Any, - ) -> Result, ClientError> { - let misbehaviour = Misbehaviour::try_from(misbehaviour)?; - let header_1 = misbehaviour.header1; - let header_2 = misbehaviour.header2; - - if header_1.height() != header_2.height() { - return Err(ClientError::InvalidHeight); - } - - if self.latest_height() >= header_1.height() { - return Err(ClientError::LowHeaderHeight { - header_height: header_1.height(), - latest_height: self.latest_height(), - }); - } - - let new_state = - MockClientState::new(header_1).with_frozen_height(Height::new(0, 1).unwrap()); - - Ok(new_state.into_box()) - } - - fn new_check_misbehaviour_and_update_state( &self, _ctx: &dyn ValidationContext, _client_id: ClientId, @@ -362,22 +312,9 @@ impl ClientState for MockClientState { Ok(()) } - fn new_verify_packet_data( - &self, - _ctx: &dyn ValidationContext, - _height: Height, - _connection_end: &ConnectionEnd, - _proof: &CommitmentProofBytes, - _root: &CommitmentRoot, - _commitment_path: &CommitmentPath, - _commitment: PacketCommitment, - ) -> Result<(), ClientError> { - Ok(()) - } - fn verify_packet_data( &self, - _ctx: &dyn ChannelReader, + _ctx: &dyn ValidationContext, _height: Height, _connection_end: &ConnectionEnd, _proof: &CommitmentProofBytes, @@ -388,35 +325,9 @@ impl ClientState for MockClientState { Ok(()) } - fn verify_packet_acknowledgement( - &self, - _ctx: &dyn ChannelReader, - _height: Height, - _connection_end: &ConnectionEnd, - _proof: &CommitmentProofBytes, - _root: &CommitmentRoot, - _ack_path: &AckPath, - _ack: AcknowledgementCommitment, - ) -> Result<(), ClientError> { - Ok(()) - } - - fn new_verify_next_sequence_recv( - &self, - _ctx: &dyn ValidationContext, - _height: Height, - _connection_end: &ConnectionEnd, - _proof: &CommitmentProofBytes, - _root: &CommitmentRoot, - _seq_recv_path: &SeqRecvPath, - _sequence: Sequence, - ) -> Result<(), ClientError> { - Ok(()) - } - fn verify_next_sequence_recv( &self, - _ctx: &dyn ChannelReader, + _ctx: &dyn ValidationContext, _height: Height, _connection_end: &ConnectionEnd, _proof: &CommitmentProofBytes, @@ -427,21 +338,9 @@ impl ClientState for MockClientState { Ok(()) } - fn new_verify_packet_receipt_absence( - &self, - _ctx: &dyn ValidationContext, - _height: Height, - _connection_end: &ConnectionEnd, - _proof: &CommitmentProofBytes, - _root: &CommitmentRoot, - _receipt_path: &ReceiptPath, - ) -> Result<(), ClientError> { - Ok(()) - } - fn verify_packet_receipt_absence( &self, - _ctx: &dyn ChannelReader, + _ctx: &dyn ValidationContext, _height: Height, _connection_end: &ConnectionEnd, _proof: &CommitmentProofBytes, @@ -451,7 +350,7 @@ impl ClientState for MockClientState { Ok(()) } - fn new_verify_packet_acknowledgement( + fn verify_packet_acknowledgement( &self, _ctx: &dyn ValidationContext, _height: Height,