diff --git a/.changelog/unreleased/breaking-changes/1320-define-host-error-type.md b/.changelog/unreleased/breaking-changes/1320-define-host-error-type.md new file mode 100644 index 000000000..ff8e02c75 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1320-define-host-error-type.md @@ -0,0 +1,2 @@ +- Defined a new `HostError` type in ics24 to draw distinction between protocol errors and host errors + ([\1320](https://github.com/cosmos/ibc-rs/issues/1320)) diff --git a/.changelog/v0.31.0/breaking-changes/482-fix-validate-self-client-error-type.md b/.changelog/v0.31.0/breaking-changes/482-fix-validate-self-client-error-type.md index b68e2b01c..f05961027 100644 --- a/.changelog/v0.31.0/breaking-changes/482-fix-validate-self-client-error-type.md +++ b/.changelog/v0.31.0/breaking-changes/482-fix-validate-self-client-error-type.md @@ -1,3 +1,3 @@ -- Modify `validate_self_client` error type to return `ContextError` instead of - `ConnectionError` - ([#482](https://github.com/cosmos/ibc-rs/issues/482)) \ No newline at end of file +- Modify `validate_self_client` error type to return `HostError` instead of + `ConnectionError` + ([#482](https://github.com/cosmos/ibc-rs/issues/482)) diff --git a/.changelog/v0.33.0/improvement/547-error-strings.md b/.changelog/v0.33.0/improvement/547-error-strings.md index 661201f75..064388cf1 100644 --- a/.changelog/v0.33.0/improvement/547-error-strings.md +++ b/.changelog/v0.33.0/improvement/547-error-strings.md @@ -1,2 +1,2 @@ -- Fix ContextError Display output +- Fix HandlerError Display output ([#547](https://github.com/cosmos/ibc-rs/issues/547)) diff --git a/.changelog/v0.45.0/breaking-changes/857-use-result-for-safe-counters-increment.md b/.changelog/v0.45.0/breaking-changes/857-use-result-for-safe-counters-increment.md index f0f87285e..c656a7fd9 100644 --- a/.changelog/v0.45.0/breaking-changes/857-use-result-for-safe-counters-increment.md +++ b/.changelog/v0.45.0/breaking-changes/857-use-result-for-safe-counters-increment.md @@ -1,3 +1,3 @@ - Allow hosts to handle overflow cases in `increase_*_counter` methods by - returning `Result<(),ContextError>` type. + returning `Result<(),HostError>` type. ([#857](https://github.com/cosmos/ibc-rs/issues/857)) diff --git a/.changelog/v0.45.0/breaking-changes/859-return-result-in-logger-event-emitter-methods.md b/.changelog/v0.45.0/breaking-changes/859-return-result-in-logger-event-emitter-methods.md index 9c25b1ba3..7157bd3be 100644 --- a/.changelog/v0.45.0/breaking-changes/859-return-result-in-logger-event-emitter-methods.md +++ b/.changelog/v0.45.0/breaking-changes/859-return-result-in-logger-event-emitter-methods.md @@ -1,2 +1,2 @@ -- logger and event emitter methods return `Result<(), ContextError>` type. +- logger and event emitter methods return `Result<(), HostError>` type. ([#859](https://github.com/cosmos/ibc-rs/issues/859)) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56e149579..2d4949e2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -641,9 +641,9 @@ There are no consensus-breaking changes. - Bump ibc-proto-rs to v0.34.0 ([#790](https://github.com/cosmos/ibc-rs/issues/790)) - Allow hosts to handle overflow cases in `increase_*_counter` methods by - returning `Result<(),ContextError>` type. + returning `Result<(),HandlerError>` type. ([#857](https://github.com/cosmos/ibc-rs/issues/857)) -- logger and event emitter methods return `Result<(), ContextError>` type. +- logger and event emitter methods return `Result<(), HandlerError>` type. ([#859](https://github.com/cosmos/ibc-rs/issues/859)) - Bump `ibc-proto-rs` to v0.35.0 along with some other minor dependency updates ([#873](https://github.com/cosmos/ibc-rs/issues/873)) @@ -1042,7 +1042,7 @@ There are no consensus-breaking changes. ### IMPROVEMENT -- Fix `ContextError` Display output +- Fix `HandlerError` Display output ([#547](https://github.com/cosmos/ibc-rs/issues/547)) ## v0.32.0 @@ -1099,7 +1099,7 @@ There are no consensus-breaking changes. ([#479](https://github.com/cosmos/ibc-rs/issues/479)) - Remove Send + Sync supertraits on the Module trait ([#480](https://github.com/cosmos/ibc-rs/issues/480)) -- Modify `validate_self_client` error type to return `ContextError` instead of +- Modify `validate_self_client` error type to return `HandlerError` instead of `ConnectionError` ([#482](https://github.com/cosmos/ibc-rs/issues/482)) diff --git a/docs/architecture/adr-006-upgrade-client-implementation.md b/docs/architecture/adr-006-upgrade-client-implementation.md index d1aa8fc86..fbfd86535 100644 --- a/docs/architecture/adr-006-upgrade-client-implementation.md +++ b/docs/architecture/adr-006-upgrade-client-implementation.md @@ -119,7 +119,7 @@ supported by `IBC-rs`: negotiated on connection handshake. 10. (U) Changing parameters that are customizable by relayers like `TrustLevel` and `TrustingPeriod`, `max_clock_drift` - + #### Upgrade Process Step-by-step An IBC-connected Tendermint chain will take the following steps to completely @@ -250,7 +250,7 @@ previous section as mentioned: 1. ```rust if old_client_state.is_frozen() { - return Err(ContextError::ClientError(ClientError::ClientFrozen { + return Err(HandlerError::Client(ClientError::ClientFrozen { client_id, })); } diff --git a/docs/architecture/adr-007-light-client-contexts.md b/docs/architecture/adr-007-light-client-contexts.md index b0caabdd5..5bf30de70 100644 --- a/docs/architecture/adr-007-light-client-contexts.md +++ b/docs/architecture/adr-007-light-client-contexts.md @@ -98,12 +98,12 @@ pub trait ClientExecutionContext: Sized { /// Called upon successful client creation and update fn store_client_state( ... - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Called upon successful client creation and update fn store_consensus_state( ... - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; } ``` @@ -120,7 +120,7 @@ pub trait ValidationContext: Router { type ClientValidationContext; type ClientExecutionContext; /// Enum that can contain a `ConsensusState` object of any supported light client - type AnyConsensusState: ConsensusState; + type AnyConsensusState: ConsensusState; /// Enum that can contain a `ClientState` object of any supported light client type AnyClientState: ClientState< Self::AnyConsensusState, diff --git a/docs/architecture/adr-010-enable-standalone-ics02-integration.md b/docs/architecture/adr-010-enable-standalone-ics02-integration.md index 24dbe1149..feb0c9695 100644 --- a/docs/architecture/adr-010-enable-standalone-ics02-integration.md +++ b/docs/architecture/adr-010-enable-standalone-ics02-integration.md @@ -129,26 +129,26 @@ pub trait ValidationContext { fn get_client_validation_context(&self) -> &Self::V; // This method will be removed and replaced by a `ClientStateDecoder` trait that will encapsulate the ability to decode a client state from an `Any` -- fn decode_client_state(&self, client_state: Any) -> Result; +- fn decode_client_state(&self, client_state: Any) -> Result; -- fn client_state(&self, client_id: &ClientId) -> Result; +- fn client_state(&self, client_id: &ClientId) -> Result; - fn consensus_state( - &self, - client_cons_state_path: &ClientConsensusStatePath, -- ) -> Result; +- ) -> Result; fn host_consensus_state( &self, height: &Height, -- ) -> Result; -+ ) -> Result; +- ) -> Result; ++ ) -> Result; fn validate_self_client( &self, - client_state_of_host_on_counterparty: Any, + client_state_of_host_on_counterparty: Self::HostClientState, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; ... // other methods } @@ -200,18 +200,18 @@ pub trait ClientValidationContext: Sized { + type ClientStateRef: ClientStateValidation; + type ConsensusStateRef: ConsensusState; -+ fn client_state(&self, client_id: &ClientId) -> Result; ++ fn client_state(&self, client_id: &ClientId) -> Result; + fn consensus_state( + &self, + client_cons_state_path: &ClientConsensusStatePath, -+ ) -> Result; ++ ) -> Result; fn client_update_meta( &self, client_id: &ClientId, height: &Height, - ) -> Result<(Timestamp, Height), ContextError>; + ) -> Result<(Timestamp, Height), HostError>; } pub trait ClientExecutionContext: @@ -222,7 +222,7 @@ pub trait ClientExecutionContext: - type AnyConsensusState: ConsensusState; + type ClientStateMut: ClientStateExecution; -+ fn client_state_mut(&self, client_id: &ClientId) -> Result { ++ fn client_state_mut(&self, client_id: &ClientId) -> Result { + self.client_state(client_id) + } @@ -230,18 +230,18 @@ pub trait ClientExecutionContext: &mut self, client_state_path: ClientStatePath, client_state: Self::ClientStateMut, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; fn store_consensus_state( &mut self, consensus_state_path: ClientConsensusStatePath, consensus_state: Self::ConsensusStateRef, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; fn delete_consensus_state( &mut self, consensus_state_path: ClientConsensusStatePath, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; fn store_update_meta( &mut self, @@ -249,13 +249,13 @@ pub trait ClientExecutionContext: height: Height, host_timestamp: Timestamp, host_height: Height, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; fn delete_update_meta( &mut self, client_id: ClientId, height: Height, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; } ``` @@ -306,28 +306,28 @@ pub trait ExtClientValidationContext: + type ConversionError: ToString; + type AnyConsensusState: TryInto; -+ fn host_timestamp(&self) -> Result; ++ fn host_timestamp(&self) -> Result; -+ fn host_height(&self) -> Result; ++ fn host_height(&self) -> Result; - fn consensus_state( - &self, - client_cons_state_path: &ClientConsensusStatePath, -- ) -> Result; +- ) -> Result; -+ fn consensus_state_heights(&self, client_id: &ClientId) -> Result, ContextError>; ++ fn consensus_state_heights(&self, client_id: &ClientId) -> Result, HostError>; fn next_consensus_state( &self, client_id: &ClientId, height: &Height, - ) -> Result, ContextError>; + ) -> Result, HostError>; fn prev_consensus_state( &self, client_id: &ClientId, height: &Height, - ) -> Result, ContextError>; + ) -> Result, HostError>; } -impl ExecutionContext for T where T: CommonContext + ClientExecutionContext {} diff --git a/ibc-apps/ics20-transfer/src/context.rs b/ibc-apps/ics20-transfer/src/context.rs index 8c22ad386..2917c9fe9 100644 --- a/ibc-apps/ics20-transfer/src/context.rs +++ b/ibc-apps/ics20-transfer/src/context.rs @@ -1,7 +1,7 @@ //! Defines the main context traits and IBC module callbacks -use ibc_app_transfer_types::error::TokenTransferError; use ibc_app_transfer_types::{Memo, PrefixedCoin, PrefixedDenom}; +use ibc_core::host::types::error::HostError; use ibc_core::host::types::identifiers::{ChannelId, PortId}; use ibc_core::primitives::prelude::*; use ibc_core::primitives::Signer; @@ -11,13 +11,13 @@ pub trait TokenTransferValidationContext { type AccountId: TryFrom; /// get_port returns the portID for the transfer module. - fn get_port(&self) -> Result; + fn get_port(&self) -> Result; /// Returns Ok() if the host chain supports sending coins. - fn can_send_coins(&self) -> Result<(), TokenTransferError>; + fn can_send_coins(&self) -> Result<(), HostError>; /// Returns Ok() if the host chain supports receiving coins. - fn can_receive_coins(&self) -> Result<(), TokenTransferError>; + fn can_receive_coins(&self) -> Result<(), HostError>; /// Validates that the tokens can be escrowed successfully. /// @@ -30,7 +30,7 @@ pub trait TokenTransferValidationContext { channel_id: &ChannelId, coin: &PrefixedCoin, memo: &Memo, - ) -> Result<(), TokenTransferError>; + ) -> Result<(), HostError>; /// Validates that the tokens can be unescrowed successfully. fn unescrow_coins_validate( @@ -39,14 +39,14 @@ pub trait TokenTransferValidationContext { port_id: &PortId, channel_id: &ChannelId, coin: &PrefixedCoin, - ) -> Result<(), TokenTransferError>; + ) -> Result<(), HostError>; /// Validates the receiver account and the coin input fn mint_coins_validate( &self, account: &Self::AccountId, coin: &PrefixedCoin, - ) -> Result<(), TokenTransferError>; + ) -> Result<(), HostError>; /// Validates the sender account and the coin input before burning. /// @@ -57,7 +57,7 @@ pub trait TokenTransferValidationContext { account: &Self::AccountId, coin: &PrefixedCoin, memo: &Memo, - ) -> Result<(), TokenTransferError>; + ) -> Result<(), HostError>; /// Returns a hash of the prefixed denom. /// Implement only if the host chain supports hashed denominations. @@ -79,7 +79,7 @@ pub trait TokenTransferExecutionContext: TokenTransferValidationContext { channel_id: &ChannelId, coin: &PrefixedCoin, memo: &Memo, - ) -> Result<(), TokenTransferError>; + ) -> Result<(), HostError>; /// Executes the unescrow of the tokens in a user account. fn unescrow_coins_execute( @@ -88,14 +88,14 @@ pub trait TokenTransferExecutionContext: TokenTransferValidationContext { port_id: &PortId, channel_id: &ChannelId, coin: &PrefixedCoin, - ) -> Result<(), TokenTransferError>; + ) -> Result<(), HostError>; /// Executes minting of the tokens in a user account. fn mint_coins_execute( &mut self, account: &Self::AccountId, coin: &PrefixedCoin, - ) -> Result<(), TokenTransferError>; + ) -> Result<(), HostError>; /// Executes burning of the tokens in a user account. /// @@ -106,5 +106,5 @@ pub trait TokenTransferExecutionContext: TokenTransferValidationContext { account: &Self::AccountId, coin: &PrefixedCoin, memo: &Memo, - ) -> Result<(), TokenTransferError>; + ) -> Result<(), HostError>; } diff --git a/ibc-apps/ics20-transfer/src/handler/mod.rs b/ibc-apps/ics20-transfer/src/handler/mod.rs index 6d3cde510..95ed5441c 100644 --- a/ibc-apps/ics20-transfer/src/handler/mod.rs +++ b/ibc-apps/ics20-transfer/src/handler/mod.rs @@ -6,6 +6,7 @@ use ibc_app_transfer_types::error::TokenTransferError; use ibc_app_transfer_types::is_sender_chain_source; use ibc_app_transfer_types::packet::PacketData; use ibc_core::channel::types::packet::Packet; +use ibc_core::primitives::prelude::*; pub use on_recv_packet::*; pub use send_transfer::*; @@ -27,16 +28,16 @@ pub fn refund_packet_token_execute( packet.chan_id_on_a.clone(), &data.token.denom, ) { - ctx_a.unescrow_coins_execute( + Ok(ctx_a.unescrow_coins_execute( &sender, &packet.port_id_on_a, &packet.chan_id_on_a, &data.token, - ) + )?) } // mint vouchers back to sender else { - ctx_a.mint_coins_execute(&sender, &data.token) + Ok(ctx_a.mint_coins_execute(&sender, &data.token)?) } } @@ -56,13 +57,13 @@ pub fn refund_packet_token_validate( packet.chan_id_on_a.clone(), &data.token.denom, ) { - ctx_a.unescrow_coins_validate( + Ok(ctx_a.unescrow_coins_validate( &sender, &packet.port_id_on_a, &packet.chan_id_on_a, &data.token, - ) + )?) } else { - ctx_a.mint_coins_validate(&sender, &data.token) + Ok(ctx_a.mint_coins_validate(&sender, &data.token)?) } } diff --git a/ibc-apps/ics20-transfer/src/handler/on_recv_packet.rs b/ibc-apps/ics20-transfer/src/handler/on_recv_packet.rs index b0fcbd877..76e22b3b6 100644 --- a/ibc-apps/ics20-transfer/src/handler/on_recv_packet.rs +++ b/ibc-apps/ics20-transfer/src/handler/on_recv_packet.rs @@ -21,7 +21,7 @@ pub fn process_recv_packet_execute( ) -> Result { ctx_b .can_receive_coins() - .map_err(|err| (ModuleExtras::empty(), err))?; + .map_err(|err| (ModuleExtras::empty(), err.into()))?; let receiver_account = data.receiver.clone().try_into().map_err(|_| { ( @@ -60,7 +60,7 @@ pub fn process_recv_packet_execute( &packet.chan_id_on_b, &coin, ) - .map_err(|token_err| (ModuleExtras::empty(), token_err))?; + .map_err(|err| (ModuleExtras::empty(), err.into()))?; ctx_b .unescrow_coins_execute( &receiver_account, @@ -68,7 +68,7 @@ pub fn process_recv_packet_execute( &packet.chan_id_on_b, &coin, ) - .map_err(|token_err| (ModuleExtras::empty(), token_err))?; + .map_err(|err| (ModuleExtras::empty(), err.into()))?; ModuleExtras::empty() } else { @@ -103,11 +103,11 @@ pub fn process_recv_packet_execute( // can be refunded. ctx_b .mint_coins_validate(&receiver_account, &coin) - .map_err(|token_err| (extras.clone(), token_err))?; + .map_err(|err| (extras.clone(), err.into()))?; ctx_b .mint_coins_execute(&receiver_account, &coin) - .map_err(|token_err| (extras.clone(), token_err))?; + .map_err(|err| (extras.clone(), err.into()))?; extras }; diff --git a/ibc-apps/ics20-transfer/src/module.rs b/ibc-apps/ics20-transfer/src/module.rs index 5958184c7..2c24dc6fe 100644 --- a/ibc-apps/ics20-transfer/src/module.rs +++ b/ibc-apps/ics20-transfer/src/module.rs @@ -6,7 +6,7 @@ use ibc_core::channel::types::acknowledgement::{Acknowledgement, Acknowledgement use ibc_core::channel::types::channel::{Counterparty, Order}; use ibc_core::channel::types::packet::Packet; use ibc_core::channel::types::Version; -use ibc_core::handler::types::error::ContextError; +use ibc_core::handler::types::error::HandlerError; use ibc_core::host::types::error::DecodingError; use ibc_core::host::types::identifiers::{ChannelId, ConnectionId, PortId}; use ibc_core::primitives::prelude::*; @@ -44,7 +44,7 @@ pub fn on_chan_open_init_validate( if !version.is_empty() { version .verify_is_expected(Version::new(VERSION.to_string())) - .map_err(ContextError::from)?; + .map_err(HandlerError::from)?; } Ok(()) @@ -80,7 +80,7 @@ pub fn on_chan_open_try_validate( counterparty_version .verify_is_expected(Version::new(VERSION.to_string())) - .map_err(ContextError::from)?; + .map_err(HandlerError::from)?; Ok(()) } @@ -105,7 +105,7 @@ pub fn on_chan_open_ack_validate( ) -> Result<(), TokenTransferError> { counterparty_version .verify_is_expected(Version::new(VERSION.to_string())) - .map_err(ContextError::from)?; + .map_err(HandlerError::from)?; Ok(()) } diff --git a/ibc-apps/ics20-transfer/types/src/error.rs b/ibc-apps/ics20-transfer/types/src/error.rs index 31dcebdd5..00e81614b 100644 --- a/ibc-apps/ics20-transfer/types/src/error.rs +++ b/ibc-apps/ics20-transfer/types/src/error.rs @@ -2,15 +2,15 @@ use displaydoc::Display; use ibc_core::channel::types::acknowledgement::StatusValue; use ibc_core::channel::types::channel::Order; -use ibc_core::handler::types::error::ContextError; -use ibc_core::host::types::error::DecodingError; +use ibc_core::handler::types::error::HandlerError; +use ibc_core::host::types::error::{DecodingError, HostError}; use ibc_core::host::types::identifiers::{ChannelId, PortId}; use ibc_core::primitives::prelude::*; #[derive(Display, Debug)] pub enum TokenTransferError { - /// context error: `{0}` - ContextError(ContextError), + /// host error: `{0}` + Handler(HandlerError), /// decoding error: `{0}` Decoding(DecodingError), /// missing destination channel `{channel_id}` on port `{port_id}` @@ -28,10 +28,7 @@ pub enum TokenTransferError { FailedToDeserializePacketData, /// failed to deserialize acknowledgement FailedToDeserializeAck, - - // TODO(seanchen1991): Used in basecoin; this variant should be moved - // to a host-relevant error - /// failed to parse account ID + /// failed to parse account FailedToParseAccount, } @@ -39,16 +36,22 @@ pub enum TokenTransferError { impl std::error::Error for TokenTransferError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match &self { - Self::ContextError(e) => Some(e), + Self::Handler(e) => Some(e), Self::Decoding(e) => Some(e), _ => None, } } } -impl From for TokenTransferError { - fn from(e: ContextError) -> Self { - Self::ContextError(e) +impl From for TokenTransferError { + fn from(e: HandlerError) -> Self { + Self::Handler(e) + } +} + +impl From for TokenTransferError { + fn from(e: HostError) -> Self { + Self::Handler(HandlerError::Host(e)) } } diff --git a/ibc-apps/ics20-transfer/types/src/msgs/transfer.rs b/ibc-apps/ics20-transfer/types/src/msgs/transfer.rs index d5c1d4eae..0bdaf0979 100644 --- a/ibc-apps/ics20-transfer/types/src/msgs/transfer.rs +++ b/ibc-apps/ics20-transfer/types/src/msgs/transfer.rs @@ -50,7 +50,6 @@ impl TryFrom for MsgTransfer { fn try_from(raw_msg: RawMsgTransfer) -> Result { let timeout_height_on_b: TimeoutHeight = raw_msg.timeout_height.try_into()?; - let timeout_timestamp_on_b: TimeoutTimestamp = raw_msg.timeout_timestamp.into(); // Packet timeout height and packet timeout timestamp cannot both be unset. diff --git a/ibc-apps/ics721-nft-transfer/src/context.rs b/ibc-apps/ics721-nft-transfer/src/context.rs index ede6ee898..201d342cb 100644 --- a/ibc-apps/ics721-nft-transfer/src/context.rs +++ b/ibc-apps/ics721-nft-transfer/src/context.rs @@ -1,10 +1,10 @@ //! Defines the required context traits for ICS-721 to interact with host //! machine. +use ibc_core::host::types::error::HostError; use ibc_core::host::types::identifiers::{ChannelId, PortId}; use ibc_core::primitives::prelude::*; use ibc_core::primitives::Signer; -use crate::types::error::NftTransferError; use crate::types::{ ClassData, ClassId, ClassUri, Memo, PrefixedClassId, TokenData, TokenId, TokenUri, }; @@ -41,13 +41,13 @@ pub trait NftTransferValidationContext { type NftClass: NftClassContext; /// get_port returns the portID for the transfer module. - fn get_port(&self) -> Result; + fn get_port(&self) -> Result; /// Returns Ok() if the host chain supports sending NFTs. - fn can_send_nft(&self) -> Result<(), NftTransferError>; + fn can_send_nft(&self) -> Result<(), HostError>; /// Returns Ok() if the host chain supports receiving NFTs. - fn can_receive_nft(&self) -> Result<(), NftTransferError>; + fn can_receive_nft(&self) -> Result<(), HostError>; /// Validates that the NFT can be created or updated successfully. /// @@ -62,7 +62,7 @@ pub trait NftTransferValidationContext { class_id: &PrefixedClassId, class_uri: Option<&ClassUri>, class_data: Option<&ClassData>, - ) -> Result<(), NftTransferError>; + ) -> Result<(), HostError>; /// Validates that the tokens can be escrowed successfully. /// @@ -77,7 +77,7 @@ pub trait NftTransferValidationContext { class_id: &PrefixedClassId, token_id: &TokenId, memo: &Memo, - ) -> Result<(), NftTransferError>; + ) -> Result<(), HostError>; /// Validates that the NFT can be unescrowed successfully. fn unescrow_nft_validate( @@ -87,7 +87,7 @@ pub trait NftTransferValidationContext { channel_id: &ChannelId, class_id: &PrefixedClassId, token_id: &TokenId, - ) -> Result<(), NftTransferError>; + ) -> Result<(), HostError>; /// Validates the receiver account and the NFT input /// @@ -104,7 +104,7 @@ pub trait NftTransferValidationContext { token_id: &TokenId, token_uri: Option<&TokenUri>, token_data: Option<&TokenData>, - ) -> Result<(), NftTransferError>; + ) -> Result<(), HostError>; /// Validates the sender account and the coin input before burning. /// @@ -117,7 +117,7 @@ pub trait NftTransferValidationContext { class_id: &PrefixedClassId, token_id: &TokenId, memo: &Memo, - ) -> Result<(), NftTransferError>; + ) -> Result<(), HostError>; /// Returns a hash of the prefixed class ID and the token ID. /// Implement only if the host chain supports hashed class ID and token ID. @@ -134,11 +134,10 @@ pub trait NftTransferValidationContext { &self, class_id: &PrefixedClassId, token_id: &TokenId, - ) -> Result; + ) -> Result; /// Returns the NFT class - fn get_nft_class(&self, class_id: &PrefixedClassId) - -> Result; + fn get_nft_class(&self, class_id: &PrefixedClassId) -> Result; } /// Read-write methods required in NFT transfer execution context. @@ -149,7 +148,7 @@ pub trait NftTransferExecutionContext: NftTransferValidationContext { class_id: &PrefixedClassId, class_uri: Option<&ClassUri>, class_data: Option<&ClassData>, - ) -> Result<(), NftTransferError>; + ) -> Result<(), HostError>; /// Executes the escrow of the NFT in a user account. /// @@ -163,7 +162,7 @@ pub trait NftTransferExecutionContext: NftTransferValidationContext { class_id: &PrefixedClassId, token_id: &TokenId, memo: &Memo, - ) -> Result<(), NftTransferError>; + ) -> Result<(), HostError>; /// Executes the unescrow of the NFT in a user account. fn unescrow_nft_execute( @@ -173,7 +172,7 @@ pub trait NftTransferExecutionContext: NftTransferValidationContext { channel_id: &ChannelId, class_id: &PrefixedClassId, token_id: &TokenId, - ) -> Result<(), NftTransferError>; + ) -> Result<(), HostError>; /// Executes minting of the NFT in a user account. fn mint_nft_execute( @@ -183,7 +182,7 @@ pub trait NftTransferExecutionContext: NftTransferValidationContext { token_id: &TokenId, token_uri: Option<&TokenUri>, token_data: Option<&TokenData>, - ) -> Result<(), NftTransferError>; + ) -> Result<(), HostError>; /// Executes burning of the NFT in a user account. /// @@ -195,5 +194,5 @@ pub trait NftTransferExecutionContext: NftTransferValidationContext { class_id: &PrefixedClassId, token_id: &TokenId, memo: &Memo, - ) -> Result<(), NftTransferError>; + ) -> Result<(), HostError>; } diff --git a/ibc-apps/ics721-nft-transfer/src/handler/mod.rs b/ibc-apps/ics721-nft-transfer/src/handler/mod.rs index 8f8d0775c..9acca019f 100644 --- a/ibc-apps/ics721-nft-transfer/src/handler/mod.rs +++ b/ibc-apps/ics721-nft-transfer/src/handler/mod.rs @@ -29,13 +29,15 @@ pub fn refund_packet_nft_execute( &data.class_id, ) { data.token_ids.as_ref().iter().try_for_each(|token_id| { - ctx_a.unescrow_nft_execute( - &sender, - &packet.port_id_on_a, - &packet.chan_id_on_a, - &data.class_id, - token_id, - ) + ctx_a + .unescrow_nft_execute( + &sender, + &packet.port_id_on_a, + &packet.chan_id_on_a, + &data.class_id, + token_id, + ) + .map_err(NftTransferError::from) }) } // mint vouchers back to sender @@ -43,8 +45,11 @@ pub fn refund_packet_nft_execute( for (i, token_id) in data.token_ids.0.iter().enumerate() { let token_uri = data.token_uris.as_ref().and_then(|uris| uris.get(i)); let token_data = data.token_data.as_ref().and_then(|data| data.get(i)); - ctx_a.mint_nft_execute(&sender, &data.class_id, token_id, token_uri, token_data)?; + + let _ = + ctx_a.mint_nft_execute(&sender, &data.class_id, token_id, token_uri, token_data); } + Ok(()) } } @@ -66,20 +71,25 @@ pub fn refund_packet_nft_validate( &data.class_id, ) { data.token_ids.0.iter().try_for_each(|token_id| { - ctx_a.unescrow_nft_validate( - &sender, - &packet.port_id_on_a, - &packet.chan_id_on_a, - &data.class_id, - token_id, - ) + ctx_a + .unescrow_nft_validate( + &sender, + &packet.port_id_on_a, + &packet.chan_id_on_a, + &data.class_id, + token_id, + ) + .map_err(NftTransferError::from) }) } else { for (i, token_id) in data.token_ids.0.iter().enumerate() { let token_uri = data.token_uris.as_ref().and_then(|uris| uris.get(i)); let token_data = data.token_data.as_ref().and_then(|data| data.get(i)); - ctx_a.mint_nft_validate(&sender, &data.class_id, token_id, token_uri, token_data)?; + + let _ = + ctx_a.mint_nft_validate(&sender, &data.class_id, token_id, token_uri, token_data); } + Ok(()) } } diff --git a/ibc-apps/ics721-nft-transfer/src/handler/on_recv_packet.rs b/ibc-apps/ics721-nft-transfer/src/handler/on_recv_packet.rs index 59e6f3cb8..6d8eeb194 100644 --- a/ibc-apps/ics721-nft-transfer/src/handler/on_recv_packet.rs +++ b/ibc-apps/ics721-nft-transfer/src/handler/on_recv_packet.rs @@ -23,7 +23,7 @@ where { ctx_b .can_receive_nft() - .map_err(|err| (ModuleExtras::empty(), err))?; + .map_err(|err| (ModuleExtras::empty(), err.into()))?; let receiver_account = data.receiver.clone().try_into().map_err(|_| { ( @@ -56,7 +56,7 @@ where &class_id, token_id, ) - .map_err(|nft_error| (ModuleExtras::empty(), nft_error))?; + .map_err(|err| (ModuleExtras::empty(), err.into()))?; ctx_b .unescrow_nft_execute( &receiver_account, @@ -65,7 +65,7 @@ where &class_id, token_id, ) - .map_err(|nft_error| (ModuleExtras::empty(), nft_error))?; + .map_err(|err| (ModuleExtras::empty(), err.into()))?; } ModuleExtras::empty() @@ -102,14 +102,14 @@ where data.class_uri.as_ref(), data.class_data.as_ref(), ) - .map_err(|nft_error| (ModuleExtras::empty(), nft_error))?; + .map_err(|err| (ModuleExtras::empty(), err.into()))?; ctx_b .create_or_update_class_execute( &class_id, data.class_uri.as_ref(), data.class_data.as_ref(), ) - .map_err(|nft_error| (ModuleExtras::empty(), nft_error))?; + .map_err(|err| (ModuleExtras::empty(), err.into()))?; ctx_b .mint_nft_validate( @@ -119,7 +119,7 @@ where token_uri, token_data, ) - .map_err(|nft_error| (extras.clone(), nft_error))?; + .map_err(|err| (extras.clone(), err.into()))?; ctx_b .mint_nft_execute( &receiver_account, @@ -128,7 +128,7 @@ where token_uri, token_data, ) - .map_err(|nft_error| (extras.clone(), nft_error))?; + .map_err(|err| (extras.clone(), err.into()))?; } extras diff --git a/ibc-apps/ics721-nft-transfer/src/module.rs b/ibc-apps/ics721-nft-transfer/src/module.rs index 5560b686f..a1f479b51 100644 --- a/ibc-apps/ics721-nft-transfer/src/module.rs +++ b/ibc-apps/ics721-nft-transfer/src/module.rs @@ -3,7 +3,7 @@ use ibc_core::channel::types::acknowledgement::{Acknowledgement, Acknowledgement use ibc_core::channel::types::channel::{Counterparty, Order}; use ibc_core::channel::types::packet::Packet; use ibc_core::channel::types::Version; -use ibc_core::handler::types::error::ContextError; +use ibc_core::handler::types::error::HandlerError; use ibc_core::host::types::identifiers::{ChannelId, ConnectionId, PortId}; use ibc_core::primitives::prelude::*; use ibc_core::primitives::Signer; @@ -44,7 +44,7 @@ pub fn on_chan_open_init_validate( if !version.is_empty() { version .verify_is_expected(Version::new(VERSION.to_string())) - .map_err(ContextError::from)?; + .map_err(HandlerError::from)?; } Ok(()) @@ -80,7 +80,7 @@ pub fn on_chan_open_try_validate( counterparty_version .verify_is_expected(Version::new(VERSION.to_string())) - .map_err(ContextError::from)?; + .map_err(HandlerError::from)?; Ok(()) } @@ -105,7 +105,7 @@ pub fn on_chan_open_ack_validate( ) -> Result<(), NftTransferError> { counterparty_version .verify_is_expected(Version::new(VERSION.to_string())) - .map_err(ContextError::from)?; + .map_err(HandlerError::from)?; Ok(()) } diff --git a/ibc-apps/ics721-nft-transfer/types/src/error.rs b/ibc-apps/ics721-nft-transfer/types/src/error.rs index d7b112a64..bda017a9b 100644 --- a/ibc-apps/ics721-nft-transfer/types/src/error.rs +++ b/ibc-apps/ics721-nft-transfer/types/src/error.rs @@ -1,16 +1,17 @@ //! Defines the Non-Fungible Token Transfer (ICS-721) error types. +use derive_more::From; use displaydoc::Display; use ibc_core::channel::types::acknowledgement::StatusValue; use ibc_core::channel::types::channel::Order; -use ibc_core::handler::types::error::ContextError; -use ibc_core::host::types::error::DecodingError; +use ibc_core::handler::types::error::HandlerError; +use ibc_core::host::types::error::{DecodingError, HostError}; use ibc_core::host::types::identifiers::{ChannelId, PortId}; use ibc_core::primitives::prelude::*; -#[derive(Display, Debug, derive_more::From)] +#[derive(Display, Debug, From)] pub enum NftTransferError { - /// context error: `{0}` - ContextError(ContextError), + /// handler error: `{0}` + Handler(HandlerError), /// decoding error: `{0}` Decoding(DecodingError), /// missing destination channel `{channel_id}` on port `{port_id}` @@ -40,13 +41,19 @@ pub enum NftTransferError { impl std::error::Error for NftTransferError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match &self { - Self::ContextError(e) => Some(e), + Self::Handler(e) => Some(e), Self::Decoding(e) => Some(e), _ => None, } } } +impl From for NftTransferError { + fn from(e: HostError) -> Self { + Self::Handler(HandlerError::Host(e)) + } +} + impl From for StatusValue { fn from(err: NftTransferError) -> Self { StatusValue::new(err.to_string()).expect("error message must not be empty") diff --git a/ibc-apps/ics721-nft-transfer/types/src/msgs/transfer.rs b/ibc-apps/ics721-nft-transfer/types/src/msgs/transfer.rs index fb717018c..ae9a31bc4 100644 --- a/ibc-apps/ics721-nft-transfer/types/src/msgs/transfer.rs +++ b/ibc-apps/ics721-nft-transfer/types/src/msgs/transfer.rs @@ -51,7 +51,6 @@ impl TryFrom for MsgTransfer { fn try_from(raw_msg: RawMsgTransfer) -> Result { let timeout_height_on_b: TimeoutHeight = raw_msg.timeout_height.try_into()?; - let timeout_timestamp_on_b: TimeoutTimestamp = raw_msg.timeout_timestamp.into(); // Packet timeout height and packet timeout timestamp cannot both be unset. diff --git a/ibc-core/ics02-client/context/src/context.rs b/ibc-core/ics02-client/context/src/context.rs index 972ec547e..e9a47bf0d 100644 --- a/ibc-core/ics02-client/context/src/context.rs +++ b/ibc-core/ics02-client/context/src/context.rs @@ -1,5 +1,5 @@ use ibc_core_client_types::Height; -use ibc_core_handler_types::error::ContextError; +use ibc_core_host_types::error::HostError; use ibc_core_host_types::identifiers::ClientId; use ibc_core_host_types::path::{ClientConsensusStatePath, ClientStatePath}; use ibc_primitives::prelude::*; @@ -19,7 +19,7 @@ pub trait ClientValidationContext: Sized { /// Returns the ClientState for the given identifier `client_id`. /// /// Note: Clients have the responsibility to store client states on client creation and update. - fn client_state(&self, client_id: &ClientId) -> Result; + fn client_state(&self, client_id: &ClientId) -> Result; /// Retrieve the consensus state for the given client ID at the specified /// height. @@ -30,7 +30,7 @@ pub trait ClientValidationContext: Sized { fn consensus_state( &self, client_cons_state_path: &ClientConsensusStatePath, - ) -> Result; + ) -> Result; /// Returns the timestamp and height of the host when it processed a client /// update request at the specified height. @@ -38,7 +38,7 @@ pub trait ClientValidationContext: Sized { &self, client_id: &ClientId, height: &Height, - ) -> Result<(Timestamp, Height), ContextError>; + ) -> Result<(Timestamp, Height), HostError>; } /// Defines the methods that all client `ExecutionContext`s (precisely the @@ -54,7 +54,7 @@ pub trait ClientExecutionContext: { type ClientStateMut: ClientStateExecution; - fn client_state_mut(&self, client_id: &ClientId) -> Result { + fn client_state_mut(&self, client_id: &ClientId) -> Result { self.client_state(client_id) } @@ -63,20 +63,20 @@ pub trait ClientExecutionContext: &mut self, client_state_path: ClientStatePath, client_state: Self::ClientStateRef, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Called upon successful client creation and update fn store_consensus_state( &mut self, consensus_state_path: ClientConsensusStatePath, consensus_state: Self::ConsensusStateRef, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Delete the consensus state from the store located at the given `ClientConsensusStatePath` fn delete_consensus_state( &mut self, consensus_state_path: ClientConsensusStatePath, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Called upon successful client update. /// @@ -88,7 +88,7 @@ pub trait ClientExecutionContext: height: Height, host_timestamp: Timestamp, host_height: Height, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Delete the update time and height associated with the client at the /// specified height. @@ -97,11 +97,7 @@ pub trait ClientExecutionContext: /// specified height. /// /// Note that this timestamp is determined by the host. - fn delete_update_meta( - &mut self, - client_id: ClientId, - height: Height, - ) -> Result<(), ContextError>; + fn delete_update_meta(&mut self, client_id: ClientId, height: Height) -> Result<(), HostError>; } /// An optional trait that extends the client validation context capabilities by @@ -115,27 +111,27 @@ pub trait ClientExecutionContext: /// specific light client requirements. pub trait ExtClientValidationContext: ClientValidationContext { /// Returns the current timestamp of the local chain. - fn host_timestamp(&self) -> Result; + fn host_timestamp(&self) -> Result; /// Returns the current height of the local chain. - fn host_height(&self) -> Result; + fn host_height(&self) -> Result; /// Returns all the heights at which a consensus state is stored. - fn consensus_state_heights(&self, client_id: &ClientId) -> Result, ContextError>; + fn consensus_state_heights(&self, client_id: &ClientId) -> Result, HostError>; /// Search for the lowest consensus state higher than `height`. fn next_consensus_state( &self, client_id: &ClientId, height: &Height, - ) -> Result, ContextError>; + ) -> Result, HostError>; /// Search for the highest consensus state lower than `height`. fn prev_consensus_state( &self, client_id: &ClientId, height: &Height, - ) -> Result, ContextError>; + ) -> Result, HostError>; } /// An optional trait that extends the client context required during execution. diff --git a/ibc-core/ics02-client/src/handler/create_client.rs b/ibc-core/ics02-client/src/handler/create_client.rs index 47f5bab4a..8ea87b2f1 100644 --- a/ibc-core/ics02-client/src/handler/create_client.rs +++ b/ibc-core/ics02-client/src/handler/create_client.rs @@ -5,13 +5,13 @@ use ibc_core_client_types::error::ClientError; use ibc_core_client_types::events::CreateClient; use ibc_core_client_types::msgs::MsgCreateClient; use ibc_core_client_types::Status; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::{ClientStateMut, ClientStateRef, ExecutionContext, ValidationContext}; use ibc_primitives::prelude::*; use ibc_primitives::proto::Any; -pub fn validate(ctx: &Ctx, msg: MsgCreateClient) -> Result<(), ContextError> +pub fn validate(ctx: &Ctx, msg: MsgCreateClient) -> Result<(), HandlerError> where Ctx: ValidationContext, as TryFrom>::Error: Into, @@ -50,7 +50,7 @@ where Ok(()) } -pub fn execute(ctx: &mut Ctx, msg: MsgCreateClient) -> Result<(), ContextError> +pub fn execute(ctx: &mut Ctx, msg: MsgCreateClient) -> Result<(), HandlerError> where Ctx: ExecutionContext, as TryFrom>::Error: Into, diff --git a/ibc-core/ics02-client/src/handler/recover_client.rs b/ibc-core/ics02-client/src/handler/recover_client.rs index 7994edab3..c3e2826b2 100644 --- a/ibc-core/ics02-client/src/handler/recover_client.rs +++ b/ibc-core/ics02-client/src/handler/recover_client.rs @@ -3,7 +3,7 @@ use ibc_core_client_context::prelude::*; use ibc_core_client_types::error::ClientError; use ibc_core_client_types::msgs::MsgRecoverClient; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_host::types::path::ClientConsensusStatePath; use ibc_core_host::{ExecutionContext, ValidationContext}; @@ -11,7 +11,7 @@ use ibc_core_host::{ExecutionContext, ValidationContext}; /// includes validating that the parameters of the subject and substitute clients match, /// as well as validating that the substitute client *is* active and that the subject /// client is *not* active. -pub fn validate(ctx: &Ctx, msg: MsgRecoverClient) -> Result<(), ContextError> +pub fn validate(ctx: &Ctx, msg: MsgRecoverClient) -> Result<(), HandlerError> where Ctx: ValidationContext, { @@ -62,7 +62,7 @@ where /// - copying the substitute client's consensus state as the subject's consensus state /// - setting the subject client's processed height and processed time values to match the substitute client's /// - setting the subject client's latest height, trusting period, and chain ID values to match the substitute client's -pub fn execute(ctx: &mut Ctx, msg: MsgRecoverClient) -> Result<(), ContextError> +pub fn execute(ctx: &mut Ctx, msg: MsgRecoverClient) -> Result<(), HandlerError> where Ctx: ExecutionContext, { diff --git a/ibc-core/ics02-client/src/handler/update_client.rs b/ibc-core/ics02-client/src/handler/update_client.rs index 66ce95ce1..b40d94a68 100644 --- a/ibc-core/ics02-client/src/handler/update_client.rs +++ b/ibc-core/ics02-client/src/handler/update_client.rs @@ -5,13 +5,14 @@ use ibc_core_client_types::error::ClientError; use ibc_core_client_types::events::{ClientMisbehaviour, UpdateClient}; use ibc_core_client_types::msgs::MsgUpdateOrMisbehaviour; use ibc_core_client_types::UpdateKind; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; +use ibc_core_host::types::error::HostError; use ibc_core_host::{ExecutionContext, ValidationContext}; use ibc_primitives::prelude::*; use ibc_primitives::ToVec; -pub fn validate(ctx: &Ctx, msg: MsgUpdateOrMisbehaviour) -> Result<(), ContextError> +pub fn validate(ctx: &Ctx, msg: MsgUpdateOrMisbehaviour) -> Result<(), HandlerError> where Ctx: ValidationContext, { @@ -35,7 +36,7 @@ where Ok(()) } -pub fn execute(ctx: &mut Ctx, msg: MsgUpdateOrMisbehaviour) -> Result<(), ContextError> +pub fn execute(ctx: &mut Ctx, msg: MsgUpdateOrMisbehaviour) -> Result<(), HandlerError> where Ctx: ExecutionContext, { @@ -77,9 +78,9 @@ where { let event = { - let consensus_height = consensus_heights.first().ok_or(ClientError::Other { - description: "client update state returned no updated height".to_string(), - })?; + let consensus_height = consensus_heights.first().ok_or( + HostError::missing_state("missing updated height in client update state"), + )?; IbcEvent::UpdateClient(UpdateClient::new( client_id, diff --git a/ibc-core/ics02-client/src/handler/upgrade_client.rs b/ibc-core/ics02-client/src/handler/upgrade_client.rs index 7dce4cdaa..3fe5f8b95 100644 --- a/ibc-core/ics02-client/src/handler/upgrade_client.rs +++ b/ibc-core/ics02-client/src/handler/upgrade_client.rs @@ -1,16 +1,16 @@ //! Protocol logic specific to processing ICS2 messages of type `MsgUpgradeAnyClient`. //! use ibc_core_client_context::prelude::*; -use ibc_core_client_types::error::ClientError; use ibc_core_client_types::events::UpgradeClient; use ibc_core_client_types::msgs::MsgUpgradeClient; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; +use ibc_core_host::types::error::HostError; use ibc_core_host::types::path::ClientConsensusStatePath; use ibc_core_host::{ExecutionContext, ValidationContext}; use ibc_primitives::prelude::*; -pub fn validate(ctx: &Ctx, msg: MsgUpgradeClient) -> Result<(), ContextError> +pub fn validate(ctx: &Ctx, msg: MsgUpgradeClient) -> Result<(), HandlerError> where Ctx: ValidationContext, { @@ -38,9 +38,12 @@ where ); let old_consensus_state = client_val_ctx .consensus_state(&old_client_cons_state_path) - .map_err(|_| ClientError::MissingConsensusState { - client_id, - height: old_client_state.latest_height(), + .map_err(|_| { + HostError::missing_state(format!( + "missing consensus state for client {} at height {}", + client_id, + old_client_state.latest_height() + )) })?; // Validate the upgraded client state and consensus state and verify proofs against the root @@ -55,7 +58,7 @@ where Ok(()) } -pub fn execute(ctx: &mut Ctx, msg: MsgUpgradeClient) -> Result<(), ContextError> +pub fn execute(ctx: &mut Ctx, msg: MsgUpgradeClient) -> Result<(), HandlerError> where Ctx: ExecutionContext, { diff --git a/ibc-core/ics02-client/types/src/error.rs b/ibc-core/ics02-client/types/src/error.rs index 06f0cfb53..0b15ac36c 100644 --- a/ibc-core/ics02-client/types/src/error.rs +++ b/ibc-core/ics02-client/types/src/error.rs @@ -1,14 +1,11 @@ //! Defines the client error type -use core::convert::Infallible; - use displaydoc::Display; use ibc_core_commitment_types::error::CommitmentError; -use ibc_core_host_types::error::{DecodingError, IdentifierError}; +use ibc_core_host_types::error::{DecodingError, HostError}; use ibc_core_host_types::identifiers::ClientId; use ibc_primitives::prelude::*; use ibc_primitives::Timestamp; -use tendermint::Error as TendermintError; use crate::height::Height; use crate::Status; @@ -16,6 +13,8 @@ use crate::Status; /// Encodes all the possible client errors #[derive(Debug, Display)] pub enum ClientError { + /// host error : `{0}` + Host(HostError), /// upgrade client error: `{0}` Upgrade(UpgradeClientError), /// decoding error: `{0}` @@ -38,6 +37,8 @@ pub enum ClientError { InvalidAttributeValue(String), /// invalid status: `{0}` InvalidStatus(String), + /// invalid header type: `{0}` + InvalidHeaderType(String), /// missing local consensus state at `{0}` MissingLocalConsensusState(Height), /// missing attribute key @@ -61,21 +62,10 @@ pub enum ClientError { FailedHeaderVerification { description: String }, /// failed misbehaviour handling: `{description}` FailedMisbehaviourHandling { description: String }, - /// client-specific error: `{description}` - ClientSpecific { description: String }, - // TODO(seanchen1991): Add these to host-relevant errors - /// missing client state for client: `{0}` - MissingClientState(ClientId), - /// missing consensus state for client `{client_id}` at height `{height}` - MissingConsensusState { client_id: ClientId, height: Height }, - /// missing update client metadata for client `{client_id}` at height `{height}` - MissingUpdateMetaData { client_id: ClientId, height: Height }, - /// invalid raw header: `{0}` - InvalidRawHeader(TendermintError), - /// invalid header type: `{0}` - InvalidHeaderType(String), // TODO(seanchen1991): Incorporate this error into its own variants + /// client-specific error: `{description}` + ClientSpecific { description: String }, /// other error: `{description}` Other { description: String }, } @@ -88,12 +78,6 @@ impl From<&'static str> for ClientError { } } -impl From for ClientError { - fn from(value: Infallible) -> Self { - match value {} - } -} - impl From for ClientError { fn from(e: CommitmentError) -> Self { Self::FailedICS23Verification(e) @@ -106,9 +90,9 @@ impl From for ClientError { } } -impl From for ClientError { - fn from(e: IdentifierError) -> Self { - Self::Decoding(DecodingError::Identifier(e)) +impl From for ClientError { + fn from(e: HostError) -> Self { + Self::Host(e) } } @@ -118,6 +102,8 @@ impl std::error::Error for ClientError { match &self { Self::FailedICS23Verification(e) => Some(e), Self::Decoding(e) => Some(e), + Self::Upgrade(e) => Some(e), + Self::Host(e) => Some(e), _ => None, } } @@ -128,6 +114,10 @@ impl std::error::Error for ClientError { pub enum UpgradeClientError { /// decoding error: `{0}` Decoding(DecodingError), + /// host chain error: `{0}` + Host(HostError), + /// invalid upgrade proposal: `{description}` + InvalidUpgradeProposal { description: String }, /// invalid proof for the upgraded client state: `{0}` InvalidUpgradeClientStateProof(CommitmentError), /// invalid proof for the upgraded consensus state: `{0}` @@ -141,22 +131,6 @@ pub enum UpgradeClientError { upgraded_height: Height, client_height: Height, }, - - // TODO(seanchen1991): Move these variants to host-relevant errors - /// invalid upgrade plan: `{description}` - InvalidUpgradePlan { description: String }, - /// invalid upgrade proposal: `{description}` - InvalidUpgradeProposal { description: String }, - /// missing upgraded client state - MissingUpgradedClientState, - /// missing upgraded consensus state - MissingUpgradedConsensusState, - /// failed to store upgrade plan: `{description}` - FailedToStoreUpgradePlan { description: String }, - /// failed to store upgraded client state: `{description}` - FailedToStoreUpgradedClientState { description: String }, - /// failed to store upgraded consensus state: `{description}` - FailedToStoreUpgradedConsensusState { description: String }, } impl From for ClientError { @@ -171,10 +145,18 @@ impl From for UpgradeClientError { } } +impl From for UpgradeClientError { + fn from(e: HostError) -> Self { + Self::Host(e) + } +} + #[cfg(feature = "std")] impl std::error::Error for UpgradeClientError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match &self { + Self::Decoding(e) => Some(e), + Self::Host(e) => Some(e), Self::InvalidUpgradeClientStateProof(e) | Self::InvalidUpgradeConsensusStateProof(e) => Some(e), _ => None, diff --git a/ibc-core/ics02-client/types/src/events.rs b/ibc-core/ics02-client/types/src/events.rs index 56585036a..c6c36dc3c 100644 --- a/ibc-core/ics02-client/types/src/events.rs +++ b/ibc-core/ics02-client/types/src/events.rs @@ -1,5 +1,7 @@ //! Types for the IBC events emitted from Tendermint Websocket by the client module. + use derive_more::From; +use ibc_core_host_types::error::DecodingError; use ibc_core_host_types::identifiers::{ClientId, ClientType}; use ibc_primitives::prelude::*; use subtle_encoding::hex; @@ -53,26 +55,30 @@ impl From for abci::EventAttribute { } } impl TryFrom for ClientIdAttribute { - type Error = ClientError; + type Error = DecodingError; fn try_from(value: abci::EventAttribute) -> Result { if let Ok(key_str) = value.key_str() { if key_str != CLIENT_ID_ATTRIBUTE_KEY { - return Err(ClientError::InvalidAttributeKey(key_str.to_string())); + return Err(DecodingError::InvalidRawData { + description: format!("invalid attribute key {}", key_str), + }); } } else { - return Err(ClientError::MissingAttributeKey); + return Err(DecodingError::MissingRawData { + description: "missing attribute key".to_string(), + }); } value .value_str() .map(|value| { - let client_id = ClientId::from_str(value) - .map_err(|_| ClientError::InvalidAttributeValue(value.to_string()))?; - + let client_id = ClientId::from_str(value)?; Ok(ClientIdAttribute { client_id }) }) - .map_err(|_| ClientError::MissingAttributeValue)? + .map_err(|e| DecodingError::MissingRawData { + description: format!("missing attribute value: {e}"), + })? } } @@ -101,26 +107,30 @@ impl From for abci::EventAttribute { } impl TryFrom for ClientTypeAttribute { - type Error = ClientError; + type Error = DecodingError; fn try_from(value: abci::EventAttribute) -> Result { if let Ok(key_str) = value.key_str() { if key_str != CLIENT_TYPE_ATTRIBUTE_KEY { - return Err(ClientError::InvalidAttributeKey(key_str.to_string())); + return Err(DecodingError::InvalidRawData { + description: format!("invalid attribute key {}", key_str), + }); } } else { - return Err(ClientError::MissingAttributeKey); + return Err(DecodingError::MissingRawData { + description: "missing attribute key".to_string(), + }); } value .value_str() .map(|value| { - let client_type = ClientType::from_str(value) - .map_err(|_| ClientError::InvalidAttributeValue(value.to_string()))?; - + let client_type = ClientType::from_str(value)?; Ok(ClientTypeAttribute { client_type }) }) - .map_err(|_| ClientError::MissingAttributeValue)? + .map_err(|e| DecodingError::MissingRawData { + description: format!("missing attribute value: {e}"), + })? } } @@ -149,25 +159,33 @@ impl From for abci::EventAttribute { } impl TryFrom for ConsensusHeightAttribute { - type Error = ClientError; + type Error = DecodingError; fn try_from(value: abci::EventAttribute) -> Result { if let Ok(key_str) = value.key_str() { if key_str != CONSENSUS_HEIGHT_ATTRIBUTE_KEY { - return Err(ClientError::InvalidAttributeKey(key_str.to_string())); + return Err(DecodingError::InvalidRawData { + description: format!("invalid attribute key {}", key_str), + }); } } else { - return Err(ClientError::MissingAttributeKey); + return Err(DecodingError::MissingRawData { + description: "missing attribute key".to_string(), + }); } value .value_str() .map(|value| { - let consensus_height = Height::from_str(value) - .map_err(|_| ClientError::InvalidAttributeValue(value.to_string()))?; + let consensus_height = + Height::from_str(value).map_err(|e| DecodingError::InvalidRawData { + description: format!("invalid attribute value: {e}"), + })?; Ok(ConsensusHeightAttribute { consensus_height }) }) - .map_err(|_| ClientError::MissingAttributeValue)? + .map_err(|e| DecodingError::MissingRawData { + description: format!("missing attribute value: {e}"), + })? } } @@ -344,12 +362,12 @@ impl From for abci::Event { } impl TryFrom for CreateClient { - type Error = ClientError; + type Error = DecodingError; fn try_from(value: abci::Event) -> Result { if value.kind != CREATE_CLIENT_EVENT { - return Err(ClientError::Other { - description: "Error in parsing CreateClient event".to_string(), + return Err(DecodingError::InvalidRawData { + description: format!("invalid event kind: expected `{}`", CREATE_CLIENT_EVENT), }); } @@ -366,11 +384,17 @@ impl TryFrom for CreateClient { attribute| { let key = attribute .key_str() - .map_err(|_| ClientError::MissingAttributeKey)?; + .map_err(|_| DecodingError::MissingRawData { + description: "missing attribute key".to_string(), + })?; match key { CLIENT_ID_ATTRIBUTE_KEY => Ok(( - Some(attribute.clone().try_into()?), + Some(attribute.clone().try_into().map_err(|e| { + DecodingError::InvalidRawData { + description: format!("{e}"), + } + })?), client_type, consensus_height, )), @@ -392,10 +416,16 @@ impl TryFrom for CreateClient { Option, Option, )| { - let client_id = client_id.ok_or(ClientError::MissingAttributeKey)?; - let client_type = client_type.ok_or(ClientError::MissingAttributeKey)?; + let client_id = client_id.ok_or(DecodingError::MissingRawData { + description: "missing attribute key".to_string(), + })?; + let client_type = client_type.ok_or(DecodingError::MissingRawData { + description: "missing attribute key".to_string(), + })?; let consensus_height = - consensus_height.ok_or(ClientError::MissingAttributeKey)?; + consensus_height.ok_or(DecodingError::MissingRawData { + description: "missing attribute key".to_string(), + })?; Ok(CreateClient::new( client_id.client_id, @@ -699,6 +729,7 @@ impl From for abci::Event { mod tests { use core::any::Any; + use ibc_core_host_types::error::IdentifierError; use rstest::*; use super::*; @@ -728,9 +759,10 @@ mod tests { abci::EventAttribute::from(("consensus_height", "1-10")), ], }, - Err(ClientError::Other { - description: "Error in parsing CreateClient event".to_string(), - }), + Err(IdentifierError::FailedToParse { + value: "CreateClient".to_string(), + description: "failed to parse event".to_string() + }.into()) )] #[case( abci::Event { @@ -740,11 +772,11 @@ mod tests { abci::EventAttribute::from(("consensus_height", "1-10")), ], }, - Err(ClientError::MissingAttributeKey), + Err(DecodingError::MissingRawData { description: "missing attribute key".to_string() }), )] fn test_create_client_try_from( #[case] event: abci::Event, - #[case] expected: Result, + #[case] expected: Result, ) { let result = CreateClient::try_from(event); if expected.is_err() { diff --git a/ibc-core/ics02-client/types/src/msgs/misbehaviour.rs b/ibc-core/ics02-client/types/src/msgs/misbehaviour.rs index dd627ae02..f923902ba 100644 --- a/ibc-core/ics02-client/types/src/msgs/misbehaviour.rs +++ b/ibc-core/ics02-client/types/src/msgs/misbehaviour.rs @@ -8,8 +8,6 @@ use ibc_proto::google::protobuf::Any as ProtoAny; use ibc_proto::ibc::core::client::v1::MsgSubmitMisbehaviour as RawMsgSubmitMisbehaviour; use ibc_proto::Protobuf; -use crate::error::ClientError; - pub const SUBMIT_MISBEHAVIOUR_TYPE_URL: &str = "/ibc.core.client.v1.MsgSubmitMisbehaviour"; /// A type of message that submits client misbehaviour proof. @@ -38,7 +36,7 @@ pub struct MsgSubmitMisbehaviour { impl Protobuf for MsgSubmitMisbehaviour {} impl TryFrom for MsgSubmitMisbehaviour { - type Error = ClientError; + type Error = DecodingError; fn try_from(raw: RawMsgSubmitMisbehaviour) -> Result { let raw_misbehaviour = raw.misbehaviour.ok_or(DecodingError::MissingRawData { diff --git a/ibc-core/ics02-client/types/src/msgs/recover_client.rs b/ibc-core/ics02-client/types/src/msgs/recover_client.rs index df371e63a..5ef857cba 100644 --- a/ibc-core/ics02-client/types/src/msgs/recover_client.rs +++ b/ibc-core/ics02-client/types/src/msgs/recover_client.rs @@ -1,13 +1,12 @@ //! Definition of domain type message `MsgRecoverClient`. +use ibc_core_host_types::error::DecodingError; use ibc_core_host_types::identifiers::ClientId; use ibc_primitives::prelude::*; use ibc_primitives::Signer; use ibc_proto::ibc::core::client::v1::MsgRecoverClient as RawMsgRecoverClient; use ibc_proto::Protobuf; -use crate::error::ClientError; - pub const RECOVER_CLIENT_TYPE_URL: &str = "/ibc.core.client.v1.MsgRecoverClient"; /// Defines the message used to recover a frozen or expired client. @@ -38,7 +37,7 @@ pub struct MsgRecoverClient { impl Protobuf for MsgRecoverClient {} impl TryFrom for MsgRecoverClient { - type Error = ClientError; + type Error = DecodingError; fn try_from(raw: RawMsgRecoverClient) -> Result { Ok(MsgRecoverClient { diff --git a/ibc-core/ics02-client/types/src/msgs/update_client.rs b/ibc-core/ics02-client/types/src/msgs/update_client.rs index fc99faf9a..16a5d250d 100644 --- a/ibc-core/ics02-client/types/src/msgs/update_client.rs +++ b/ibc-core/ics02-client/types/src/msgs/update_client.rs @@ -8,8 +8,6 @@ use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::core::client::v1::MsgUpdateClient as RawMsgUpdateClient; use ibc_proto::Protobuf; -use crate::error::ClientError; - pub const UPDATE_CLIENT_TYPE_URL: &str = "/ibc.core.client.v1.MsgUpdateClient"; /// Represents the message that triggers the update of an on-chain (IBC) client @@ -31,7 +29,7 @@ pub struct MsgUpdateClient { impl Protobuf for MsgUpdateClient {} impl TryFrom for MsgUpdateClient { - type Error = ClientError; + type Error = DecodingError; fn try_from(raw: RawMsgUpdateClient) -> Result { Ok(MsgUpdateClient { diff --git a/ibc-core/ics02-client/types/src/msgs/upgrade_client.rs b/ibc-core/ics02-client/types/src/msgs/upgrade_client.rs index 90bc14837..f5ed52afb 100644 --- a/ibc-core/ics02-client/types/src/msgs/upgrade_client.rs +++ b/ibc-core/ics02-client/types/src/msgs/upgrade_client.rs @@ -3,7 +3,6 @@ use core::str::FromStr; use ibc_core_commitment_types::commitment::CommitmentProofBytes; -use ibc_core_commitment_types::error::CommitmentError; use ibc_core_host_types::error::DecodingError; use ibc_core_host_types::identifiers::ClientId; use ibc_primitives::prelude::*; @@ -12,8 +11,6 @@ use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::core::client::v1::MsgUpgradeClient as RawMsgUpgradeClient; use ibc_proto::Protobuf; -use crate::error::{ClientError, UpgradeClientError}; - pub const UPGRADE_CLIENT_TYPE_URL: &str = "/ibc.core.client.v1.MsgUpgradeClient"; /// A type of message that triggers the upgrade of an on-chain (IBC) client. @@ -55,7 +52,7 @@ impl From for RawMsgUpgradeClient { } impl TryFrom for MsgUpgradeClient { - type Error = ClientError; + type Error = DecodingError; fn try_from(proto_msg: RawMsgUpgradeClient) -> Result { let raw_client_state = proto_msg @@ -72,17 +69,15 @@ impl TryFrom for MsgUpgradeClient { })?; let c_bytes = - CommitmentProofBytes::try_from(proto_msg.proof_upgrade_client).map_err(|_| { - UpgradeClientError::InvalidUpgradeClientStateProof( - CommitmentError::InvalidMerkleProof, - ) + CommitmentProofBytes::try_from(proto_msg.proof_upgrade_client).map_err(|e| { + DecodingError::InvalidRawData { + description: format!("invalid upgrade client state proof: {e}"), + } })?; let cs_bytes = CommitmentProofBytes::try_from(proto_msg.proof_upgrade_consensus_state) - .map_err(|_| { - UpgradeClientError::InvalidUpgradeConsensusStateProof( - CommitmentError::EmptyMerkleProof, - ) + .map_err(|e| DecodingError::InvalidRawData { + description: format!("invalid upgrade consensus state proof: {e}"), })?; Ok(MsgUpgradeClient { diff --git a/ibc-core/ics03-connection/src/delay.rs b/ibc-core/ics03-connection/src/delay.rs index 82c162e4f..b2c51158a 100644 --- a/ibc-core/ics03-connection/src/delay.rs +++ b/ibc-core/ics03-connection/src/delay.rs @@ -2,14 +2,14 @@ use ibc_core_client::context::ClientValidationContext; use ibc_core_client::types::Height; use ibc_core_connection_types::error::ConnectionError; use ibc_core_connection_types::ConnectionEnd; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_host::ValidationContext; pub fn verify_conn_delay_passed( ctx: &Ctx, packet_proof_height: Height, connection_end: &ConnectionEnd, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where Ctx: ValidationContext, { @@ -31,7 +31,7 @@ where let earliest_valid_time = (last_client_update.0 + conn_delay_time_period) .map_err(ConnectionError::OverflowedTimestamp)?; if current_host_time < earliest_valid_time { - return Err(ContextError::ConnectionError( + return Err(HandlerError::Connection( ConnectionError::InsufficientTimeElapsed { current_host_time, earliest_valid_time, @@ -42,7 +42,7 @@ where // Verify that the current host chain height is later than the last client update height let earliest_valid_height = last_client_update.1.add(conn_delay_height_period); if current_host_height < earliest_valid_height { - return Err(ContextError::ConnectionError( + return Err(HandlerError::Connection( ConnectionError::InsufficientBlocksElapsed { current_host_height, earliest_valid_height, diff --git a/ibc-core/ics03-connection/src/handler/conn_open_ack.rs b/ibc-core/ics03-connection/src/handler/conn_open_ack.rs index 91027ff43..470100833 100644 --- a/ibc-core/ics03-connection/src/handler/conn_open_ack.rs +++ b/ibc-core/ics03-connection/src/handler/conn_open_ack.rs @@ -6,7 +6,7 @@ use ibc_core_connection_types::error::ConnectionError; use ibc_core_connection_types::events::OpenAck; use ibc_core_connection_types::msgs::MsgConnectionOpenAck; use ibc_core_connection_types::{ConnectionEnd, Counterparty, State}; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::identifiers::ClientId; use ibc_core_host::types::path::{ClientConsensusStatePath, ClientStatePath, ConnectionPath, Path}; @@ -17,7 +17,7 @@ use ibc_primitives::ToVec; use crate::handler::{pack_host_consensus_state, unpack_host_client_state}; -pub fn validate(ctx_a: &Ctx, msg: MsgConnectionOpenAck) -> Result<(), ContextError> +pub fn validate(ctx_a: &Ctx, msg: MsgConnectionOpenAck) -> Result<(), HandlerError> where Ctx: ValidationContext, >::Error: Into, @@ -30,7 +30,7 @@ fn validate_impl( ctx_a: &Ctx, msg: &MsgConnectionOpenAck, vars: &LocalVars, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where Ctx: ValidationContext, >::Error: Into, @@ -143,7 +143,7 @@ where Ok(()) } -pub fn execute(ctx_a: &mut Ctx, msg: MsgConnectionOpenAck) -> Result<(), ContextError> +pub fn execute(ctx_a: &mut Ctx, msg: MsgConnectionOpenAck) -> Result<(), HandlerError> where Ctx: ExecutionContext, { @@ -155,7 +155,7 @@ fn execute_impl( ctx_a: &mut Ctx, msg: MsgConnectionOpenAck, vars: LocalVars, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where Ctx: ExecutionContext, { @@ -193,7 +193,7 @@ struct LocalVars { } impl LocalVars { - fn new(ctx_a: &Ctx, msg: &MsgConnectionOpenAck) -> Result + fn new(ctx_a: &Ctx, msg: &MsgConnectionOpenAck) -> Result where Ctx: ValidationContext, { diff --git a/ibc-core/ics03-connection/src/handler/conn_open_confirm.rs b/ibc-core/ics03-connection/src/handler/conn_open_confirm.rs index 1987c047f..414b01006 100644 --- a/ibc-core/ics03-connection/src/handler/conn_open_confirm.rs +++ b/ibc-core/ics03-connection/src/handler/conn_open_confirm.rs @@ -5,7 +5,7 @@ use ibc_core_connection_types::error::ConnectionError; use ibc_core_connection_types::events::OpenConfirm; use ibc_core_connection_types::msgs::MsgConnectionOpenConfirm; use ibc_core_connection_types::{ConnectionEnd, Counterparty, State}; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::identifiers::{ClientId, ConnectionId}; use ibc_core_host::types::path::{ClientConsensusStatePath, ConnectionPath, Path}; @@ -13,7 +13,7 @@ use ibc_core_host::{ExecutionContext, ValidationContext}; use ibc_primitives::prelude::*; use ibc_primitives::proto::Protobuf; -pub fn validate(ctx_b: &Ctx, msg: &MsgConnectionOpenConfirm) -> Result<(), ContextError> +pub fn validate(ctx_b: &Ctx, msg: &MsgConnectionOpenConfirm) -> Result<(), HandlerError> where Ctx: ValidationContext, { @@ -25,7 +25,7 @@ fn validate_impl( ctx_b: &Ctx, msg: &MsgConnectionOpenConfirm, vars: &LocalVars, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where Ctx: ValidationContext, { @@ -88,7 +88,7 @@ where Ok(()) } -pub fn execute(ctx_b: &mut Ctx, msg: &MsgConnectionOpenConfirm) -> Result<(), ContextError> +pub fn execute(ctx_b: &mut Ctx, msg: &MsgConnectionOpenConfirm) -> Result<(), HandlerError> where Ctx: ExecutionContext, { @@ -100,7 +100,7 @@ fn execute_impl( ctx_b: &mut Ctx, msg: &MsgConnectionOpenConfirm, vars: LocalVars, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where Ctx: ExecutionContext, { @@ -137,7 +137,7 @@ struct LocalVars { } impl LocalVars { - fn new(ctx_b: &Ctx, msg: &MsgConnectionOpenConfirm) -> Result + fn new(ctx_b: &Ctx, msg: &MsgConnectionOpenConfirm) -> Result where Ctx: ValidationContext, { diff --git a/ibc-core/ics03-connection/src/handler/conn_open_init.rs b/ibc-core/ics03-connection/src/handler/conn_open_init.rs index 8d4286616..9a42ec556 100644 --- a/ibc-core/ics03-connection/src/handler/conn_open_init.rs +++ b/ibc-core/ics03-connection/src/handler/conn_open_init.rs @@ -3,14 +3,14 @@ use ibc_core_client::context::prelude::*; use ibc_core_connection_types::events::OpenInit; use ibc_core_connection_types::msgs::MsgConnectionOpenInit; use ibc_core_connection_types::{ConnectionEnd, Counterparty, State}; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::identifiers::ConnectionId; use ibc_core_host::types::path::{ClientConnectionPath, ConnectionPath}; use ibc_core_host::{ExecutionContext, ValidationContext}; use ibc_primitives::prelude::*; -pub fn validate(ctx_a: &Ctx, msg: MsgConnectionOpenInit) -> Result<(), ContextError> +pub fn validate(ctx_a: &Ctx, msg: MsgConnectionOpenInit) -> Result<(), HandlerError> where Ctx: ValidationContext, { @@ -32,7 +32,7 @@ where Ok(()) } -pub fn execute(ctx_a: &mut Ctx, msg: MsgConnectionOpenInit) -> Result<(), ContextError> +pub fn execute(ctx_a: &mut Ctx, msg: MsgConnectionOpenInit) -> Result<(), HandlerError> where Ctx: ExecutionContext, { diff --git a/ibc-core/ics03-connection/src/handler/conn_open_try.rs b/ibc-core/ics03-connection/src/handler/conn_open_try.rs index fbb013824..93a963643 100644 --- a/ibc-core/ics03-connection/src/handler/conn_open_try.rs +++ b/ibc-core/ics03-connection/src/handler/conn_open_try.rs @@ -5,7 +5,7 @@ use ibc_core_connection_types::error::ConnectionError; use ibc_core_connection_types::events::OpenTry; use ibc_core_connection_types::msgs::MsgConnectionOpenTry; use ibc_core_connection_types::{ConnectionEnd, Counterparty, State}; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::identifiers::{ClientId, ConnectionId}; use ibc_core_host::types::path::{ @@ -18,7 +18,7 @@ use ibc_primitives::ToVec; use crate::handler::{pack_host_consensus_state, unpack_host_client_state}; -pub fn validate(ctx_b: &Ctx, msg: MsgConnectionOpenTry) -> Result<(), ContextError> +pub fn validate(ctx_b: &Ctx, msg: MsgConnectionOpenTry) -> Result<(), HandlerError> where Ctx: ValidationContext, >::Error: Into, @@ -31,7 +31,7 @@ fn validate_impl( ctx_b: &Ctx, msg: &MsgConnectionOpenTry, vars: &LocalVars, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where Ctx: ValidationContext, >::Error: Into, @@ -139,7 +139,7 @@ where Ok(()) } -pub fn execute(ctx_b: &mut Ctx, msg: MsgConnectionOpenTry) -> Result<(), ContextError> +pub fn execute(ctx_b: &mut Ctx, msg: MsgConnectionOpenTry) -> Result<(), HandlerError> where Ctx: ExecutionContext, { @@ -151,7 +151,7 @@ fn execute_impl( ctx_b: &mut Ctx, msg: MsgConnectionOpenTry, vars: LocalVars, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where Ctx: ExecutionContext, { @@ -188,7 +188,7 @@ struct LocalVars { } impl LocalVars { - fn new(ctx_b: &Ctx, msg: &MsgConnectionOpenTry) -> Result + fn new(ctx_b: &Ctx, msg: &MsgConnectionOpenTry) -> Result where Ctx: ValidationContext, { diff --git a/ibc-core/ics03-connection/src/handler/mod.rs b/ibc-core/ics03-connection/src/handler/mod.rs index f780295e4..8026db244 100644 --- a/ibc-core/ics03-connection/src/handler/mod.rs +++ b/ibc-core/ics03-connection/src/handler/mod.rs @@ -1,5 +1,5 @@ use ibc_core_client::types::error::ClientError; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; #[cfg(feature = "wasm-client")] use ibc_core_host::types::error::DecodingError; use ibc_core_host::types::identifiers::ClientId; @@ -18,7 +18,7 @@ pub mod conn_open_try; pub(crate) fn unpack_host_client_state( value: Any, host_client_id_at_counterparty: &ClientId, -) -> Result +) -> Result where CS: TryFrom, >::Error: Into, @@ -31,7 +31,7 @@ where use prost::Message; let wasm_client_state = WasmClientState::try_from(value).map_err(|e| { - ContextError::ConnectionError(ConnectionError::InvalidClientState { + HandlerError::Connection(ConnectionError::InvalidClientState { description: e.to_string(), }) })?; diff --git a/ibc-core/ics03-connection/types/src/connection.rs b/ibc-core/ics03-connection/types/src/connection.rs index 4ffd8002b..2ce46ff52 100644 --- a/ibc-core/ics03-connection/types/src/connection.rs +++ b/ibc-core/ics03-connection/types/src/connection.rs @@ -208,7 +208,7 @@ impl TryFrom for ConnectionEnd { if value.versions.is_empty() { return Err(DecodingError::MissingRawData { - description: "connection versions is empty".to_string(), + description: "empty connection versions".to_string(), })?; } @@ -218,7 +218,7 @@ impl TryFrom for ConnectionEnd { value .counterparty .ok_or(DecodingError::MissingRawData { - description: "counterparty not set".to_string(), + description: "missing counterparty".to_string(), })? .try_into()?, value diff --git a/ibc-core/ics03-connection/types/src/error.rs b/ibc-core/ics03-connection/types/src/error.rs index 7a4342c74..96febd06f 100644 --- a/ibc-core/ics03-connection/types/src/error.rs +++ b/ibc-core/ics03-connection/types/src/error.rs @@ -34,6 +34,8 @@ pub enum ConnectionError { MissingCommonFeatures, /// missing counterparty MissingCounterparty, + /// missing connection `{0}` + MissingConnection(ConnectionId), /// insufficient consensus height `{current_height}` for host chain; needs to meet counterparty's height `{target_height}` InsufficientConsensusHeight { target_height: Height, @@ -57,18 +59,6 @@ pub enum ConnectionError { FailedToVerifyClientState(ClientError), /// overflowed timestamp: `{0}` OverflowedTimestamp(TimestampError), - - // TODO(seanchen1991): Move these variants to host-relevant error types - /// missing connection `{0}` - MissingConnection(ConnectionId), - /// missing connection counter - MissingConnectionCounter, - /// failed to store connection IDs - FailedToStoreConnectionIds, - /// failed to store connection end - FailedToStoreConnectionEnd, - /// failed to update connection counter - FailedToUpdateConnectionCounter, } impl From for ConnectionError { diff --git a/ibc-core/ics03-connection/types/src/version.rs b/ibc-core/ics03-connection/types/src/version.rs index ac8f9d975..5a2061edf 100644 --- a/ibc-core/ics03-connection/types/src/version.rs +++ b/ibc-core/ics03-connection/types/src/version.rs @@ -120,12 +120,13 @@ impl Display for Version { /// compatible version continues. This function is called in the `conn_open_try` /// handshake procedure. /// -/// NOTE: Empty feature set is not currently allowed for a chosen version. +/// NOTE: Empty feature sets are not currently allowed for a chosen version. pub fn pick_version( supported_versions: &[Version], counterparty_versions: &[Version], ) -> Result { let mut intersection: Vec = Vec::new(); + for sv in supported_versions.iter() { if let Ok(cv) = find_supported_version(sv, counterparty_versions) { if let Ok(feature_set) = get_feature_set_intersection(&sv.features, &cv.features) { @@ -142,6 +143,7 @@ pub fn pick_version( } intersection.sort_by(|a, b| a.identifier.cmp(&b.identifier)); + Ok(intersection[0].clone()) } diff --git a/ibc-core/ics04-channel/src/context.rs b/ibc-core/ics04-channel/src/context.rs index 1fba1de8f..92844b4d4 100644 --- a/ibc-core/ics04-channel/src/context.rs +++ b/ibc-core/ics04-channel/src/context.rs @@ -4,8 +4,8 @@ use ibc_core_channel_types::channel::ChannelEnd; use ibc_core_channel_types::commitment::PacketCommitment; use ibc_core_client::context::prelude::*; use ibc_core_connection::types::ConnectionEnd; -use ibc_core_handler_types::error::ContextError; use ibc_core_handler_types::events::IbcEvent; +use ibc_core_host::types::error::HostError; use ibc_core_host::types::identifiers::{ConnectionId, Sequence}; use ibc_core_host::types::path::{ChannelEndPath, CommitmentPath, SeqSendPath}; use ibc_core_host::{ExecutionContext, ValidationContext}; @@ -19,13 +19,12 @@ pub trait SendPacketValidationContext { fn get_client_validation_context(&self) -> &Self::V; /// Returns the ChannelEnd for the given `port_id` and `chan_id`. - fn channel_end(&self, channel_end_path: &ChannelEndPath) -> Result; + fn channel_end(&self, channel_end_path: &ChannelEndPath) -> Result; /// Returns the ConnectionState for the given identifier `connection_id`. - fn connection_end(&self, connection_id: &ConnectionId) -> Result; + fn connection_end(&self, connection_id: &ConnectionId) -> Result; - fn get_next_sequence_send(&self, seq_send_path: &SeqSendPath) - -> Result; + fn get_next_sequence_send(&self, seq_send_path: &SeqSendPath) -> Result; } impl SendPacketValidationContext for T @@ -38,18 +37,15 @@ where self.get_client_validation_context() } - fn channel_end(&self, channel_end_path: &ChannelEndPath) -> Result { + fn channel_end(&self, channel_end_path: &ChannelEndPath) -> Result { self.channel_end(channel_end_path) } - fn connection_end(&self, connection_id: &ConnectionId) -> Result { + fn connection_end(&self, connection_id: &ConnectionId) -> Result { self.connection_end(connection_id) } - fn get_next_sequence_send( - &self, - seq_send_path: &SeqSendPath, - ) -> Result { + fn get_next_sequence_send(&self, seq_send_path: &SeqSendPath) -> Result { self.get_next_sequence_send(seq_send_path) } } @@ -60,19 +56,19 @@ pub trait SendPacketExecutionContext: SendPacketValidationContext { &mut self, seq_send_path: &SeqSendPath, seq: Sequence, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; fn store_packet_commitment( &mut self, commitment_path: &CommitmentPath, commitment: PacketCommitment, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Ibc events - fn emit_ibc_event(&mut self, event: IbcEvent) -> Result<(), ContextError>; + fn emit_ibc_event(&mut self, event: IbcEvent) -> Result<(), HostError>; /// Logging facility - fn log_message(&mut self, message: String) -> Result<(), ContextError>; + fn log_message(&mut self, message: String) -> Result<(), HostError>; } impl SendPacketExecutionContext for T @@ -83,7 +79,7 @@ where &mut self, seq_send_path: &SeqSendPath, seq: Sequence, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { self.store_next_sequence_send(seq_send_path, seq) } @@ -91,15 +87,15 @@ where &mut self, commitment_path: &CommitmentPath, commitment: PacketCommitment, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { self.store_packet_commitment(commitment_path, commitment) } - fn emit_ibc_event(&mut self, event: IbcEvent) -> Result<(), ContextError> { + fn emit_ibc_event(&mut self, event: IbcEvent) -> Result<(), HostError> { self.emit_ibc_event(event) } - fn log_message(&mut self, message: String) -> Result<(), ContextError> { + fn log_message(&mut self, message: String) -> Result<(), HostError> { self.log_message(message) } } diff --git a/ibc-core/ics04-channel/src/handler/acknowledgement.rs b/ibc-core/ics04-channel/src/handler/acknowledgement.rs index e5f484f2b..4c7b1c30e 100644 --- a/ibc-core/ics04-channel/src/handler/acknowledgement.rs +++ b/ibc-core/ics04-channel/src/handler/acknowledgement.rs @@ -6,7 +6,7 @@ use ibc_core_channel_types::msgs::MsgAcknowledgement; use ibc_core_client::context::prelude::*; use ibc_core_connection::delay::verify_conn_delay_passed; use ibc_core_connection::types::State as ConnectionState; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::path::{ AckPath, ChannelEndPath, ClientConsensusStatePath, CommitmentPath, Path, SeqAckPath, @@ -19,7 +19,7 @@ pub fn acknowledgement_packet_validate( ctx_a: &ValCtx, module: &dyn Module, msg: MsgAcknowledgement, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ValCtx: ValidationContext, { @@ -27,14 +27,14 @@ where module .on_acknowledgement_packet_validate(&msg.packet, &msg.acknowledgement, &msg.signer) - .map_err(ContextError::PacketError) + .map_err(HandlerError::Packet) } pub fn acknowledgement_packet_execute( ctx_a: &mut ExecCtx, module: &mut dyn Module, msg: MsgAcknowledgement, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ExecCtx: ExecutionContext, { @@ -103,7 +103,7 @@ where Ok(()) } -fn validate(ctx_a: &Ctx, msg: &MsgAcknowledgement) -> Result<(), ContextError> +fn validate(ctx_a: &Ctx, msg: &MsgAcknowledgement) -> Result<(), HandlerError> where Ctx: ValidationContext, { diff --git a/ibc-core/ics04-channel/src/handler/chan_close_confirm.rs b/ibc-core/ics04-channel/src/handler/chan_close_confirm.rs index 5b315ecbf..e9cc78d5c 100644 --- a/ibc-core/ics04-channel/src/handler/chan_close_confirm.rs +++ b/ibc-core/ics04-channel/src/handler/chan_close_confirm.rs @@ -7,7 +7,7 @@ use ibc_core_channel_types::msgs::MsgChannelCloseConfirm; use ibc_core_client::context::prelude::*; use ibc_core_connection::types::State as ConnectionState; use ibc_core_connection_types::error::ConnectionError; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::path::{ChannelEndPath, ClientConsensusStatePath, Path}; use ibc_core_host::{ExecutionContext, ValidationContext}; @@ -19,7 +19,7 @@ pub fn chan_close_confirm_validate( ctx_b: &ValCtx, module: &dyn Module, msg: MsgChannelCloseConfirm, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ValCtx: ValidationContext, { @@ -34,7 +34,7 @@ pub fn chan_close_confirm_execute( ctx_b: &mut ExecCtx, module: &mut dyn Module, msg: MsgChannelCloseConfirm, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ExecCtx: ExecutionContext, { @@ -58,9 +58,11 @@ where let core_event = { let port_id_on_a = chan_end_on_b.counterparty().port_id.clone(); - let chan_id_on_a = chan_end_on_b.counterparty().channel_id.clone().ok_or( - ContextError::ChannelError(ChannelError::MissingCounterparty), - )?; + let chan_id_on_a = chan_end_on_b + .counterparty() + .channel_id + .clone() + .ok_or(HandlerError::Channel(ChannelError::MissingCounterparty))?; let conn_id_on_b = chan_end_on_b.connection_hops[0].clone(); IbcEvent::CloseConfirmChannel(CloseConfirm::new( @@ -86,7 +88,7 @@ where Ok(()) } -fn validate(ctx_b: &Ctx, msg: &MsgChannelCloseConfirm) -> Result<(), ContextError> +fn validate(ctx_b: &Ctx, msg: &MsgChannelCloseConfirm) -> Result<(), HandlerError> where Ctx: ValidationContext, { diff --git a/ibc-core/ics04-channel/src/handler/chan_close_init.rs b/ibc-core/ics04-channel/src/handler/chan_close_init.rs index 6bdab73f6..0f0cd557d 100644 --- a/ibc-core/ics04-channel/src/handler/chan_close_init.rs +++ b/ibc-core/ics04-channel/src/handler/chan_close_init.rs @@ -5,7 +5,7 @@ use ibc_core_channel_types::events::CloseInit; use ibc_core_channel_types::msgs::MsgChannelCloseInit; use ibc_core_client::context::prelude::*; use ibc_core_connection::types::State as ConnectionState; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::path::ChannelEndPath; use ibc_core_host::{ExecutionContext, ValidationContext}; @@ -16,7 +16,7 @@ pub fn chan_close_init_validate( ctx_a: &ValCtx, module: &dyn Module, msg: MsgChannelCloseInit, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ValCtx: ValidationContext, { @@ -31,7 +31,7 @@ pub fn chan_close_init_execute( ctx_a: &mut ExecCtx, module: &mut dyn Module, msg: MsgChannelCloseInit, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ExecCtx: ExecutionContext, { @@ -56,9 +56,11 @@ where let core_event = { 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.clone().ok_or( - ContextError::ChannelError(ChannelError::MissingCounterparty), - )?; + let chan_id_on_b = chan_end_on_a + .counterparty() + .channel_id + .clone() + .ok_or(HandlerError::Channel(ChannelError::MissingCounterparty))?; let conn_id_on_a = chan_end_on_a.connection_hops[0].clone(); IbcEvent::CloseInitChannel(CloseInit::new( @@ -84,7 +86,7 @@ where Ok(()) } -fn validate(ctx_a: &Ctx, msg: &MsgChannelCloseInit) -> Result<(), ContextError> +fn validate(ctx_a: &Ctx, msg: &MsgChannelCloseInit) -> Result<(), HandlerError> where Ctx: ValidationContext, { diff --git a/ibc-core/ics04-channel/src/handler/chan_open_ack.rs b/ibc-core/ics04-channel/src/handler/chan_open_ack.rs index f6271bcd0..64aff01d6 100644 --- a/ibc-core/ics04-channel/src/handler/chan_open_ack.rs +++ b/ibc-core/ics04-channel/src/handler/chan_open_ack.rs @@ -6,7 +6,7 @@ use ibc_core_channel_types::msgs::MsgChannelOpenAck; use ibc_core_client::context::prelude::*; use ibc_core_connection::types::State as ConnectionState; use ibc_core_connection_types::error::ConnectionError; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::path::{ChannelEndPath, ClientConsensusStatePath, Path}; use ibc_core_host::{ExecutionContext, ValidationContext}; @@ -18,7 +18,7 @@ pub fn chan_open_ack_validate( ctx_a: &ValCtx, module: &dyn Module, msg: MsgChannelOpenAck, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ValCtx: ValidationContext, { @@ -33,7 +33,7 @@ pub fn chan_open_ack_execute( ctx_a: &mut ExecCtx, module: &mut dyn Module, msg: MsgChannelOpenAck, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ExecCtx: ExecutionContext, { @@ -87,7 +87,7 @@ where Ok(()) } -fn validate(ctx_a: &Ctx, msg: &MsgChannelOpenAck) -> Result<(), ContextError> +fn validate(ctx_a: &Ctx, msg: &MsgChannelOpenAck) -> Result<(), HandlerError> where Ctx: ValidationContext, { diff --git a/ibc-core/ics04-channel/src/handler/chan_open_confirm.rs b/ibc-core/ics04-channel/src/handler/chan_open_confirm.rs index 2ea7078a4..e3ade9e35 100644 --- a/ibc-core/ics04-channel/src/handler/chan_open_confirm.rs +++ b/ibc-core/ics04-channel/src/handler/chan_open_confirm.rs @@ -7,7 +7,7 @@ use ibc_core_channel_types::msgs::MsgChannelOpenConfirm; use ibc_core_client::context::prelude::*; use ibc_core_connection::types::State as ConnectionState; use ibc_core_connection_types::error::ConnectionError; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::path::{ChannelEndPath, ClientConsensusStatePath, Path}; use ibc_core_host::{ExecutionContext, ValidationContext}; @@ -19,7 +19,7 @@ pub fn chan_open_confirm_validate( ctx_b: &ValCtx, module: &dyn Module, msg: MsgChannelOpenConfirm, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ValCtx: ValidationContext, { @@ -34,7 +34,7 @@ pub fn chan_open_confirm_execute( ctx_b: &mut ExecCtx, module: &mut dyn Module, msg: MsgChannelOpenConfirm, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ExecCtx: ExecutionContext, { @@ -59,14 +59,11 @@ where let conn_id_on_b = chan_end_on_b.connection_hops[0].clone(); let port_id_on_a = chan_end_on_b.counterparty().port_id.clone(); - let chan_id_on_a = - chan_end_on_b - .counterparty() - .channel_id - .clone() - .ok_or(ContextError::ChannelError( - ChannelError::MissingCounterparty, - ))?; + let chan_id_on_a = chan_end_on_b + .counterparty() + .channel_id + .clone() + .ok_or(HandlerError::Channel(ChannelError::MissingCounterparty))?; let core_event = IbcEvent::OpenConfirmChannel(OpenConfirm::new( msg.port_id_on_b.clone(), @@ -90,7 +87,7 @@ where Ok(()) } -fn validate(ctx_b: &Ctx, msg: &MsgChannelOpenConfirm) -> Result<(), ContextError> +fn validate(ctx_b: &Ctx, msg: &MsgChannelOpenConfirm) -> Result<(), HandlerError> where Ctx: ValidationContext, { diff --git a/ibc-core/ics04-channel/src/handler/chan_open_init.rs b/ibc-core/ics04-channel/src/handler/chan_open_init.rs index 58a161d0b..b952e7d1a 100644 --- a/ibc-core/ics04-channel/src/handler/chan_open_init.rs +++ b/ibc-core/ics04-channel/src/handler/chan_open_init.rs @@ -4,7 +4,7 @@ use ibc_core_channel_types::channel::{ChannelEnd, Counterparty, State}; use ibc_core_channel_types::events::OpenInit; use ibc_core_channel_types::msgs::MsgChannelOpenInit; use ibc_core_client::context::prelude::*; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::identifiers::ChannelId; use ibc_core_host::types::path::{ChannelEndPath, SeqAckPath, SeqRecvPath, SeqSendPath}; @@ -16,7 +16,7 @@ pub fn chan_open_init_validate( ctx_a: &ValCtx, module: &dyn Module, msg: MsgChannelOpenInit, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ValCtx: ValidationContext, { @@ -39,7 +39,7 @@ pub fn chan_open_init_execute( ctx_a: &mut ExecCtx, module: &mut dyn Module, msg: MsgChannelOpenInit, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ExecCtx: ExecutionContext, { @@ -107,7 +107,7 @@ where Ok(()) } -fn validate(ctx_a: &Ctx, msg: &MsgChannelOpenInit) -> Result<(), ContextError> +fn validate(ctx_a: &Ctx, msg: &MsgChannelOpenInit) -> Result<(), HandlerError> where Ctx: ValidationContext, { diff --git a/ibc-core/ics04-channel/src/handler/chan_open_try.rs b/ibc-core/ics04-channel/src/handler/chan_open_try.rs index 48138ce69..09ca21604 100644 --- a/ibc-core/ics04-channel/src/handler/chan_open_try.rs +++ b/ibc-core/ics04-channel/src/handler/chan_open_try.rs @@ -7,7 +7,7 @@ use ibc_core_channel_types::msgs::MsgChannelOpenTry; use ibc_core_client::context::prelude::*; use ibc_core_connection::types::State as ConnectionState; use ibc_core_connection_types::error::ConnectionError; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::identifiers::ChannelId; use ibc_core_host::types::path::{ @@ -22,7 +22,7 @@ pub fn chan_open_try_validate( ctx_b: &ValCtx, module: &dyn Module, msg: MsgChannelOpenTry, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ValCtx: ValidationContext, { @@ -46,7 +46,7 @@ pub fn chan_open_try_execute( ctx_b: &mut ExecCtx, module: &mut dyn Module, msg: MsgChannelOpenTry, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ExecCtx: ExecutionContext, { @@ -116,7 +116,7 @@ where Ok(()) } -fn validate(ctx_b: &Ctx, msg: &MsgChannelOpenTry) -> Result<(), ContextError> +fn validate(ctx_b: &Ctx, msg: &MsgChannelOpenTry) -> Result<(), HandlerError> where Ctx: ValidationContext, { diff --git a/ibc-core/ics04-channel/src/handler/recv_packet.rs b/ibc-core/ics04-channel/src/handler/recv_packet.rs index 95a47dd49..faa0ffe02 100644 --- a/ibc-core/ics04-channel/src/handler/recv_packet.rs +++ b/ibc-core/ics04-channel/src/handler/recv_packet.rs @@ -7,7 +7,7 @@ use ibc_core_channel_types::packet::Receipt; use ibc_core_client::context::prelude::*; use ibc_core_connection::delay::verify_conn_delay_passed; use ibc_core_connection::types::State as ConnectionState; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::path::{ AckPath, ChannelEndPath, ClientConsensusStatePath, CommitmentPath, Path, ReceiptPath, @@ -17,7 +17,7 @@ use ibc_core_host::{ExecutionContext, ValidationContext}; use ibc_core_router::module::Module; use ibc_primitives::prelude::*; -pub fn recv_packet_validate(ctx_b: &ValCtx, msg: MsgRecvPacket) -> Result<(), ContextError> +pub fn recv_packet_validate(ctx_b: &ValCtx, msg: MsgRecvPacket) -> Result<(), HandlerError> where ValCtx: ValidationContext, { @@ -32,7 +32,7 @@ pub fn recv_packet_execute( ctx_b: &mut ExecCtx, module: &mut dyn Module, msg: MsgRecvPacket, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ExecCtx: ExecutionContext, { @@ -136,7 +136,7 @@ where Ok(()) } -fn validate(ctx_b: &Ctx, msg: &MsgRecvPacket) -> Result<(), ContextError> +fn validate(ctx_b: &Ctx, msg: &MsgRecvPacket) -> Result<(), HandlerError> where Ctx: ValidationContext, { @@ -254,8 +254,8 @@ where validate_write_acknowledgement(ctx_b, msg)?; } Order::None => { - return Err(ContextError::ChannelError(ChannelError::InvalidOrderType { - expected: "Channel ordering cannot be None".to_string(), + return Err(HandlerError::Channel(ChannelError::InvalidOrderType { + expected: "Channel ordering to not be None".to_string(), actual: chan_end_on_b.ordering.to_string(), })) } @@ -264,7 +264,7 @@ where Ok(()) } -fn validate_write_acknowledgement(ctx_b: &Ctx, msg: &MsgRecvPacket) -> Result<(), ContextError> +fn validate_write_acknowledgement(ctx_b: &Ctx, msg: &MsgRecvPacket) -> Result<(), HandlerError> where Ctx: ValidationContext, { diff --git a/ibc-core/ics04-channel/src/handler/send_packet.rs b/ibc-core/ics04-channel/src/handler/send_packet.rs index 6680bf6fb..c15b03d21 100644 --- a/ibc-core/ics04-channel/src/handler/send_packet.rs +++ b/ibc-core/ics04-channel/src/handler/send_packet.rs @@ -4,7 +4,7 @@ use ibc_core_channel_types::error::PacketError; use ibc_core_channel_types::events::SendPacket; use ibc_core_channel_types::packet::Packet; use ibc_core_client::context::prelude::*; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::path::{ ChannelEndPath, ClientConsensusStatePath, CommitmentPath, SeqSendPath, @@ -19,7 +19,7 @@ use crate::context::{SendPacketExecutionContext, SendPacketValidationContext}; pub fn send_packet( ctx_a: &mut impl SendPacketExecutionContext, packet: Packet, -) -> Result<(), ContextError> { +) -> Result<(), HandlerError> { send_packet_validate(ctx_a, &packet)?; send_packet_execute(ctx_a, packet) } @@ -28,9 +28,9 @@ pub fn send_packet( pub fn send_packet_validate( ctx_a: &impl SendPacketValidationContext, packet: &Packet, -) -> Result<(), ContextError> { +) -> Result<(), HandlerError> { if !packet.timeout_height_on_b.is_set() && !packet.timeout_timestamp_on_b.is_set() { - return Err(ContextError::PacketError(PacketError::MissingTimeout)); + return Err(HandlerError::Packet(PacketError::MissingTimeout)); } let chan_end_path_on_a = ChannelEndPath::new(&packet.port_id_on_a, &packet.chan_id_on_a); @@ -104,7 +104,7 @@ pub fn send_packet_validate( pub fn send_packet_execute( ctx_a: &mut impl SendPacketExecutionContext, packet: Packet, -) -> Result<(), ContextError> { +) -> Result<(), HandlerError> { { let seq_send_path_on_a = SeqSendPath::new(&packet.port_id_on_a, &packet.chan_id_on_a); let next_seq_send_on_a = ctx_a.get_next_sequence_send(&seq_send_path_on_a)?; diff --git a/ibc-core/ics04-channel/src/handler/timeout.rs b/ibc-core/ics04-channel/src/handler/timeout.rs index 9ce98bc0a..9e587256d 100644 --- a/ibc-core/ics04-channel/src/handler/timeout.rs +++ b/ibc-core/ics04-channel/src/handler/timeout.rs @@ -5,7 +5,7 @@ use ibc_core_channel_types::events::{ChannelClosed, TimeoutPacket}; use ibc_core_channel_types::msgs::{MsgTimeout, MsgTimeoutOnClose}; use ibc_core_client::context::prelude::*; use ibc_core_connection::delay::verify_conn_delay_passed; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::path::{ ChannelEndPath, ClientConsensusStatePath, CommitmentPath, Path, ReceiptPath, SeqRecvPath, @@ -25,7 +25,7 @@ pub fn timeout_packet_validate( ctx_a: &ValCtx, module: &dyn Module, timeout_msg_type: TimeoutMsgType, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ValCtx: ValidationContext, { @@ -41,14 +41,14 @@ where module .on_timeout_packet_validate(&packet, &signer) - .map_err(ContextError::PacketError) + .map_err(HandlerError::Packet) } pub fn timeout_packet_execute( ctx_a: &mut ExecCtx, module: &mut dyn Module, timeout_msg_type: TimeoutMsgType, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where ExecCtx: ExecutionContext, { @@ -126,7 +126,7 @@ where Ok(()) } -fn validate(ctx_a: &Ctx, msg: &MsgTimeout) -> Result<(), ContextError> +fn validate(ctx_a: &Ctx, msg: &MsgTimeout) -> Result<(), HandlerError> where Ctx: ValidationContext, { @@ -247,7 +247,7 @@ where ) } Order::None => { - return Err(ContextError::ChannelError(ChannelError::InvalidOrderType { + return Err(HandlerError::Channel(ChannelError::InvalidOrderType { expected: "Channel ordering cannot be None".to_string(), actual: chan_end_on_a.ordering.to_string(), })) diff --git a/ibc-core/ics04-channel/src/handler/timeout_on_close.rs b/ibc-core/ics04-channel/src/handler/timeout_on_close.rs index c52225f81..e6bd30724 100644 --- a/ibc-core/ics04-channel/src/handler/timeout_on_close.rs +++ b/ibc-core/ics04-channel/src/handler/timeout_on_close.rs @@ -5,7 +5,7 @@ use ibc_core_channel_types::msgs::MsgTimeoutOnClose; use ibc_core_client::context::prelude::*; use ibc_core_connection::delay::verify_conn_delay_passed; use ibc_core_connection::types::error::ConnectionError; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_host::types::path::{ ChannelEndPath, ClientConsensusStatePath, CommitmentPath, Path, ReceiptPath, SeqRecvPath, }; @@ -13,7 +13,7 @@ use ibc_core_host::ValidationContext; use ibc_primitives::prelude::*; use ibc_primitives::proto::Protobuf; -pub fn validate(ctx_a: &Ctx, msg: &MsgTimeoutOnClose) -> Result<(), ContextError> +pub fn validate(ctx_a: &Ctx, msg: &MsgTimeoutOnClose) -> Result<(), HandlerError> where Ctx: ValidationContext, { @@ -155,7 +155,7 @@ where ) } Order::None => { - return Err(ContextError::ChannelError(ChannelError::InvalidOrderType { + return Err(HandlerError::Channel(ChannelError::InvalidOrderType { expected: "Channel ordering cannot be None".to_string(), actual: chan_end_on_a.ordering.to_string(), })) diff --git a/ibc-core/ics04-channel/types/src/error.rs b/ibc-core/ics04-channel/types/src/error.rs index 4e0551e66..722c5bf26 100644 --- a/ibc-core/ics04-channel/types/src/error.rs +++ b/ibc-core/ics04-channel/types/src/error.rs @@ -53,17 +53,6 @@ pub enum ChannelError { }, /// failed proof verification: `{0}` FailedProofVerification(ClientError), - - // TODO(seanchen1991): These variants should be encoded by host-relevant error types - // once those have been defined. - /// application module error: `{description}` - AppModule { description: String }, - /// missing channel counter - MissingCounter, - /// failed to update counter: `{description}` - FailedToUpdateCounter { description: String }, - /// failed to store channel: `{description}` - FailedToStoreChannel { description: String }, } #[derive(Debug, Display)] @@ -109,16 +98,6 @@ pub enum PacketError { timeout_timestamp: TimeoutTimestamp, chain_timestamp: Timestamp, }, - - // TODO(seanchen1991): Move these variants to host-relevant error types - /// application module error: `{description}` - AppModule { description: String }, - /// missing acknowledgment for packet `{0}` - MissingPacketAcknowledgment(Sequence), - /// missing packet receipt for packet `{0}` - MissingPacketReceipt(Sequence), - /// implementation-specific error - ImplementationSpecific, } impl From for ChannelError { diff --git a/ibc-core/ics24-host/cosmos/src/upgrade_proposal/context.rs b/ibc-core/ics24-host/cosmos/src/upgrade_proposal/context.rs index 1328355e8..89ec14ff3 100644 --- a/ibc-core/ics24-host/cosmos/src/upgrade_proposal/context.rs +++ b/ibc-core/ics24-host/cosmos/src/upgrade_proposal/context.rs @@ -6,7 +6,7 @@ //! If it proves to be generic enough, we may move it to the ICS02 section. use ibc_core_client_context::ClientValidationContext; -use ibc_core_client_types::error::UpgradeClientError; +use ibc_core_host_types::error::HostError; use ibc_core_host_types::path::{UpgradeClientStatePath, UpgradeConsensusStatePath}; use super::Plan; @@ -23,41 +23,41 @@ pub trait UpgradeValidationContext { type V: ClientValidationContext; /// Returns the upgrade plan that is scheduled and has not been executed yet. - fn upgrade_plan(&self) -> Result; + fn upgrade_plan(&self) -> Result; /// Returns the upgraded client state at the specified upgrade path. fn upgraded_client_state( &self, upgrade_path: &UpgradeClientStatePath, - ) -> Result, UpgradeClientError>; + ) -> Result, HostError>; /// Returns the upgraded consensus state at the specified upgrade path. fn upgraded_consensus_state( &self, upgrade_path: &UpgradeConsensusStatePath, - ) -> Result, UpgradeClientError>; + ) -> Result, HostError>; } /// Helper context to execute client upgrades, providing methods to schedule /// an upgrade and store related upgraded client and consensus states. pub trait UpgradeExecutionContext: UpgradeValidationContext { /// Schedules an upgrade based on the specified plan. If there is another `Plan` it should be overwritten. - fn schedule_upgrade(&mut self, plan: Plan) -> Result<(), UpgradeClientError>; + fn schedule_upgrade(&mut self, plan: Plan) -> Result<(), HostError>; /// Clears the upgrade plan at the specified height. - fn clear_upgrade_plan(&mut self, plan_height: u64) -> Result<(), UpgradeClientError>; + fn clear_upgrade_plan(&mut self, plan_height: u64) -> Result<(), HostError>; /// Stores the upgraded client state at the specified upgrade path. fn store_upgraded_client_state( &mut self, upgrade_path: UpgradeClientStatePath, client_state: UpgradedClientStateRef, - ) -> Result<(), UpgradeClientError>; + ) -> Result<(), HostError>; /// Stores the upgraded consensus state at the specified upgrade path. fn store_upgraded_consensus_state( &mut self, upgrade_path: UpgradeConsensusStatePath, consensus_state: UpgradedConsensusStateRef, - ) -> Result<(), UpgradeClientError>; + ) -> Result<(), HostError>; } diff --git a/ibc-core/ics24-host/cosmos/src/upgrade_proposal/plan.rs b/ibc-core/ics24-host/cosmos/src/upgrade_proposal/plan.rs index 48ceaf0e5..ccba17567 100644 --- a/ibc-core/ics24-host/cosmos/src/upgrade_proposal/plan.rs +++ b/ibc-core/ics24-host/cosmos/src/upgrade_proposal/plan.rs @@ -1,7 +1,7 @@ //! Definition of domain `Plan` type. use ibc_core_client_types::error::UpgradeClientError; -use ibc_core_host_types::error::DecodingError; +use ibc_core_host_types::error::{DecodingError, IdentifierError}; use ibc_primitives::prelude::*; use ibc_proto::cosmos::upgrade::v1beta1::Plan as RawPlan; use ibc_proto::google::protobuf::Any; @@ -29,35 +29,33 @@ pub struct Plan { impl Protobuf for Plan {} impl TryFrom for Plan { - type Error = UpgradeClientError; + type Error = DecodingError; fn try_from(raw: RawPlan) -> Result { if raw.name.is_empty() { - return Err(UpgradeClientError::InvalidUpgradePlan { - description: "name field cannot be empty".to_string(), + return Err(DecodingError::InvalidRawData { + description: "upgrade plan name cannot be empty".to_string(), }); } #[allow(deprecated)] if raw.time.is_some() { - return Err(UpgradeClientError::InvalidUpgradePlan { - description: "time field must be empty".to_string(), + return Err(DecodingError::InvalidRawData { + description: "upgrade plan time must be empty".to_string(), }); } #[allow(deprecated)] if raw.upgraded_client_state.is_some() { - return Err(UpgradeClientError::InvalidUpgradePlan { - description: "upgraded_client_state field must be empty".to_string(), + return Err(DecodingError::InvalidRawData { + description: "upgrade plan `upgraded_client_state` field must be empty".to_string(), }); } Ok(Self { name: raw.name, height: u64::try_from(raw.height).map_err(|_| { - UpgradeClientError::InvalidUpgradePlan { - description: "height plan overflow".to_string(), - } + DecodingError::Identifier(IdentifierError::OverflowedRevisionNumber) })?, info: raw.info, }) diff --git a/ibc-core/ics24-host/cosmos/src/upgrade_proposal/proposal.rs b/ibc-core/ics24-host/cosmos/src/upgrade_proposal/proposal.rs index f069e6852..9de0a272a 100644 --- a/ibc-core/ics24-host/cosmos/src/upgrade_proposal/proposal.rs +++ b/ibc-core/ics24-host/cosmos/src/upgrade_proposal/proposal.rs @@ -1,6 +1,6 @@ //! Definition of domain `UpgradeProposal` type for handling upgrade client proposal -use ibc_core_client_types::error::UpgradeClientError; +use ibc_core_host_types::error::DecodingError; use ibc_primitives::prelude::*; use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::core::client::v1::UpgradeProposal as RawUpgradeProposal; @@ -28,34 +28,35 @@ pub struct UpgradeProposal { impl Protobuf for UpgradeProposal {} impl TryFrom for UpgradeProposal { - type Error = UpgradeClientError; + type Error = DecodingError; fn try_from(raw: RawUpgradeProposal) -> Result { if raw.title.is_empty() { - return Err(UpgradeClientError::InvalidUpgradeProposal { - description: "missing title field".to_string(), + return Err(DecodingError::InvalidRawData { + description: "invalid upgrade proposal: missing title field".to_string(), }); } if raw.description.is_empty() { - return Err(UpgradeClientError::InvalidUpgradeProposal { - description: "missing description field".to_string(), + return Err(DecodingError::InvalidRawData { + description: "invalid upgrade proposal: missing description field".to_string(), }); } let plan = if let Some(plan) = raw.plan { plan.try_into()? } else { - return Err(UpgradeClientError::InvalidUpgradeProposal { - description: "missing plan field".to_string(), + return Err(DecodingError::InvalidRawData { + description: "invalid upgrade proposal: missing plan field".to_string(), }); }; - let upgraded_client_state = raw.upgraded_client_state.ok_or_else(|| { - UpgradeClientError::InvalidUpgradeProposal { - description: "missing upgraded client state".to_string(), - } - })?; + let upgraded_client_state = + raw.upgraded_client_state + .ok_or_else(|| DecodingError::InvalidRawData { + description: "invalid upgrade proposal: missing upgraded client state" + .to_string(), + })?; Ok(Self { title: raw.title, diff --git a/ibc-core/ics24-host/cosmos/src/validate_self_client.rs b/ibc-core/ics24-host/cosmos/src/validate_self_client.rs index f6d66994d..d6c84e365 100644 --- a/ibc-core/ics24-host/cosmos/src/validate_self_client.rs +++ b/ibc-core/ics24-host/cosmos/src/validate_self_client.rs @@ -1,11 +1,9 @@ use core::time::Duration; use ibc_client_tendermint::types::ClientState as TmClientState; -use ibc_core_client_types::error::ClientError; -use ibc_core_client_types::{Height, Status}; +use ibc_core_client_types::Height; use ibc_core_commitment_types::specs::ProofSpecs; -use ibc_core_connection_types::error::ConnectionError; -use ibc_core_handler_types::error::ContextError; +use ibc_core_host_types::error::HostError; use ibc_core_host_types::identifiers::ChainId; use ibc_primitives::prelude::*; use tendermint::trust_threshold::TrustThresholdFraction as TendermintTrustThresholdFraction; @@ -19,63 +17,53 @@ pub trait ValidateSelfClientContext { fn validate_self_tendermint_client( &self, client_state_of_host_on_counterparty: TmClientState, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { client_state_of_host_on_counterparty .validate() - .map_err(ClientError::from)?; + .map_err(|e| { + HostError::invalid_state(format!( + "invalid counterparty client state that could not be validated: {e}" + )) + })?; if client_state_of_host_on_counterparty.is_frozen() { - return Err(ClientError::UnexpectedStatus(Status::Frozen).into()); + return Err(HostError::invalid_state("client unexpectedly frozen")); } let self_chain_id = self.chain_id(); + if self_chain_id != &client_state_of_host_on_counterparty.chain_id { - return Err(ContextError::ConnectionError( - ConnectionError::InvalidClientState { - description: format!( - "invalid chain-id. expected: {}, got: {}", - self_chain_id, client_state_of_host_on_counterparty.chain_id - ), - }, - )); + return Err(HostError::invalid_state(format!( + "invalid chain ID: expected {}, actual {}", + self_chain_id, client_state_of_host_on_counterparty.chain_id + ))); } let latest_height = client_state_of_host_on_counterparty.latest_height; let self_revision_number = self_chain_id.revision_number(); + if self_revision_number != latest_height.revision_number() { - return Err(ContextError::ConnectionError( - ConnectionError::InvalidClientState { - description: format!( - "client is not in the same revision as the chain. expected: {}, got: {}", - self_revision_number, - latest_height.revision_number() - ), - }, - )); + return Err(HostError::invalid_state(format!( + "mismatched client revision numbers; expected {}, actual {}", + self_revision_number, + latest_height.revision_number() + ))); } if latest_height >= self.host_current_height() { - return Err(ContextError::ConnectionError( - ConnectionError::InvalidClientState { - description: format!( - "client has latest height {} greater than or equal to chain height {}", - latest_height, - self.host_current_height() - ), - }, - )); + return Err(HostError::invalid_state(format!( + "client latest height {} should be less than chain height {}", + latest_height, + self.host_current_height() + ))); } if self.proof_specs() != &client_state_of_host_on_counterparty.proof_specs { - return Err(ContextError::ConnectionError( - ConnectionError::InvalidClientState { - description: format!( - "client has invalid proof specs. expected: {:?}, got: {:?}", - self.proof_specs(), - client_state_of_host_on_counterparty.proof_specs - ), - }, - )); + return Err(HostError::invalid_state(format!( + "invalid client proof specs; expected {:?}, actual {:?}", + self.proof_specs(), + client_state_of_host_on_counterparty.proof_specs + ))); } let _ = { @@ -85,45 +73,35 @@ pub trait ValidateSelfClientContext { trust_level.numerator(), trust_level.denominator(), ) - .map_err(|_| ConnectionError::InvalidClientState { - description: "invalid trust level".to_string(), - })? + .map_err(HostError::invalid_state)? }; if self.unbonding_period() != client_state_of_host_on_counterparty.unbonding_period { - return Err(ContextError::ConnectionError( - ConnectionError::InvalidClientState { - description: format!( - "invalid unbonding period. expected: {:?}, got: {:?}", - self.unbonding_period(), - client_state_of_host_on_counterparty.unbonding_period, - ), - }, - )); + return Err(HostError::invalid_state(format!( + "invalid unbonding period; expected {:?}, actual {:?}", + self.unbonding_period(), + client_state_of_host_on_counterparty.unbonding_period, + ))); } if client_state_of_host_on_counterparty.unbonding_period < client_state_of_host_on_counterparty.trusting_period { - return Err(ContextError::ConnectionError(ConnectionError::InvalidClientState{ description: format!( - "unbonding period must be greater than trusting period. unbonding period ({:?}) < trusting period ({:?})", + return Err(HostError::invalid_state(format!( + "invalid counterparty client state: unbonding period must be greater than trusting period; unbonding period ({:?}) < trusting period ({:?})", client_state_of_host_on_counterparty.unbonding_period, client_state_of_host_on_counterparty.trusting_period - )})); + ))); } if !client_state_of_host_on_counterparty.upgrade_path.is_empty() && self.upgrade_path() != client_state_of_host_on_counterparty.upgrade_path { - return Err(ContextError::ConnectionError( - ConnectionError::InvalidClientState { - description: format!( - "invalid upgrade path. expected: {:?}, got: {:?}", - self.upgrade_path(), - client_state_of_host_on_counterparty.upgrade_path - ), - }, - )); + return Err(HostError::invalid_state(format!( + "invalid upgrade path; expected {:?}, actual {:?}", + self.upgrade_path(), + client_state_of_host_on_counterparty.upgrade_path + ))); } Ok(()) diff --git a/ibc-core/ics24-host/src/context.rs b/ibc-core/ics24-host/src/context.rs index 44451c4f5..a9a84ab53 100644 --- a/ibc-core/ics24-host/src/context.rs +++ b/ibc-core/ics24-host/src/context.rs @@ -8,8 +8,8 @@ use ibc_core_client_types::Height; use ibc_core_commitment_types::commitment::CommitmentPrefix; use ibc_core_connection_types::version::{pick_version, Version as ConnectionVersion}; use ibc_core_connection_types::ConnectionEnd; -use ibc_core_handler_types::error::ContextError; use ibc_core_handler_types::events::IbcEvent; +use ibc_core_host_types::error::HostError; use ibc_core_host_types::identifiers::{ConnectionId, Sequence}; use ibc_core_host_types::path::{ AckPath, ChannelEndPath, ClientConnectionPath, CommitmentPath, ConnectionPath, ReceiptPath, @@ -34,24 +34,21 @@ pub trait ValidationContext { fn get_client_validation_context(&self) -> &Self::V; /// Returns the current height of the local chain. - fn host_height(&self) -> Result; + fn host_height(&self) -> Result; /// Returns the current timestamp of the local chain. - fn host_timestamp(&self) -> Result; + fn host_timestamp(&self) -> Result; /// Returns the `ConsensusState` of the host (local) chain at a specific height. - fn host_consensus_state( - &self, - height: &Height, - ) -> Result; + fn host_consensus_state(&self, height: &Height) -> Result; /// Returns a natural number, counting how many clients have been created /// thus far. The value of this counter should increase only via method /// `ExecutionContext::increase_client_counter`. - fn client_counter(&self) -> Result; + fn client_counter(&self) -> Result; /// Returns the ConnectionEnd for the given identifier `conn_id`. - fn connection_end(&self, conn_id: &ConnectionId) -> Result; + fn connection_end(&self, conn_id: &ConnectionId) -> Result; /// Validates the `ClientState` of the host chain stored on the counterparty /// chain against the host's internal state. @@ -65,13 +62,13 @@ pub trait ValidationContext { fn validate_self_client( &self, client_state_of_host_on_counterparty: Self::HostClientState, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Returns the prefix that the local chain uses in the KV store. fn commitment_prefix(&self) -> CommitmentPrefix; /// Returns a counter on how many connections have been created thus far. - fn connection_counter(&self) -> Result; + fn connection_counter(&self) -> Result; /// Function required by ICS-03. Returns the list of all possible versions that the connection /// handshake protocol supports. @@ -84,33 +81,31 @@ pub trait ValidationContext { fn pick_version( &self, counterparty_candidate_versions: &[ConnectionVersion], - ) -> Result { - let version = pick_version( + ) -> Result { + pick_version( &self.get_compatible_versions(), counterparty_candidate_versions, - )?; - Ok(version) + ) + .map_err(HostError::missing_state) } /// Returns the `ChannelEnd` for the given `port_id` and `chan_id`. - fn channel_end(&self, channel_end_path: &ChannelEndPath) -> Result; + fn channel_end(&self, channel_end_path: &ChannelEndPath) -> Result; /// Returns the sequence number for the next packet to be sent for the given store path - fn get_next_sequence_send(&self, seq_send_path: &SeqSendPath) - -> Result; + fn get_next_sequence_send(&self, seq_send_path: &SeqSendPath) -> Result; /// Returns the sequence number for the next packet to be received for the given store path - fn get_next_sequence_recv(&self, seq_recv_path: &SeqRecvPath) - -> Result; + fn get_next_sequence_recv(&self, seq_recv_path: &SeqRecvPath) -> Result; /// Returns the sequence number for the next packet to be acknowledged for the given store path - fn get_next_sequence_ack(&self, seq_ack_path: &SeqAckPath) -> Result; + fn get_next_sequence_ack(&self, seq_ack_path: &SeqAckPath) -> Result; /// Returns the packet commitment for the given store path fn get_packet_commitment( &self, commitment_path: &CommitmentPath, - ) -> Result; + ) -> Result; /// Returns the packet receipt for the given store path. This receipt is /// used to acknowledge the successful processing of a received packet, and @@ -120,18 +115,18 @@ pub trait ValidationContext { /// indicating the packet has already been processed. If the receipt is /// absent, return `Receipt::None`, indicating the packet has not been /// received. - fn get_packet_receipt(&self, receipt_path: &ReceiptPath) -> Result; + fn get_packet_receipt(&self, receipt_path: &ReceiptPath) -> Result; /// Returns the packet acknowledgement for the given store path fn get_packet_acknowledgement( &self, ack_path: &AckPath, - ) -> Result; + ) -> 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 /// `ExecutionContext::increase_channel_counter`. - fn channel_counter(&self) -> Result; + fn channel_counter(&self) -> Result; /// Returns the maximum expected time per block fn max_expected_time_per_block(&self) -> Duration; @@ -144,7 +139,7 @@ pub trait ValidationContext { /// Validates the `signer` field of IBC messages, which represents the address /// of the user/relayer that signed the given message. - fn validate_message_signer(&self, signer: &Signer) -> Result<(), ContextError>; + fn validate_message_signer(&self, signer: &Signer) -> Result<(), HostError>; } /// Context to be implemented by the host that provides all "write-only" methods. @@ -158,93 +153,93 @@ pub trait ExecutionContext: ValidationContext { /// Called upon client creation. /// Increases the counter, that keeps track of how many clients have been created. - fn increase_client_counter(&mut self) -> Result<(), ContextError>; + fn increase_client_counter(&mut self) -> Result<(), HostError>; /// Stores the given connection_end at path fn store_connection( &mut self, connection_path: &ConnectionPath, connection_end: ConnectionEnd, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Stores the given connection_id at a path associated with the client_id. fn store_connection_to_client( &mut self, client_connection_path: &ClientConnectionPath, conn_id: ConnectionId, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Called upon connection identifier creation (Init or Try process). /// Increases the counter which keeps track of how many connections have been created. - fn increase_connection_counter(&mut self) -> Result<(), ContextError>; + fn increase_connection_counter(&mut self) -> Result<(), HostError>; /// Stores the given packet commitment at the given store path fn store_packet_commitment( &mut self, commitment_path: &CommitmentPath, commitment: PacketCommitment, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Deletes the packet commitment at the given store path fn delete_packet_commitment( &mut self, commitment_path: &CommitmentPath, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Stores the given packet receipt at the given store path fn store_packet_receipt( &mut self, receipt_path: &ReceiptPath, receipt: Receipt, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Stores the given packet acknowledgement at the given store path fn store_packet_acknowledgement( &mut self, ack_path: &AckPath, ack_commitment: AcknowledgementCommitment, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Deletes the packet acknowledgement at the given store path - fn delete_packet_acknowledgement(&mut self, ack_path: &AckPath) -> Result<(), ContextError>; + fn delete_packet_acknowledgement(&mut self, ack_path: &AckPath) -> Result<(), HostError>; /// Stores the given channel_end at a path associated with the port_id and channel_id. fn store_channel( &mut self, channel_end_path: &ChannelEndPath, channel_end: ChannelEnd, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Stores the given `nextSequenceSend` number at the given store path fn store_next_sequence_send( &mut self, seq_send_path: &SeqSendPath, seq: Sequence, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Stores the given `nextSequenceRecv` number at the given store path fn store_next_sequence_recv( &mut self, seq_recv_path: &SeqRecvPath, seq: Sequence, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Stores the given `nextSequenceAck` number at the given store path fn store_next_sequence_ack( &mut self, seq_ack_path: &SeqAckPath, seq: Sequence, - ) -> Result<(), ContextError>; + ) -> Result<(), HostError>; /// Called upon channel identifier creation (Init or Try message processing). /// Increases the counter, that keeps track of how many channels have been created. - fn increase_channel_counter(&mut self) -> Result<(), ContextError>; + fn increase_channel_counter(&mut self) -> Result<(), HostError>; /// Emit the given IBC event - fn emit_ibc_event(&mut self, event: IbcEvent) -> Result<(), ContextError>; + fn emit_ibc_event(&mut self, event: IbcEvent) -> Result<(), HostError>; /// Log the given message. - fn log_message(&mut self, message: String) -> Result<(), ContextError>; + fn log_message(&mut self, message: String) -> Result<(), HostError>; } /// Convenient type alias for `ClientStateRef`, providing access to client diff --git a/ibc-core/ics24-host/types/src/error.rs b/ibc-core/ics24-host/types/src/error.rs index b3738e952..7fd47c2cc 100644 --- a/ibc-core/ics24-host/types/src/error.rs +++ b/ibc-core/ics24-host/types/src/error.rs @@ -9,6 +9,47 @@ use ibc_primitives::prelude::*; use ibc_primitives::proto::Error as ProtoError; use prost::DecodeError as ProstError; +/// Errors that originate from host implementations. +#[derive(Debug, Display)] +pub enum HostError { + /// invalid state: `{description}` + InvalidState { description: String }, + /// missing state: `{description}` + MissingState { description: String }, + /// failed to update store: `{description}` + FailedToStore { description: String }, + /// failed to retrieve from store: `{description}` + FailedToRetrieve { description: String }, + /// other error: `{description}` + Other { description: String }, +} + +impl HostError { + pub fn invalid_state(description: T) -> Self { + Self::InvalidState { + description: description.to_string(), + } + } + + pub fn missing_state(description: T) -> Self { + Self::MissingState { + description: description.to_string(), + } + } + + pub fn failed_to_retrieve(description: T) -> Self { + Self::FailedToRetrieve { + description: description.to_string(), + } + } + + pub fn failed_to_store(description: T) -> Self { + Self::FailedToStore { + description: description.to_string(), + } + } +} + /// Errors that arise when parsing identifiers. #[cfg_attr(feature = "serde", derive(serde::Serialize))] #[derive(Debug, Display)] @@ -25,7 +66,8 @@ pub enum IdentifierError { OverflowedRevisionNumber, } -/// Errors that result in decoding failures +/// Errors that occur during the process of decoding, deserializing, +/// and/or converting raw types into domain types. #[derive(Debug, Display)] pub enum DecodingError { /// identifier error: `{0}` @@ -103,3 +145,6 @@ impl std::error::Error for IdentifierError {} #[cfg(feature = "std")] impl std::error::Error for DecodingError {} + +#[cfg(feature = "std")] +impl std::error::Error for HostError {} diff --git a/ibc-core/ics25-handler/src/entrypoint.rs b/ibc-core/ics25-handler/src/entrypoint.rs index 575e5e096..f3aa2323a 100644 --- a/ibc-core/ics25-handler/src/entrypoint.rs +++ b/ibc-core/ics25-handler/src/entrypoint.rs @@ -17,11 +17,13 @@ use ibc_core_connection::handler::{ conn_open_ack, conn_open_confirm, conn_open_init, conn_open_try, }; use ibc_core_connection::types::msgs::ConnectionMsg; -use ibc_core_handler_types::error::ContextError; +use ibc_core_handler_types::error::HandlerError; use ibc_core_handler_types::msgs::MsgEnvelope; +use ibc_core_host::types::error::HostError; use ibc_core_host::{ExecutionContext, ValidationContext}; use ibc_core_router::router::Router; use ibc_core_router::types::error::RouterError; +use ibc_primitives::prelude::*; use ibc_primitives::proto::Any; /// Entrypoint which performs both validation and message execution @@ -29,7 +31,7 @@ pub fn dispatch( ctx: &mut Ctx, router: &mut impl Router, msg: MsgEnvelope, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where Ctx: ExecutionContext, <::ClientStateRef as TryFrom>::Error: Into, @@ -48,7 +50,7 @@ where /// That is, the state transition of message `i` must be applied before /// message `i+1` is validated. This is equivalent to calling /// `dispatch()` on each successively. -pub fn validate(ctx: &Ctx, router: &impl Router, msg: MsgEnvelope) -> Result<(), ContextError> +pub fn validate(ctx: &Ctx, router: &impl Router, msg: MsgEnvelope) -> Result<(), HandlerError> where Ctx: ValidationContext, <::ClientStateRef as TryFrom>::Error: Into, @@ -80,7 +82,10 @@ where let port_id = channel_msg_to_port_id(&msg); let module_id = router .lookup_module(port_id) - .ok_or(RouterError::UnknownPort(port_id.clone()))?; + .ok_or(HostError::missing_state(format!( + "failed to look up port {}", + port_id.clone() + )))?; let module = router .get_route(&module_id) .ok_or(RouterError::MissingModule)?; @@ -98,7 +103,10 @@ where let port_id = packet_msg_to_port_id(&msg); let module_id = router .lookup_module(port_id) - .ok_or(RouterError::UnknownPort(port_id.clone()))?; + .ok_or(HostError::missing_state(format!( + "failed to look up port {}", + port_id.clone() + )))?; let module = router .get_route(&module_id) .ok_or(RouterError::MissingModule)?; @@ -122,7 +130,7 @@ pub fn execute( ctx: &mut Ctx, router: &mut impl Router, msg: MsgEnvelope, -) -> Result<(), ContextError> +) -> Result<(), HandlerError> where Ctx: ExecutionContext, <::ClientStateMut as TryFrom>::Error: Into, @@ -153,7 +161,10 @@ where let port_id = channel_msg_to_port_id(&msg); let module_id = router .lookup_module(port_id) - .ok_or(RouterError::UnknownPort(port_id.clone()))?; + .ok_or(HostError::missing_state(format!( + "failed to look up port {}", + port_id.clone() + )))?; let module = router .get_route_mut(&module_id) .ok_or(RouterError::MissingModule)?; @@ -171,7 +182,10 @@ where let port_id = packet_msg_to_port_id(&msg); let module_id = router .lookup_module(port_id) - .ok_or(RouterError::UnknownPort(port_id.clone()))?; + .ok_or(HostError::missing_state(format!( + "failed to look up port {}", + port_id.clone() + )))?; let module = router .get_route_mut(&module_id) .ok_or(RouterError::MissingModule)?; diff --git a/ibc-core/ics25-handler/types/src/error.rs b/ibc-core/ics25-handler/types/src/error.rs index 84bc0b939..bc93d11f4 100644 --- a/ibc-core/ics25-handler/types/src/error.rs +++ b/ibc-core/ics25-handler/types/src/error.rs @@ -1,49 +1,53 @@ -//! Defines the context error type +//! Defines the handler error type use derive_more::From; use displaydoc::Display; use ibc_core_channel_types::error::{ChannelError, PacketError}; use ibc_core_client_types::error::ClientError; use ibc_core_connection_types::error::ConnectionError; +use ibc_core_host_types::error::HostError; use ibc_core_router_types::error::RouterError; use ibc_primitives::prelude::*; -/// Top-level error +/// Top-level type that surfaces errors from the core ibc-rs crates. #[derive(Debug, Display, From)] -pub enum ContextError { +pub enum HandlerError { /// ICS02 Client error: {0} - ClientError(ClientError), + Client(ClientError), /// ICS03 Connection error: {0} - ConnectionError(ConnectionError), + Connection(ConnectionError), /// ICS04 Channel error: {0} - ChannelError(ChannelError), + Channel(ChannelError), /// ICS04 Packet error: {0} - PacketError(PacketError), + Packet(PacketError), /// ICS26 Routing error: {0} - RouterError(RouterError), + Router(RouterError), + /// ICS25 Host error: {0} + Host(HostError), } // TODO(seanchen1991): Figure out how to remove this -impl From for ClientError { - fn from(context_error: ContextError) -> Self { - match context_error { - ContextError::ClientError(e) => e, +impl From for ClientError { + fn from(e: HandlerError) -> Self { + match e { + HandlerError::Client(e) => e, _ => ClientError::Other { - description: context_error.to_string(), + description: e.to_string(), }, } } } #[cfg(feature = "std")] -impl std::error::Error for ContextError { +impl std::error::Error for HandlerError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { - Self::ClientError(e) => Some(e), - Self::ConnectionError(e) => Some(e), - Self::ChannelError(e) => Some(e), - Self::PacketError(e) => Some(e), - Self::RouterError(e) => Some(e), + Self::Client(e) => Some(e), + Self::Connection(e) => Some(e), + Self::Channel(e) => Some(e), + Self::Packet(e) => Some(e), + Self::Router(e) => Some(e), + Self::Host(e) => Some(e), } } } diff --git a/ibc-core/ics26-routing/types/src/error.rs b/ibc-core/ics26-routing/types/src/error.rs index 97650e147..b49f70993 100644 --- a/ibc-core/ics26-routing/types/src/error.rs +++ b/ibc-core/ics26-routing/types/src/error.rs @@ -1,5 +1,4 @@ use displaydoc::Display; -use ibc_core_host_types::identifiers::PortId; use ibc_primitives::prelude::*; /// Error type for the router module. @@ -7,10 +6,6 @@ use ibc_primitives::prelude::*; pub enum RouterError { /// missing module MissingModule, - - // TODO(seanchen1991): This variant needs to be moved to HostError - /// unknown port `{0}` - UnknownPort(PortId), } #[cfg(feature = "std")] diff --git a/ibc-query/src/core/context.rs b/ibc-query/src/core/context.rs index 693dafec9..7f29306c6 100644 --- a/ibc-query/src/core/context.rs +++ b/ibc-query/src/core/context.rs @@ -4,7 +4,7 @@ use ibc::core::channel::types::channel::IdentifiedChannelEnd; use ibc::core::channel::types::packet::PacketState; use ibc::core::client::types::Height; use ibc::core::connection::types::IdentifiedConnectionEnd; -use ibc::core::handler::types::error::ContextError; +use ibc::core::host::types::error::HostError; use ibc::core::host::types::identifiers::{ClientId, ConnectionId, Sequence}; use ibc::core::host::types::path::{ChannelEndPath, Path}; use ibc::core::host::{ClientStateRef, ConsensusStateRef, ValidationContext}; @@ -22,32 +22,29 @@ pub trait QueryContext: ProvableContext + ValidationContext { // Client queries /// Returns the list of all clients. - fn client_states(&self) -> Result)>, ContextError>; + fn client_states(&self) -> Result)>, HostError>; /// Returns the list of all consensus states for the given client. fn consensus_states( &self, client_id: &ClientId, - ) -> Result)>, ContextError>; + ) -> Result)>, HostError>; /// Returns the list of all heights at which consensus states for the given client are. - fn consensus_state_heights(&self, client_id: &ClientId) -> Result, ContextError>; + fn consensus_state_heights(&self, client_id: &ClientId) -> Result, HostError>; // Connection queries /// Returns the list of all connection ends. - fn connection_ends(&self) -> Result, ContextError>; + fn connection_ends(&self) -> Result, HostError>; /// Returns the list of all connection ids of the given client. - fn client_connection_ends( - &self, - client_id: &ClientId, - ) -> Result, ContextError>; + fn client_connection_ends(&self, client_id: &ClientId) -> Result, HostError>; // Channel queries /// Returns the list of all channel ends. - fn channel_ends(&self) -> Result, ContextError>; + fn channel_ends(&self) -> Result, HostError>; // Packet queries @@ -55,7 +52,7 @@ pub trait QueryContext: ProvableContext + ValidationContext { fn packet_commitments( &self, channel_end_path: &ChannelEndPath, - ) -> Result, ContextError>; + ) -> Result, HostError>; /// Filters the list of packet sequences for the given channel end that are acknowledged. /// Returns all the packet acknowledgements if `sequences` is empty. @@ -63,14 +60,14 @@ pub trait QueryContext: ProvableContext + ValidationContext { &self, channel_end_path: &ChannelEndPath, sequences: impl ExactSizeIterator, - ) -> Result, ContextError>; + ) -> Result, HostError>; /// Filters the packet sequences for the given channel end that are not received. fn unreceived_packets( &self, channel_end_path: &ChannelEndPath, sequences: impl ExactSizeIterator, - ) -> Result, ContextError>; + ) -> Result, HostError>; /// Filters the list of packet sequences for the given channel end whose acknowledgement is not received. /// Returns all the unreceived acknowledgements if `sequences` is empty. @@ -78,5 +75,5 @@ pub trait QueryContext: ProvableContext + ValidationContext { &self, channel_end_path: &ChannelEndPath, sequences: impl ExactSizeIterator, - ) -> Result, ContextError>; + ) -> Result, HostError>; } diff --git a/ibc-query/src/error.rs b/ibc-query/src/error.rs index a16bda8e7..2d18a8547 100644 --- a/ibc-query/src/error.rs +++ b/ibc-query/src/error.rs @@ -4,8 +4,8 @@ use displaydoc::Display; use ibc::core::channel::types::error::{ChannelError, PacketError}; use ibc::core::client::types::error::ClientError; use ibc::core::connection::types::error::ConnectionError; -use ibc::core::handler::types::error::ContextError; -use ibc::core::host::types::error::{DecodingError, IdentifierError}; +use ibc::core::handler::types::error::HandlerError; +use ibc::core::host::types::error::{DecodingError, HostError, IdentifierError}; use tonic::Status; /// The main error type of the ibc-query crate. This type mainly @@ -13,10 +13,10 @@ use tonic::Status; /// ibc-query's codepaths. #[derive(Debug, Display)] pub enum QueryError { - /// context error: `{0}` - ContextError(ContextError), + /// handler error: `{0}` + Handler(HandlerError), /// decoding error: `{0}` - DecodingError(DecodingError), + Decoding(DecodingError), /// missing proof: `{0}` MissingProof(String), /// missing field: `{0}` @@ -36,52 +36,58 @@ impl QueryError { impl From for Status { fn from(e: QueryError) -> Self { match e { - QueryError::DecodingError(de) => Self::internal(de.to_string()), - QueryError::ContextError(ctx_err) => Self::internal(ctx_err.to_string()), + QueryError::Handler(ctx_err) => Self::internal(ctx_err.to_string()), + QueryError::Decoding(de) => Self::internal(de.to_string()), QueryError::MissingProof(description) => Self::not_found(description), QueryError::MissingField(description) => Self::invalid_argument(description), } } } -impl From for QueryError { - fn from(e: ContextError) -> Self { - Self::ContextError(e) +impl From for QueryError { + fn from(e: HandlerError) -> Self { + Self::Handler(e) } } impl From for QueryError { fn from(e: ClientError) -> Self { - Self::ContextError(ContextError::ClientError(e)) + Self::Handler(HandlerError::Client(e)) } } impl From for QueryError { fn from(e: ConnectionError) -> Self { - Self::ContextError(ContextError::ConnectionError(e)) + Self::Handler(HandlerError::Connection(e)) } } impl From for QueryError { fn from(e: ChannelError) -> Self { - Self::ContextError(ContextError::ChannelError(e)) + Self::Handler(HandlerError::Channel(e)) } } impl From for QueryError { fn from(e: PacketError) -> Self { - Self::ContextError(ContextError::PacketError(e)) + Self::Handler(HandlerError::Packet(e)) } } impl From for QueryError { fn from(e: DecodingError) -> Self { - Self::DecodingError(e) + Self::Decoding(e) } } impl From for QueryError { fn from(e: IdentifierError) -> Self { - Self::DecodingError(DecodingError::Identifier(e)) + Self::Decoding(DecodingError::Identifier(e)) + } +} + +impl From for QueryError { + fn from(e: HostError) -> Self { + Self::Handler(HandlerError::Host(e)) } } diff --git a/ibc-testkit/src/context.rs b/ibc-testkit/src/context.rs index 92255ba3d..92986d14f 100644 --- a/ibc-testkit/src/context.rs +++ b/ibc-testkit/src/context.rs @@ -10,7 +10,7 @@ use ibc::core::client::context::{ClientExecutionContext, ClientValidationContext use ibc::core::client::types::Height; use ibc::core::connection::types::ConnectionEnd; use ibc::core::entrypoint::{dispatch, execute, validate}; -use ibc::core::handler::types::error::ContextError; +use ibc::core::handler::types::error::HandlerError; use ibc::core::handler::types::events::IbcEvent; use ibc::core::handler::types::msgs::MsgEnvelope; use ibc::core::host::types::identifiers::{ChannelId, ClientId, ConnectionId, PortId, Sequence}; @@ -462,24 +462,24 @@ where } /// Calls [`validate`] function on [`MsgEnvelope`] using the context's IBC store and router. - pub fn validate(&mut self, msg: MsgEnvelope) -> Result<(), ContextError> { + pub fn validate(&mut self, msg: MsgEnvelope) -> Result<(), HandlerError> { validate(&self.ibc_store, &self.ibc_router, msg) } /// Calls [`execute`] function on [`MsgEnvelope`] using the context's IBC store and router. - pub fn execute(&mut self, msg: MsgEnvelope) -> Result<(), ContextError> { + pub fn execute(&mut self, msg: MsgEnvelope) -> Result<(), HandlerError> { execute(&mut self.ibc_store, &mut self.ibc_router, msg) } /// Calls [`dispatch`] function on [`MsgEnvelope`] using the context's IBC store and router. - pub fn dispatch(&mut self, msg: MsgEnvelope) -> Result<(), ContextError> { + pub fn dispatch(&mut self, msg: MsgEnvelope) -> Result<(), HandlerError> { dispatch(&mut self.ibc_store, &mut self.ibc_router, msg) } /// A datagram passes from the relayer to the IBC module (on host chain). /// Alternative method to `Ics18Context::send` that does not exercise any serialization. /// Used in testing the Ics18 algorithms, hence this may return an Ics18Error. - pub fn deliver(&mut self, msg: MsgEnvelope) -> Result<(), ContextError> { + pub fn deliver(&mut self, msg: MsgEnvelope) -> Result<(), HandlerError> { self.dispatch(msg)?; // Create a new block. diff --git a/ibc-testkit/src/fixtures/mod.rs b/ibc-testkit/src/fixtures/mod.rs index f6b51ef46..c5e14f29a 100644 --- a/ibc-testkit/src/fixtures/mod.rs +++ b/ibc-testkit/src/fixtures/mod.rs @@ -3,13 +3,13 @@ pub mod clients; pub mod core; use alloc::fmt::Debug; -use ibc::core::handler::types::error::ContextError; +use ibc::core::handler::types::error::HandlerError; use ibc::core::primitives::prelude::*; use crate::testapp::ibc::core::types::DefaultIbcStore; pub enum Expect { Success, - Failure(Option), + Failure(Option), } #[derive(Debug)] @@ -23,7 +23,7 @@ impl Fixture { &self, expect: &Expect, process: &str, - res: &Result<(), ContextError>, + res: &Result<(), HandlerError>, ) -> String { let base_error = match expect { Expect::Success => "step failed!", diff --git a/ibc-testkit/src/testapp/ibc/applications/nft_transfer/context.rs b/ibc-testkit/src/testapp/ibc/applications/nft_transfer/context.rs index a526dcf45..84838d846 100644 --- a/ibc-testkit/src/testapp/ibc/applications/nft_transfer/context.rs +++ b/ibc-testkit/src/testapp/ibc/applications/nft_transfer/context.rs @@ -1,10 +1,10 @@ use ibc::apps::nft_transfer::context::{ NftClassContext, NftContext, NftTransferExecutionContext, NftTransferValidationContext, }; -use ibc::apps::nft_transfer::types::error::NftTransferError; use ibc::apps::nft_transfer::types::{ ClassData, ClassId, ClassUri, Memo, PrefixedClassId, TokenData, TokenId, TokenUri, }; +use ibc::core::host::types::error::HostError; use ibc::core::host::types::identifiers::{ChannelId, PortId}; use ibc::core::primitives::prelude::*; use ibc::core::primitives::Signer; @@ -48,15 +48,15 @@ impl NftTransferValidationContext for DummyNftTransferModule { type Nft = DummyNft; type NftClass = DummyNftClass; - fn get_port(&self) -> Result { + fn get_port(&self) -> Result { Ok(PortId::transfer()) } - fn can_send_nft(&self) -> Result<(), NftTransferError> { + fn can_send_nft(&self) -> Result<(), HostError> { Ok(()) } - fn can_receive_nft(&self) -> Result<(), NftTransferError> { + fn can_receive_nft(&self) -> Result<(), HostError> { Ok(()) } @@ -65,7 +65,7 @@ impl NftTransferValidationContext for DummyNftTransferModule { _class_id: &PrefixedClassId, _class_uri: Option<&ClassUri>, _class_data: Option<&ClassData>, - ) -> Result<(), NftTransferError> { + ) -> Result<(), HostError> { Ok(()) } @@ -77,7 +77,7 @@ impl NftTransferValidationContext for DummyNftTransferModule { _class_id: &PrefixedClassId, _token_id: &TokenId, _memo: &Memo, - ) -> Result<(), NftTransferError> { + ) -> Result<(), HostError> { Ok(()) } @@ -88,7 +88,7 @@ impl NftTransferValidationContext for DummyNftTransferModule { _channel_id: &ChannelId, _class_id: &PrefixedClassId, _token_id: &TokenId, - ) -> Result<(), NftTransferError> { + ) -> Result<(), HostError> { Ok(()) } @@ -99,7 +99,7 @@ impl NftTransferValidationContext for DummyNftTransferModule { _token_id: &TokenId, _token_uri: Option<&TokenUri>, _token_data: Option<&TokenData>, - ) -> Result<(), NftTransferError> { + ) -> Result<(), HostError> { Ok(()) } @@ -109,7 +109,7 @@ impl NftTransferValidationContext for DummyNftTransferModule { _class_id: &PrefixedClassId, _token_id: &TokenId, _memo: &Memo, - ) -> Result<(), NftTransferError> { + ) -> Result<(), HostError> { Ok(()) } @@ -117,14 +117,11 @@ impl NftTransferValidationContext for DummyNftTransferModule { &self, _class_id: &PrefixedClassId, _token_id: &TokenId, - ) -> Result { + ) -> Result { Ok(DummyNft::default()) } - fn get_nft_class( - &self, - _class_id: &PrefixedClassId, - ) -> Result { + fn get_nft_class(&self, _class_id: &PrefixedClassId) -> Result { Ok(DummyNftClass::default()) } } @@ -135,7 +132,7 @@ impl NftTransferExecutionContext for DummyNftTransferModule { _class_id: &PrefixedClassId, _class_uri: Option<&ClassUri>, _class_data: Option<&ClassData>, - ) -> Result<(), NftTransferError> { + ) -> Result<(), HostError> { Ok(()) } @@ -147,7 +144,7 @@ impl NftTransferExecutionContext for DummyNftTransferModule { _class_id: &PrefixedClassId, _token_id: &TokenId, _memo: &Memo, - ) -> Result<(), NftTransferError> { + ) -> Result<(), HostError> { Ok(()) } @@ -158,7 +155,7 @@ impl NftTransferExecutionContext for DummyNftTransferModule { _channel_id: &ChannelId, _class_id: &PrefixedClassId, _token_id: &TokenId, - ) -> Result<(), NftTransferError> { + ) -> Result<(), HostError> { Ok(()) } @@ -169,7 +166,7 @@ impl NftTransferExecutionContext for DummyNftTransferModule { _token_id: &TokenId, _token_uri: Option<&TokenUri>, _token_data: Option<&TokenData>, - ) -> Result<(), NftTransferError> { + ) -> Result<(), HostError> { Ok(()) } @@ -179,7 +176,7 @@ impl NftTransferExecutionContext for DummyNftTransferModule { _class_id: &PrefixedClassId, _token_id: &TokenId, _memo: &Memo, - ) -> Result<(), NftTransferError> { + ) -> Result<(), HostError> { Ok(()) } } diff --git a/ibc-testkit/src/testapp/ibc/applications/transfer/context.rs b/ibc-testkit/src/testapp/ibc/applications/transfer/context.rs index d8876b315..d4a9677ef 100644 --- a/ibc-testkit/src/testapp/ibc/applications/transfer/context.rs +++ b/ibc-testkit/src/testapp/ibc/applications/transfer/context.rs @@ -1,6 +1,6 @@ use ibc::apps::transfer::context::{TokenTransferExecutionContext, TokenTransferValidationContext}; -use ibc::apps::transfer::types::error::TokenTransferError; use ibc::apps::transfer::types::{Memo, PrefixedCoin}; +use ibc::core::host::types::error::HostError; use ibc::core::host::types::identifiers::{ChannelId, PortId}; use ibc::core::primitives::Signer; @@ -9,15 +9,15 @@ use super::types::DummyTransferModule; impl TokenTransferValidationContext for DummyTransferModule { type AccountId = Signer; - fn get_port(&self) -> Result { + fn get_port(&self) -> Result { Ok(PortId::transfer()) } - fn can_send_coins(&self) -> Result<(), TokenTransferError> { + fn can_send_coins(&self) -> Result<(), HostError> { Ok(()) } - fn can_receive_coins(&self) -> Result<(), TokenTransferError> { + fn can_receive_coins(&self) -> Result<(), HostError> { Ok(()) } fn escrow_coins_validate( @@ -27,7 +27,7 @@ impl TokenTransferValidationContext for DummyTransferModule { _channel_id: &ChannelId, _coin: &PrefixedCoin, _memo: &Memo, - ) -> Result<(), TokenTransferError> { + ) -> Result<(), HostError> { Ok(()) } @@ -37,7 +37,7 @@ impl TokenTransferValidationContext for DummyTransferModule { _port_id: &PortId, _channel_id: &ChannelId, _coin: &PrefixedCoin, - ) -> Result<(), TokenTransferError> { + ) -> Result<(), HostError> { Ok(()) } @@ -45,7 +45,7 @@ impl TokenTransferValidationContext for DummyTransferModule { &self, _account: &Self::AccountId, _coin: &PrefixedCoin, - ) -> Result<(), TokenTransferError> { + ) -> Result<(), HostError> { Ok(()) } @@ -54,7 +54,7 @@ impl TokenTransferValidationContext for DummyTransferModule { _account: &Self::AccountId, _coin: &PrefixedCoin, _memo: &Memo, - ) -> Result<(), TokenTransferError> { + ) -> Result<(), HostError> { Ok(()) } } @@ -67,7 +67,7 @@ impl TokenTransferExecutionContext for DummyTransferModule { _channel_id: &ChannelId, _coin: &PrefixedCoin, _memo: &Memo, - ) -> Result<(), TokenTransferError> { + ) -> Result<(), HostError> { Ok(()) } @@ -77,7 +77,7 @@ impl TokenTransferExecutionContext for DummyTransferModule { _port_id: &PortId, _channel_id: &ChannelId, _coin: &PrefixedCoin, - ) -> Result<(), TokenTransferError> { + ) -> Result<(), HostError> { Ok(()) } @@ -85,7 +85,7 @@ impl TokenTransferExecutionContext for DummyTransferModule { &mut self, _account: &Self::AccountId, _coin: &PrefixedCoin, - ) -> Result<(), TokenTransferError> { + ) -> Result<(), HostError> { Ok(()) } @@ -94,7 +94,7 @@ impl TokenTransferExecutionContext for DummyTransferModule { _account: &Self::AccountId, _coin: &PrefixedCoin, _memo: &Memo, - ) -> Result<(), TokenTransferError> { + ) -> Result<(), HostError> { Ok(()) } } diff --git a/ibc-testkit/src/testapp/ibc/clients/mock/client_state.rs b/ibc-testkit/src/testapp/ibc/clients/mock/client_state.rs index dff68ecd9..ef6f4c0f0 100644 --- a/ibc-testkit/src/testapp/ibc/clients/mock/client_state.rs +++ b/ibc-testkit/src/testapp/ibc/clients/mock/client_state.rs @@ -8,8 +8,7 @@ use ibc::core::client::types::{Height, Status}; use ibc::core::commitment_types::commitment::{ CommitmentPrefix, CommitmentProofBytes, CommitmentRoot, }; -use ibc::core::handler::types::error::ContextError; -use ibc::core::host::types::error::DecodingError; +use ibc::core::host::types::error::{DecodingError, HostError}; use ibc::core::host::types::identifiers::{ClientId, ClientType}; use ibc::core::host::types::path::{ClientConsensusStatePath, ClientStatePath, Path, PathBytes}; use ibc::core::primitives::prelude::*; @@ -155,10 +154,10 @@ impl From for Any { pub trait MockClientContext { /// Returns the current timestamp of the local chain. - fn host_timestamp(&self) -> Result; + fn host_timestamp(&self) -> Result; /// Returns the current height of the local chain. - fn host_height(&self) -> Result; + fn host_height(&self) -> Result; } impl ClientStateCommon for MockClientState { diff --git a/ibc-testkit/src/testapp/ibc/core/client_ctx.rs b/ibc-testkit/src/testapp/ibc/core/client_ctx.rs index a2c9d59d7..f2dbe930c 100644 --- a/ibc-testkit/src/testapp/ibc/core/client_ctx.rs +++ b/ibc-testkit/src/testapp/ibc/core/client_ctx.rs @@ -5,9 +5,8 @@ use basecoin_store::types::Height as StoreHeight; use ibc::core::client::context::{ ClientExecutionContext, ClientValidationContext, ExtClientValidationContext, }; -use ibc::core::client::types::error::ClientError; use ibc::core::client::types::Height; -use ibc::core::handler::types::error::ContextError; +use ibc::core::host::types::error::HostError; use ibc::core::host::types::identifiers::{ChannelId, ClientId, PortId}; use ibc::core::host::types::path::{ ClientConsensusStatePath, ClientStatePath, ClientUpdateHeightPath, ClientUpdateTimePath, Path, @@ -37,11 +36,11 @@ impl MockClientContext for MockIbcStore where S: ProvableStore + Debug, { - fn host_timestamp(&self) -> Result { + fn host_timestamp(&self) -> Result { ValidationContext::host_timestamp(self) } - fn host_height(&self) -> Result { + fn host_height(&self) -> Result { ValidationContext::host_height(self) } } @@ -50,21 +49,17 @@ impl ExtClientValidationContext for MockIbcStore where S: ProvableStore + Debug, { - fn host_timestamp(&self) -> Result { + fn host_timestamp(&self) -> Result { ValidationContext::host_timestamp(self) } - fn host_height(&self) -> Result { + fn host_height(&self) -> Result { ValidationContext::host_height(self) } /// Returns the list of heights at which the consensus state of the given client was updated. - fn consensus_state_heights(&self, client_id: &ClientId) -> Result, ContextError> { - let path = format!("clients/{}/consensusStates", client_id) - .try_into() - .map_err(|_| ClientError::Other { - description: "Invalid consensus state path".into(), - })?; + fn consensus_state_heights(&self, client_id: &ClientId) -> Result, HostError> { + let path = format!("clients/{}/consensusStates", client_id).into(); self.consensus_state_store .get_keys(&path) @@ -77,10 +72,11 @@ where } }) .map(|consensus_path| { - Ok(Height::new( + Height::new( consensus_path.revision_number, consensus_path.revision_height, - )?) + ) + .map_err(HostError::invalid_state) }) .collect::, _>>() } @@ -89,7 +85,7 @@ where &self, client_id: &ClientId, height: &Height, - ) -> Result, ContextError> { + ) -> Result, HostError> { let path = format!("clients/{client_id}/consensusStates").into(); let keys = self.store.get_keys(&path); @@ -108,12 +104,16 @@ where .map(|path| { self.consensus_state_store .get(StoreHeight::Pending, &path) - .ok_or_else(|| ClientError::MissingConsensusState { - client_id: client_id.clone(), - height: *height, + .ok_or_else(|| { + HostError::failed_to_retrieve(format!( + "missing consensus state for client {} at height {}", + client_id.clone(), + *height + )) }) }) - .transpose()?; + .transpose() + .map_err(HostError::missing_state)?; Ok(consensus_state) } @@ -122,7 +122,7 @@ where &self, client_id: &ClientId, height: &Height, - ) -> Result, ContextError> { + ) -> Result, HostError> { let path = format!("clients/{client_id}/consensusStates").into(); let keys = self.store.get_keys(&path); @@ -141,12 +141,16 @@ where .map(|path| { self.consensus_state_store .get(StoreHeight::Pending, &path) - .ok_or_else(|| ClientError::MissingConsensusState { - client_id: client_id.clone(), - height: *height, + .ok_or_else(|| { + HostError::failed_to_retrieve(format!( + "missing consensus state for client {} at height {}", + client_id.clone(), + *height + )) }) }) - .transpose()?; + .transpose() + .map_err(HostError::missing_state)?; Ok(consensus_state) } @@ -159,29 +163,32 @@ where type ClientStateRef = AnyClientState; type ConsensusStateRef = AnyConsensusState; - fn client_state(&self, client_id: &ClientId) -> Result { - Ok(self - .client_state_store + fn client_state(&self, client_id: &ClientId) -> Result { + self.client_state_store .get(StoreHeight::Pending, &ClientStatePath(client_id.clone())) - .ok_or(ClientError::MissingClientState(client_id.clone()))?) + .ok_or(HostError::failed_to_retrieve(format!( + "missing client state for client {}", + client_id.clone() + ))) } fn consensus_state( &self, client_cons_state_path: &ClientConsensusStatePath, - ) -> Result { + ) -> Result { let height = Height::new( client_cons_state_path.revision_number, client_cons_state_path.revision_height, ) - .map_err(|_| ClientError::InvalidHeight)?; + .map_err(HostError::invalid_state)?; let consensus_state = self .consensus_state_store .get(StoreHeight::Pending, client_cons_state_path) - .ok_or(ClientError::MissingConsensusState { - client_id: client_cons_state_path.client_id.clone(), - height, - })?; + .ok_or(HostError::failed_to_retrieve(format!( + "missing consensus state for client {} at height {}", + client_cons_state_path.client_id.clone(), + height + )))?; Ok(consensus_state) } @@ -192,7 +199,7 @@ where &self, client_id: &ClientId, height: &Height, - ) -> Result<(Timestamp, Height), ContextError> { + ) -> Result<(Timestamp, Height), HostError> { let client_update_time_path = ClientUpdateTimePath::new( client_id.clone(), height.revision_number(), @@ -201,10 +208,11 @@ where let processed_timestamp = self .client_processed_times .get(StoreHeight::Pending, &client_update_time_path) - .ok_or(ClientError::MissingUpdateMetaData { - client_id: client_id.clone(), - height: *height, - })?; + .ok_or(HostError::failed_to_retrieve(format!( + "missing client update metadata for client {} at height {}", + client_id.clone(), + *height, + )))?; let client_update_height_path = ClientUpdateHeightPath::new( client_id.clone(), height.revision_number(), @@ -213,10 +221,11 @@ where let processed_height = self .client_processed_heights .get(StoreHeight::Pending, &client_update_height_path) - .ok_or(ClientError::MissingUpdateMetaData { - client_id: client_id.clone(), - height: *height, - })?; + .ok_or(HostError::failed_to_retrieve(format!( + "missing client update metadata for client {} at height {}", + client_id.clone(), + *height, + )))?; Ok((processed_timestamp, processed_height)) } @@ -233,12 +242,10 @@ where &mut self, client_state_path: ClientStatePath, client_state: Self::ClientStateRef, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { self.client_state_store .set(client_state_path, client_state) - .map_err(|_| ClientError::Other { - description: "Client state store error".to_string(), - })?; + .map_err(|e| HostError::failed_to_store(format!("{e:?}")))?; Ok(()) } @@ -248,30 +255,24 @@ where &mut self, consensus_state_path: ClientConsensusStatePath, consensus_state: Self::ConsensusStateRef, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { self.consensus_state_store .set(consensus_state_path, consensus_state) - .map_err(|_| ClientError::Other { - description: "Consensus state store error".to_string(), - })?; + .map_err(|e| HostError::failed_to_store(format!("{e:?}")))?; Ok(()) } fn delete_consensus_state( &mut self, consensus_state_path: ClientConsensusStatePath, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { self.consensus_state_store.delete(consensus_state_path); Ok(()) } /// Delete the update metadata associated with the client at the specified /// height. - fn delete_update_meta( - &mut self, - client_id: ClientId, - height: Height, - ) -> Result<(), ContextError> { + fn delete_update_meta(&mut self, client_id: ClientId, height: Height) -> Result<(), HostError> { let client_update_time_path = ClientUpdateTimePath::new( client_id.clone(), height.revision_number(), @@ -297,7 +298,7 @@ where height: Height, host_timestamp: Timestamp, host_height: Height, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { let client_update_time_path = ClientUpdateTimePath::new( client_id.clone(), height.revision_number(), @@ -305,9 +306,7 @@ where ); self.client_processed_times .set(client_update_time_path, host_timestamp) - .map_err(|_| ClientError::Other { - description: "store update error".into(), - })?; + .map_err(|e| HostError::failed_to_store(format!("{e:?}")))?; let client_update_height_path = ClientUpdateHeightPath::new( client_id, height.revision_number(), @@ -315,9 +314,7 @@ where ); self.client_processed_heights .set(client_update_height_path, host_height) - .map_err(|_| ClientError::Other { - description: "store update error".into(), - })?; + .map_err(|e| HostError::failed_to_store(format!("{e:?}")))?; Ok(()) } } diff --git a/ibc-testkit/src/testapp/ibc/core/core_ctx.rs b/ibc-testkit/src/testapp/ibc/core/core_ctx.rs index 2791bc174..d97140764 100644 --- a/ibc-testkit/src/testapp/ibc/core/core_ctx.rs +++ b/ibc-testkit/src/testapp/ibc/core/core_ctx.rs @@ -7,17 +7,15 @@ use basecoin_store::context::{ProvableStore, Store}; use basecoin_store::types::Height as StoreHeight; use ibc::core::channel::types::channel::{ChannelEnd, IdentifiedChannelEnd}; use ibc::core::channel::types::commitment::{AcknowledgementCommitment, PacketCommitment}; -use ibc::core::channel::types::error::{ChannelError, PacketError}; use ibc::core::channel::types::packet::{PacketState, Receipt}; use ibc::core::client::context::consensus_state::ConsensusState; use ibc::core::client::types::error::ClientError; -use ibc::core::client::types::{Height, Status}; +use ibc::core::client::types::Height; use ibc::core::commitment_types::commitment::CommitmentPrefix; use ibc::core::commitment_types::merkle::MerkleProof; -use ibc::core::connection::types::error::ConnectionError; use ibc::core::connection::types::{ConnectionEnd, IdentifiedConnectionEnd}; -use ibc::core::handler::types::error::ContextError; use ibc::core::handler::types::events::IbcEvent; +use ibc::core::host::types::error::HostError; use ibc::core::host::types::identifiers::{ClientId, ConnectionId, Sequence}; use ibc::core::host::types::path::{ AckPath, ChannelEndPath, ClientConnectionPath, CommitmentPath, ConnectionPath, @@ -42,45 +40,40 @@ where type HostClientState = AnyClientState; type HostConsensusState = AnyConsensusState; - fn host_height(&self) -> Result { - Ok(Height::new( - *self.revision_number.lock(), - self.store.current_height(), - )?) + fn host_height(&self) -> Result { + Height::new(*self.revision_number.lock(), self.store.current_height()) + .map_err(HostError::invalid_state) } - fn host_timestamp(&self) -> Result { + fn host_timestamp(&self) -> Result { let host_height = self.host_height()?; let host_cons_state = self.host_consensus_state(&host_height)?; Ok(host_cons_state.timestamp()) } - fn client_counter(&self) -> Result { - Ok(self - .client_counter + fn client_counter(&self) -> Result { + self.client_counter .get(StoreHeight::Pending, &NextClientSequencePath) - .ok_or(ClientError::Other { - description: "client counter not found".into(), - })?) + .ok_or(HostError::missing_state("missing client counter")) } - fn host_consensus_state( - &self, - height: &Height, - ) -> Result { + fn host_consensus_state(&self, height: &Height) -> Result { let consensus_states_binding = self.host_consensus_states.lock(); - Ok(consensus_states_binding + + consensus_states_binding .get(&height.revision_height()) .cloned() - .ok_or(ClientError::MissingLocalConsensusState(*height))?) + .ok_or(HostError::missing_state( + ClientError::MissingLocalConsensusState(*height), + )) } fn validate_self_client( &self, client_state_of_host_on_counterparty: Self::HostClientState, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { if client_state_of_host_on_counterparty.is_frozen() { - return Err(ClientError::UnexpectedStatus(Status::Frozen).into()); + return Err(HostError::invalid_state("client unexpectedly frozen")); } let latest_height = self.host_height()?; @@ -91,40 +84,36 @@ where .latest_height() .revision_number() { - return Err(ContextError::ConnectionError( - ConnectionError::InvalidClientState { - description: format!( - "client is not in the same revision as the chain. expected: {}, got: {}", - self_revision_number, - client_state_of_host_on_counterparty - .latest_height() - .revision_number() - ), - }, - )); + return Err(HostError::invalid_state(format!( + "client is not in the same revision as the chain; expected {}, actual {}", + self_revision_number, + client_state_of_host_on_counterparty + .latest_height() + .revision_number() + ))); } let host_current_height = latest_height.increment(); if client_state_of_host_on_counterparty.latest_height() >= host_current_height { - return Err(ContextError::ConnectionError( - ConnectionError::InvalidClientState { - description: format!( - "client has latest height {} greater than or equal to chain height {}", - client_state_of_host_on_counterparty.latest_height(), - host_current_height - ), - }, + return Err(HostError::invalid_state( + format!( + "invalid counterparty client state: client latest height {} should be less than chain height {}", + client_state_of_host_on_counterparty.latest_height(), + host_current_height + ), )); } Ok(()) } - fn connection_end(&self, conn_id: &ConnectionId) -> Result { - Ok(self - .connection_end_store + fn connection_end(&self, conn_id: &ConnectionId) -> Result { + self.connection_end_store .get(StoreHeight::Pending, &ConnectionPath::new(conn_id)) - .ok_or(ConnectionError::MissingConnection(conn_id.clone()))?) + .ok_or(HostError::missing_state(format!( + "missing connection end for connection {}", + conn_id.clone() + ))) } fn commitment_prefix(&self) -> CommitmentPrefix { @@ -133,68 +122,63 @@ where CommitmentPrefix::from(b"mock".to_vec()) } - fn connection_counter(&self) -> Result { - Ok(self - .conn_counter + fn connection_counter(&self) -> Result { + self.conn_counter .get(StoreHeight::Pending, &NextConnectionSequencePath) - .ok_or(ConnectionError::MissingConnectionCounter)?) + .ok_or(HostError::missing_state("missing connection counter")) } - fn channel_end(&self, channel_end_path: &ChannelEndPath) -> Result { - Ok(self - .channel_end_store + fn channel_end(&self, channel_end_path: &ChannelEndPath) -> Result { + self.channel_end_store .get( StoreHeight::Pending, &ChannelEndPath::new(&channel_end_path.0, &channel_end_path.1), ) - .ok_or(ChannelError::NonexistentChannel { - port_id: channel_end_path.0.clone(), - channel_id: channel_end_path.1.clone(), - })?) + .ok_or(HostError::missing_state(format!( + "missing channel {} in port {}", + channel_end_path.1.clone(), + channel_end_path.0.clone() + ))) } - fn get_next_sequence_send( - &self, - seq_send_path: &SeqSendPath, - ) -> Result { - Ok(self - .send_sequence_store + fn get_next_sequence_send(&self, seq_send_path: &SeqSendPath) -> Result { + self.send_sequence_store .get( StoreHeight::Pending, &SeqSendPath::new(&seq_send_path.0, &seq_send_path.1), ) - .ok_or(PacketError::ImplementationSpecific)?) + .ok_or(HostError::failed_to_retrieve( + "failed to retrieve send packet sequence", + )) } - fn get_next_sequence_recv( - &self, - seq_recv_path: &SeqRecvPath, - ) -> Result { - Ok(self - .recv_sequence_store + fn get_next_sequence_recv(&self, seq_recv_path: &SeqRecvPath) -> Result { + self.recv_sequence_store .get( StoreHeight::Pending, &SeqRecvPath::new(&seq_recv_path.0, &seq_recv_path.1), ) - .ok_or(PacketError::ImplementationSpecific)?) + .ok_or(HostError::failed_to_retrieve( + "failed to retrieve recv packet sequence", + )) } - fn get_next_sequence_ack(&self, seq_ack_path: &SeqAckPath) -> Result { - Ok(self - .ack_sequence_store + fn get_next_sequence_ack(&self, seq_ack_path: &SeqAckPath) -> Result { + self.ack_sequence_store .get( StoreHeight::Pending, &SeqAckPath::new(&seq_ack_path.0, &seq_ack_path.1), ) - .ok_or(PacketError::ImplementationSpecific)?) + .ok_or(HostError::failed_to_retrieve( + "failed to retrieve ack packet sequence", + )) } fn get_packet_commitment( &self, commitment_path: &CommitmentPath, - ) -> Result { - Ok(self - .packet_commitment_store + ) -> Result { + self.packet_commitment_store .get( StoreHeight::Pending, &CommitmentPath::new( @@ -203,10 +187,12 @@ where commitment_path.sequence, ), ) - .ok_or(PacketError::ImplementationSpecific)?) + .ok_or(HostError::failed_to_retrieve( + "failed to retrieve packet commitment", + )) } - fn get_packet_receipt(&self, receipt_path: &ReceiptPath) -> Result { + fn get_packet_receipt(&self, receipt_path: &ReceiptPath) -> Result { if self .packet_receipt_store .is_path_set(StoreHeight::Pending, receipt_path) @@ -220,24 +206,27 @@ where fn get_packet_acknowledgement( &self, ack_path: &AckPath, - ) -> Result { - Ok(self - .packet_ack_store + ) -> Result { + self.packet_ack_store .get( StoreHeight::Pending, &AckPath::new(&ack_path.port_id, &ack_path.channel_id, ack_path.sequence), ) - .ok_or(PacketError::MissingPacketAcknowledgment(ack_path.sequence))?) + .ok_or(HostError::failed_to_retrieve(format!( + "failed to retrieve packet acknowledgment {}", + ack_path.sequence + ))) } /// Returns a counter of the number of channel ids that have been created thus far. /// The value of this counter should increase only via the /// `ChannelKeeper::increase_channel_counter` method. - fn channel_counter(&self) -> Result { - Ok(self - .channel_counter + fn channel_counter(&self) -> Result { + self.channel_counter .get(StoreHeight::Pending, &NextChannelSequencePath) - .ok_or(ChannelError::MissingCounter)?) + .ok_or(HostError::failed_to_retrieve( + "failed to retrieve channel counter", + )) } /// Returns the maximum expected time per block @@ -245,7 +234,7 @@ where Duration::from_secs(DEFAULT_BLOCK_TIME_SECS) } - fn validate_message_signer(&self, _signer: &Signer) -> Result<(), ContextError> { + fn validate_message_signer(&self, _signer: &Signer) -> Result<(), HostError> { Ok(()) } @@ -285,7 +274,7 @@ where S: ProvableStore + Debug, { /// Returns the list of all client states. - fn client_states(&self) -> Result)>, ContextError> { + fn client_states(&self) -> Result)>, HostError> { let path = "clients".to_owned().into(); self.client_state_store @@ -302,7 +291,12 @@ where let client_state = self .client_state_store .get(StoreHeight::Pending, &client_state_path) - .ok_or_else(|| ClientError::MissingClientState(client_state_path.0.clone()))?; + .ok_or_else(|| { + HostError::failed_to_retrieve(format!( + "failed to retrieve client state from path {}", + client_state_path.0.clone() + )) + })?; Ok((client_state_path.0, client_state)) }) .collect() @@ -312,12 +306,8 @@ where fn consensus_states( &self, client_id: &ClientId, - ) -> Result)>, ContextError> { - let path = format!("clients/{}/consensusStates", client_id) - .try_into() - .map_err(|_| ClientError::Other { - description: "Invalid consensus state path".into(), - })?; + ) -> Result)>, HostError> { + let path = format!("clients/{}/consensusStates", client_id).into(); self.consensus_state_store .get_keys(&path) @@ -333,28 +323,23 @@ where let height = Height::new( consensus_path.revision_number, consensus_path.revision_height, - )?; + ) + .map_err(HostError::invalid_state)?; let client_state = self .consensus_state_store .get(StoreHeight::Pending, &consensus_path) - .ok_or({ - ClientError::MissingConsensusState { - client_id: consensus_path.client_id, - height, - } - })?; + .ok_or(HostError::failed_to_retrieve(format!( + "missing consensus state for client {} at height {}", + consensus_path.client_id, height, + )))?; Ok((height, client_state)) }) .collect() } /// Returns the list of heights at which the consensus state of the given client was updated. - fn consensus_state_heights(&self, client_id: &ClientId) -> Result, ContextError> { - let path = format!("clients/{}/consensusStates", client_id) - .try_into() - .map_err(|_| ClientError::Other { - description: "Invalid consensus state path".into(), - })?; + fn consensus_state_heights(&self, client_id: &ClientId) -> Result, HostError> { + let path = format!("clients/{}/consensusStates", client_id).into(); self.consensus_state_store .get_keys(&path) @@ -367,16 +352,17 @@ where } }) .map(|consensus_path| { - Ok(Height::new( + Height::new( consensus_path.revision_number, consensus_path.revision_height, - )?) + ) + .map_err(HostError::invalid_state) }) .collect::, _>>() } /// Returns all the IBC connection ends of a chain. - fn connection_ends(&self) -> Result, ContextError> { + fn connection_ends(&self) -> Result, HostError> { let path = "connections".to_owned().into(); self.connection_end_store @@ -393,7 +379,12 @@ where let connection_end = self .connection_end_store .get(StoreHeight::Pending, &connection_path) - .ok_or_else(|| ConnectionError::MissingConnection(connection_path.0.clone()))?; + .ok_or_else(|| { + HostError::failed_to_retrieve(format!( + "missing connection {}", + connection_path.0.clone() + )) + })?; Ok(IdentifiedConnectionEnd { connection_id: connection_path.0, connection_end, @@ -403,10 +394,7 @@ where } /// Returns all the IBC connection ends associated with a client. - fn client_connection_ends( - &self, - client_id: &ClientId, - ) -> Result, ContextError> { + fn client_connection_ends(&self, client_id: &ClientId) -> Result, HostError> { let client_connection_path = ClientConnectionPath::new(client_id.clone()); Ok(self @@ -416,7 +404,7 @@ where } /// Returns all the IBC channel ends of a chain. - fn channel_ends(&self) -> Result, ContextError> { + fn channel_ends(&self) -> Result, HostError> { let path = "channelEnds".to_owned().into(); self.channel_end_store @@ -433,9 +421,12 @@ where let channel_end = self .channel_end_store .get(StoreHeight::Pending, &channel_path) - .ok_or_else(|| ChannelError::NonexistentChannel { - port_id: channel_path.0.clone(), - channel_id: channel_path.1.clone(), + .ok_or_else(|| { + HostError::failed_to_retrieve(format!( + "missing channel {} with port {}", + channel_path.1.clone(), + channel_path.0.clone() + )) })?; Ok(IdentifiedChannelEnd { port_id: channel_path.0, @@ -450,7 +441,7 @@ where fn packet_commitments( &self, channel_end_path: &ChannelEndPath, - ) -> Result, ContextError> { + ) -> Result, HostError> { let path = format!( "commitments/ports/{}/channels/{}/sequences", channel_end_path.0, channel_end_path.1 @@ -492,7 +483,7 @@ where &self, channel_end_path: &ChannelEndPath, sequences: impl ExactSizeIterator, - ) -> Result, ContextError> { + ) -> Result, HostError> { let collected_paths: Vec<_> = if sequences.len() == 0 { // if sequences is empty, return all the acks let ack_path_prefix = format!( @@ -545,7 +536,7 @@ where &self, channel_end_path: &ChannelEndPath, sequences: impl ExactSizeIterator, - ) -> Result, ContextError> { + ) -> Result, HostError> { // QUESTION. Currently only works for unordered channels; ordered channels // don't use receipts. However, ibc-go does it this way. Investigate if // this query only ever makes sense on unordered channels. @@ -570,7 +561,7 @@ where &self, channel_end_path: &ChannelEndPath, sequences: impl ExactSizeIterator, - ) -> Result, ContextError> { + ) -> Result, HostError> { let collected_paths: Vec<_> = if sequences.len() == 0 { // if sequences is empty, return all the acks let commitment_path_prefix = format!( @@ -621,18 +612,16 @@ where /// Called upon client creation. /// Increases the counter, that keeps track of how many clients have been created. - fn increase_client_counter(&mut self) -> Result<(), ContextError> { + fn increase_client_counter(&mut self) -> Result<(), HostError> { let current_sequence = self .client_counter .get(StoreHeight::Pending, &NextClientSequencePath) - .ok_or(ClientError::Other { - description: "client counter not found".into(), - })?; + .ok_or(HostError::failed_to_retrieve("missing client counter"))?; self.client_counter .set(NextClientSequencePath, current_sequence + 1) - .map_err(|e| ClientError::Other { - description: format!("client counter update failed: {e:?}"), + .map_err(|e| { + HostError::failed_to_store(format!("failed to update client counter: {e:?}")) })?; Ok(()) @@ -643,10 +632,12 @@ where &mut self, connection_path: &ConnectionPath, connection_end: ConnectionEnd, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { self.connection_end_store .set(connection_path.clone(), connection_end) - .map_err(|_| ConnectionError::FailedToStoreConnectionEnd)?; + .map_err(|e| { + HostError::failed_to_store(format!("failed to set connection end: {e:?}")) + })?; Ok(()) } @@ -655,7 +646,7 @@ where &mut self, client_connection_path: &ClientConnectionPath, conn_id: ConnectionId, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { let mut conn_ids: Vec = self .connection_ids_store .get(StoreHeight::Pending, client_connection_path) @@ -663,21 +654,25 @@ where conn_ids.push(conn_id); self.connection_ids_store .set(client_connection_path.clone(), conn_ids) - .map_err(|_| ConnectionError::FailedToStoreConnectionIds)?; + .map_err(|e| { + HostError::failed_to_store(format!("failed to store connection IDs: {e:?}")) + })?; Ok(()) } /// Called upon connection identifier creation (Init or Try process). /// Increases the counter, that keeps track of how many connections have been created. - fn increase_connection_counter(&mut self) -> Result<(), ContextError> { + fn increase_connection_counter(&mut self) -> Result<(), HostError> { let current_sequence = self .conn_counter .get(StoreHeight::Pending, &NextConnectionSequencePath) - .ok_or(ConnectionError::MissingConnectionCounter)?; + .ok_or(HostError::failed_to_retrieve("missing connection counter"))?; self.conn_counter .set(NextConnectionSequencePath, current_sequence + 1) - .map_err(|_| ConnectionError::FailedToUpdateConnectionCounter)?; + .map_err(|e| { + HostError::failed_to_store(format!("failed to update connection counter: {e:?}")) + })?; Ok(()) } @@ -686,17 +681,19 @@ where &mut self, commitment_path: &CommitmentPath, commitment: PacketCommitment, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { self.packet_commitment_store .set(commitment_path.clone(), commitment) - .map_err(|_| PacketError::ImplementationSpecific)?; + .map_err(|e| { + HostError::failed_to_store(format!("failed to store packet commitment: {e:?}")) + })?; Ok(()) } fn delete_packet_commitment( &mut self, commitment_path: &CommitmentPath, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { self.packet_commitment_store.delete(commitment_path.clone()); Ok(()) } @@ -705,10 +702,12 @@ where &mut self, receipt_path: &ReceiptPath, _receipt: Receipt, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { self.packet_receipt_store .set_path(receipt_path.clone()) - .map_err(|_| PacketError::ImplementationSpecific)?; + .map_err(|e| { + HostError::failed_to_store(format!("failed to store packet receipt: {e:?}")) + })?; Ok(()) } @@ -716,14 +715,16 @@ where &mut self, ack_path: &AckPath, ack_commitment: AcknowledgementCommitment, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { self.packet_ack_store .set(ack_path.clone(), ack_commitment) - .map_err(|_| PacketError::ImplementationSpecific)?; + .map_err(|e| { + HostError::failed_to_store(format!("failed to store packet acknowledgment: {e:?}")) + })?; Ok(()) } - fn delete_packet_acknowledgement(&mut self, ack_path: &AckPath) -> Result<(), ContextError> { + fn delete_packet_acknowledgement(&mut self, ack_path: &AckPath) -> Result<(), HostError> { self.packet_ack_store.delete(ack_path.clone()); Ok(()) } @@ -732,12 +733,10 @@ where &mut self, channel_end_path: &ChannelEndPath, channel_end: ChannelEnd, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { self.channel_end_store .set(channel_end_path.clone(), channel_end) - .map_err(|e| ChannelError::FailedToStoreChannel { - description: format!("{e:?}"), - })?; + .map_err(|e| HostError::failed_to_store(format!("failed to store channel: {e:?}")))?; Ok(()) } @@ -745,10 +744,12 @@ where &mut self, seq_send_path: &SeqSendPath, seq: Sequence, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { self.send_sequence_store .set(seq_send_path.clone(), seq) - .map_err(|_| PacketError::ImplementationSpecific)?; + .map_err(|e| { + HostError::failed_to_store(format!("failed to store send sequence: {e:?}")) + })?; Ok(()) } @@ -756,10 +757,12 @@ where &mut self, seq_recv_path: &SeqRecvPath, seq: Sequence, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { self.recv_sequence_store .set(seq_recv_path.clone(), seq) - .map_err(|_| PacketError::ImplementationSpecific)?; + .map_err(|e| { + HostError::failed_to_store(format!("failed to store recv sequence: {e:?}")) + })?; Ok(()) } @@ -767,34 +770,33 @@ where &mut self, seq_ack_path: &SeqAckPath, seq: Sequence, - ) -> Result<(), ContextError> { + ) -> Result<(), HostError> { self.ack_sequence_store .set(seq_ack_path.clone(), seq) - .map_err(|_| PacketError::ImplementationSpecific)?; + .map_err(|e| { + HostError::failed_to_store(format!("failed to store ack sequence: {e:?}")) + })?; Ok(()) } - fn increase_channel_counter(&mut self) -> Result<(), ContextError> { + fn increase_channel_counter(&mut self) -> Result<(), HostError> { let current_sequence = self .channel_counter .get(StoreHeight::Pending, &NextChannelSequencePath) - .ok_or(ChannelError::MissingCounter)?; + .ok_or(HostError::failed_to_retrieve("missing counter"))?; self.channel_counter .set(NextChannelSequencePath, current_sequence + 1) - .map_err(|e| ChannelError::FailedToUpdateCounter { - description: format!("{e:?}"), - })?; - + .map_err(|e| HostError::failed_to_store(format!("failed to update counter: {e:?}")))?; Ok(()) } - fn emit_ibc_event(&mut self, event: IbcEvent) -> Result<(), ContextError> { + fn emit_ibc_event(&mut self, event: IbcEvent) -> Result<(), HostError> { self.events.lock().push(event); Ok(()) } - fn log_message(&mut self, message: String) -> Result<(), ContextError> { + fn log_message(&mut self, message: String) -> Result<(), HostError> { self.logs.lock().push(message); Ok(()) } diff --git a/tests-integration/tests/core/ics02_client/create_client.rs b/tests-integration/tests/core/ics02_client/create_client.rs index c78fef45c..baa9188c0 100644 --- a/tests-integration/tests/core/ics02_client/create_client.rs +++ b/tests-integration/tests/core/ics02_client/create_client.rs @@ -8,7 +8,7 @@ use ibc::core::client::types::msgs::{ClientMsg, MsgCreateClient}; use ibc::core::client::types::Height; use ibc::core::commitment_types::error::CommitmentError; use ibc::core::entrypoint::{execute, validate}; -use ibc::core::handler::types::error::ContextError; +use ibc::core::handler::types::error::HandlerError; use ibc::core::handler::types::msgs::MsgEnvelope; use ibc::core::host::types::identifiers::ClientId; use ibc::core::host::types::path::{ClientConsensusStatePath, NextClientSequencePath}; @@ -180,9 +180,9 @@ fn test_create_expired_mock_client() { let fxt = create_client_fixture(Ctx::Default, Msg::ExpiredMockHeader); create_client_validate( &fxt, - Expect::Failure(Some(ContextError::ClientError( - ClientError::UnexpectedStatus(Status::Expired), - ))), + Expect::Failure(Some(HandlerError::Client(ClientError::UnexpectedStatus( + Status::Expired, + )))), ); } @@ -206,9 +206,9 @@ fn test_create_expired_tm_client() { let fxt = create_client_fixture(Ctx::Default, Msg::ExpiredTendermintHeader); create_client_validate( &fxt, - Expect::Failure(Some(ContextError::ClientError( - ClientError::UnexpectedStatus(Status::Expired), - ))), + Expect::Failure(Some(HandlerError::Client(ClientError::UnexpectedStatus( + Status::Expired, + )))), ); } @@ -218,9 +218,9 @@ fn test_create_frozen_tm_client() { let fxt = create_client_fixture(Ctx::Default, Msg::FrozenTendermintHeader); create_client_validate( &fxt, - Expect::Failure(Some(ContextError::ClientError( - ClientError::UnexpectedStatus(Status::Frozen), - ))), + Expect::Failure(Some(HandlerError::Client(ClientError::UnexpectedStatus( + Status::Frozen, + )))), ); } diff --git a/tests-integration/tests/core/ics02_client/upgrade_client.rs b/tests-integration/tests/core/ics02_client/upgrade_client.rs index 153d69e42..fb2e0f22b 100644 --- a/tests-integration/tests/core/ics02_client/upgrade_client.rs +++ b/tests-integration/tests/core/ics02_client/upgrade_client.rs @@ -4,10 +4,11 @@ use ibc::core::client::types::error::{ClientError, UpgradeClientError}; use ibc::core::client::types::msgs::{ClientMsg, MsgUpgradeClient}; use ibc::core::client::types::Height; use ibc::core::entrypoint::{execute, validate}; -use ibc::core::handler::types::error::ContextError; +use ibc::core::handler::types::error::HandlerError; use ibc::core::handler::types::events::{IbcEvent, MessageEvent}; use ibc::core::handler::types::msgs::MsgEnvelope; use ibc::core::host::types::path::ClientConsensusStatePath; +use ibc_core_host_types::error::HostError; use ibc_testkit::context::MockContext; use ibc_testkit::fixtures::clients::tendermint::{ dummy_tm_client_state_from_header, dummy_valid_tendermint_header, @@ -142,8 +143,10 @@ fn msg_upgrade_client_healthy() { #[test] fn upgrade_client_fail_nonexisting_client() { let fxt = msg_upgrade_client_fixture(Ctx::Default, Msg::Default); - let expected_err = - ContextError::ClientError(ClientError::MissingClientState(fxt.msg.client_id.clone())); + let expected_err = HandlerError::Host(HostError::missing_state(format!( + "missing client state for client {0}", + fxt.msg.client_id.clone() + ))); upgrade_client_validate(&fxt, Expect::Failure(Some(expected_err))); } @@ -158,14 +161,14 @@ fn upgrade_client_fail_low_upgrade_height() { .into(); upgrade_client_validate( &fxt, - Expect::Failure(Some(ContextError::from(expected_err))), + Expect::Failure(Some(HandlerError::from(expected_err))), ); } #[test] fn upgrade_client_fail_unknown_upgraded_client_state() { let fxt = msg_upgrade_client_fixture(Ctx::WithClient, Msg::UnknownUpgradedClientStateType); - let expected_err = ContextError::ClientError(ClientError::InvalidClientStateType( + let expected_err = HandlerError::Client(ClientError::InvalidClientStateType( client_type().to_string(), )); upgrade_client_validate(&fxt, Expect::Failure(Some(expected_err))); diff --git a/tests-integration/tests/core/ics03_connection/conn_open_ack.rs b/tests-integration/tests/core/ics03_connection/conn_open_ack.rs index 5d292b3f7..bf5064ad5 100644 --- a/tests-integration/tests/core/ics03_connection/conn_open_ack.rs +++ b/tests-integration/tests/core/ics03_connection/conn_open_ack.rs @@ -6,13 +6,14 @@ use ibc::core::connection::types::error::ConnectionError; use ibc::core::connection::types::msgs::{ConnectionMsg, MsgConnectionOpenAck}; use ibc::core::connection::types::{ConnectionEnd, Counterparty, State}; use ibc::core::entrypoint::{execute, validate}; -use ibc::core::handler::types::error::ContextError; +use ibc::core::handler::types::error::HandlerError; use ibc::core::handler::types::events::{IbcEvent, MessageEvent}; use ibc::core::handler::types::msgs::MsgEnvelope; use ibc::core::host::types::identifiers::{ChainId, ClientId}; use ibc::core::host::ValidationContext; use ibc::core::primitives::prelude::*; use ibc::core::primitives::ZERO_DURATION; +use ibc_core_host_types::error::HostError; use ibc_testkit::context::MockContext; use ibc_testkit::fixtures::core::connection::dummy_msg_conn_open_ack; use ibc_testkit::fixtures::core::context::TestContextConfig; @@ -126,16 +127,16 @@ fn conn_open_ack_validate(fxt: &Fixture, expect: Expect) { let cons_state_height = fxt.msg.consensus_height_of_a_on_b; match res.unwrap_err() { - ContextError::ConnectionError(ConnectionError::MissingConnection(connection_id)) => { - assert_eq!(connection_id, right_connection_id) + HandlerError::Host(HostError::MissingState { ref description }) => { + assert!(description.contains(right_connection_id.to_string().as_str())) } - ContextError::ConnectionError(ConnectionError::InsufficientConsensusHeight { + HandlerError::Connection(ConnectionError::InsufficientConsensusHeight { target_height, current_height: _, }) => { assert_eq!(cons_state_height, target_height); } - ContextError::ConnectionError(ConnectionError::MismatchedConnectionStates { + HandlerError::Connection(ConnectionError::MismatchedConnectionStates { expected: _, actual: _, }) => {} @@ -187,27 +188,27 @@ fn conn_open_ack_healthy() { #[test] fn conn_open_ack_no_connection() { let fxt = conn_open_ack_fixture(Ctx::New); - let expected_err = ContextError::ConnectionError(ConnectionError::MissingConnection( - fxt.msg.conn_id_on_a.clone(), - )); + let expected_err = HandlerError::Host(HostError::missing_state(format!( + "missing connection end for connection {}", + fxt.msg.conn_id_on_a.clone() + ))); conn_open_ack_validate(&fxt, Expect::Failure(Some(expected_err))); } #[test] fn conn_open_ack_invalid_consensus_height() { let fxt = conn_open_ack_fixture(Ctx::DefaultWithConnection); - let expected_err = - ContextError::ConnectionError(ConnectionError::InsufficientConsensusHeight { - target_height: fxt.msg.consensus_height_of_a_on_b, - current_height: Height::new(0, 10).unwrap(), - }); + let expected_err = HandlerError::Connection(ConnectionError::InsufficientConsensusHeight { + target_height: fxt.msg.consensus_height_of_a_on_b, + current_height: Height::new(0, 10).unwrap(), + }); conn_open_ack_validate(&fxt, Expect::Failure(Some(expected_err))); } #[test] fn conn_open_ack_connection_mismatch() { let fxt = conn_open_ack_fixture(Ctx::NewWithConnectionEndOpen); - let expected_err = ContextError::ConnectionError(ConnectionError::MismatchedConnectionStates { + let expected_err = HandlerError::Connection(ConnectionError::MismatchedConnectionStates { expected: State::Init.to_string(), actual: State::Open.to_string(), }); diff --git a/tests-integration/tests/core/router.rs b/tests-integration/tests/core/router.rs index 303f5f469..825352428 100644 --- a/tests-integration/tests/core/router.rs +++ b/tests-integration/tests/core/router.rs @@ -4,7 +4,6 @@ use ibc::apps::transfer::handler::send_transfer; use ibc::apps::transfer::types::error::TokenTransferError; use ibc::apps::transfer::types::msgs::transfer::MsgTransfer; use ibc::apps::transfer::types::{BaseCoin, U256}; -use ibc::core::channel::types::error::ChannelError; use ibc::core::channel::types::msgs::{ ChannelMsg, MsgAcknowledgement, MsgChannelCloseConfirm, MsgChannelCloseInit, MsgChannelOpenAck, MsgChannelOpenInit, MsgChannelOpenTry, MsgRecvPacket, MsgTimeoutOnClose, PacketMsg, @@ -14,7 +13,7 @@ use ibc::core::client::types::msgs::{ClientMsg, MsgCreateClient, MsgUpdateClient use ibc::core::client::types::Height; use ibc::core::connection::types::msgs::ConnectionMsg; use ibc::core::entrypoint::dispatch; -use ibc::core::handler::types::error::ContextError; +use ibc::core::handler::types::error::HandlerError; use ibc::core::handler::types::events::{IbcEvent, MessageEvent}; use ibc::core::handler::types::msgs::MsgEnvelope; use ibc::core::host::types::identifiers::ConnectionId; @@ -22,6 +21,7 @@ use ibc::core::host::types::path::CommitmentPath; use ibc::core::host::ValidationContext; use ibc::core::primitives::prelude::*; use ibc::core::primitives::Timestamp; +use ibc_core_host_types::error::HostError; use ibc_testkit::context::MockContext; use ibc_testkit::fixtures::applications::transfer::{ extract_transfer_packet, MsgTransferConfig, PacketDataConfig, @@ -407,10 +407,10 @@ fn routing_module_and_keepers() { let res = match test.msg.clone() { TestMsg::Ics26(msg) => dispatch(&mut ctx.ibc_store, &mut router, msg), TestMsg::Ics20(msg) => send_transfer(&mut ctx.ibc_store, &mut DummyTransferModule, msg) - .map_err(|e: TokenTransferError| ChannelError::AppModule { - description: e.to_string(), + .map_err(|e: TokenTransferError| HostError::Other { + description: format!("token transfer application error: {e}"), }) - .map_err(ContextError::from), + .map_err(HandlerError::from), }; assert_eq!(