From cca4d618a97a0a22dd20f6ad24fbb4b0ec7006fe Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 14 Jun 2024 15:01:08 +0200 Subject: [PATCH 1/8] add port capability --- .../ics03-connection/types/src/connection.rs | 1 - ibc-core/ics04-channel/src/context.rs | 19 ++++++++++++++- .../src/handler/chan_open_init.rs | 8 +++++++ .../src/handler/chan_open_try.rs | 8 +++++++ .../ics04-channel/src/handler/send_packet.rs | 12 ++++++++-- ibc-core/ics04-channel/types/src/error.rs | 10 ++++++++ ibc-core/ics24-host/src/context.rs | 22 ++++++++++++++++- .../types/src/identifiers/capability_key.rs | 24 +++++++++++++++++++ .../ics24-host/types/src/identifiers/mod.rs | 2 ++ ibc-core/ics26-routing/src/module.rs | 12 ++++++++-- 10 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 ibc-core/ics24-host/types/src/identifiers/capability_key.rs diff --git a/ibc-core/ics03-connection/types/src/connection.rs b/ibc-core/ics03-connection/types/src/connection.rs index 1a6499193..227632161 100644 --- a/ibc-core/ics03-connection/types/src/connection.rs +++ b/ibc-core/ics03-connection/types/src/connection.rs @@ -2,7 +2,6 @@ use core::fmt::{Display, Error as FmtError, Formatter}; use core::time::Duration; -use core::u64; use ibc_core_client_types::error::ClientError; use ibc_core_commitment_types::commitment::CommitmentPrefix; diff --git a/ibc-core/ics04-channel/src/context.rs b/ibc-core/ics04-channel/src/context.rs index 1fba1de8f..fa5714986 100644 --- a/ibc-core/ics04-channel/src/context.rs +++ b/ibc-core/ics04-channel/src/context.rs @@ -6,9 +6,10 @@ 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::identifiers::{ConnectionId, Sequence}; +use ibc_core_host::types::identifiers::{ChannelId, ConnectionId, PortId, Sequence}; use ibc_core_host::types::path::{ChannelEndPath, CommitmentPath, SeqSendPath}; use ibc_core_host::{ExecutionContext, ValidationContext}; +use ibc_core_router::module::Module; use ibc_primitives::prelude::*; /// Methods required in send packet validation, to be implemented by the host @@ -26,6 +27,13 @@ pub trait SendPacketValidationContext { fn get_next_sequence_send(&self, seq_send_path: &SeqSendPath) -> Result; + + fn has_port_capability( + &self, + module: &impl Module, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result<(), ContextError>; } impl SendPacketValidationContext for T @@ -52,6 +60,15 @@ where ) -> Result { self.get_next_sequence_send(seq_send_path) } + + fn has_port_capability( + &self, + module: &impl Module, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result<(), ContextError> { + self.has_port_capability(module.identifier().to_string().into(), port_id, channel_id) + } } /// Methods required in send packet execution, to be implemented by the host 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..38c75c353 100644 --- a/ibc-core/ics04-channel/src/handler/chan_open_init.rs +++ b/ibc-core/ics04-channel/src/handler/chan_open_init.rs @@ -32,6 +32,8 @@ where &msg.version_proposal, )?; + ctx_a.available_port_capability(&msg.port_id_on_a, &chan_id_on_a)?; + Ok(()) } @@ -104,6 +106,12 @@ where } } + ctx_a.claim_port_capability( + module.identifier().to_string().into(), + &msg.port_id_on_a, + &chan_id_on_a, + )?; + Ok(()) } 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 08c82deac..4297364d8 100644 --- a/ibc-core/ics04-channel/src/handler/chan_open_try.rs +++ b/ibc-core/ics04-channel/src/handler/chan_open_try.rs @@ -38,6 +38,8 @@ where &msg.version_supported_on_a, )?; + ctx_b.available_port_capability(&msg.port_id_on_b, &chan_id_on_b)?; + Ok(()) } @@ -112,6 +114,12 @@ where } } + ctx_b.claim_port_capability( + module.identifier().to_string().into(), + &msg.port_id_on_b, + &chan_id_on_b, + )?; + Ok(()) } diff --git a/ibc-core/ics04-channel/src/handler/send_packet.rs b/ibc-core/ics04-channel/src/handler/send_packet.rs index 895ad9457..6aa93ce60 100644 --- a/ibc-core/ics04-channel/src/handler/send_packet.rs +++ b/ibc-core/ics04-channel/src/handler/send_packet.rs @@ -9,6 +9,7 @@ use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::path::{ ChannelEndPath, ClientConsensusStatePath, CommitmentPath, SeqSendPath, }; +use ibc_core_router::module::Module; use ibc_primitives::prelude::*; use ibc_primitives::Expiry; @@ -19,17 +20,21 @@ use crate::context::{SendPacketExecutionContext, SendPacketValidationContext}; /// Equivalent to calling [`send_packet_validate`], followed by [`send_packet_execute`] pub fn send_packet( ctx_a: &mut impl SendPacketExecutionContext, + module: &impl Module, packet: Packet, ) -> Result<(), ContextError> { - send_packet_validate(ctx_a, &packet)?; - send_packet_execute(ctx_a, packet) + send_packet_validate(ctx_a, module, &packet)?; + send_packet_execute(ctx_a, module, packet) } /// Validate that sending the given packet would succeed. pub fn send_packet_validate( ctx_a: &impl SendPacketValidationContext, + module: &impl Module, packet: &Packet, ) -> Result<(), ContextError> { + ctx_a.has_port_capability(module, &packet.port_id_on_a, &packet.chan_id_on_a)?; + if !packet.timeout_height_on_b.is_set() && !packet.timeout_timestamp_on_b.is_set() { return Err(ContextError::PacketError(PacketError::MissingTimeout)); } @@ -104,8 +109,11 @@ pub fn send_packet_validate( /// A prior call to [`send_packet_validate`] MUST have succeeded. pub fn send_packet_execute( ctx_a: &mut impl SendPacketExecutionContext, + module: &impl Module, packet: Packet, ) -> Result<(), ContextError> { + ctx_a.has_port_capability(module, &packet.port_id_on_a, &packet.chan_id_on_a)?; + { 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/types/src/error.rs b/ibc-core/ics04-channel/types/src/error.rs index 2b7b760ef..ac53949fa 100644 --- a/ibc-core/ics04-channel/types/src/error.rs +++ b/ibc-core/ics04-channel/types/src/error.rs @@ -71,6 +71,16 @@ pub enum ChannelError { InvalidIdentifier(IdentifierError), /// channel counter overflow error CounterOverflow, + /// Capability for `{port_id}/{channel_id}` does not exist + CapabilityNotFound { + port_id: PortId, + channel_id: ChannelId, + }, + /// Capability for `{port_id}/{channel_id}` already exists + CapabilityAlreadyExists { + port_id: PortId, + channel_id: ChannelId, + }, /// other error: `{description}` Other { description: String }, } diff --git a/ibc-core/ics24-host/src/context.rs b/ibc-core/ics24-host/src/context.rs index da858968d..16d1a804b 100644 --- a/ibc-core/ics24-host/src/context.rs +++ b/ibc-core/ics24-host/src/context.rs @@ -10,7 +10,7 @@ use ibc_core_connection_types::version::{pick_version, Version as ConnectionVers 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::identifiers::{ConnectionId, Sequence}; +use ibc_core_host_types::identifiers::{CapabilityKey, ChannelId, ConnectionId, PortId, Sequence}; use ibc_core_host_types::path::{ AckPath, ChannelEndPath, ClientConnectionPath, CommitmentPath, ConnectionPath, ReceiptPath, SeqAckPath, SeqRecvPath, SeqSendPath, @@ -126,6 +126,19 @@ pub trait ValidationContext { /// `ExecutionContext::increase_channel_counter`. fn channel_counter(&self) -> Result; + fn available_port_capability( + &self, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result<(), ContextError>; + + fn has_port_capability( + &self, + capability: CapabilityKey, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result<(), ContextError>; + /// Returns the maximum expected time per block fn max_expected_time_per_block(&self) -> Duration; @@ -233,6 +246,13 @@ pub trait ExecutionContext: ValidationContext { /// Increases the counter, that keeps track of how many channels have been created. fn increase_channel_counter(&mut self) -> Result<(), ContextError>; + fn claim_port_capability( + &mut self, + capability: CapabilityKey, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result<(), ContextError>; + /// Emit the given IBC event fn emit_ibc_event(&mut self, event: IbcEvent) -> Result<(), ContextError>; diff --git a/ibc-core/ics24-host/types/src/identifiers/capability_key.rs b/ibc-core/ics24-host/types/src/identifiers/capability_key.rs new file mode 100644 index 000000000..5c2927e66 --- /dev/null +++ b/ibc-core/ics24-host/types/src/identifiers/capability_key.rs @@ -0,0 +1,24 @@ +use core::any::TypeId; + +use ibc_primitives::prelude::String; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct CapabilityKey(String); + +impl From for CapabilityKey { + fn from(type_id: TypeId) -> Self { + Self(std::format!("{:?}", type_id)) + } +} + +impl From for CapabilityKey { + fn from(value: String) -> Self { + Self(value) + } +} + +impl AsRef for CapabilityKey { + fn as_ref(&self) -> &str { + self.0.as_str() + } +} diff --git a/ibc-core/ics24-host/types/src/identifiers/mod.rs b/ibc-core/ics24-host/types/src/identifiers/mod.rs index 9ae79f673..6acd8aa3f 100644 --- a/ibc-core/ics24-host/types/src/identifiers/mod.rs +++ b/ibc-core/ics24-host/types/src/identifiers/mod.rs @@ -1,5 +1,6 @@ //! Defines identifier types +mod capability_key; mod chain_id; mod channel_id; mod client_id; @@ -8,6 +9,7 @@ mod connection_id; mod port_id; mod sequence; +pub use capability_key::CapabilityKey; pub use chain_id::ChainId; pub use channel_id::ChannelId; pub use client_id::ClientId; diff --git a/ibc-core/ics26-routing/src/module.rs b/ibc-core/ics26-routing/src/module.rs index 26b296713..47ddbfaee 100644 --- a/ibc-core/ics26-routing/src/module.rs +++ b/ibc-core/ics26-routing/src/module.rs @@ -1,5 +1,7 @@ +use core::any::TypeId; /// The trait that defines an IBC application use core::fmt::Debug; +use core::fmt::Write; use ibc_core_channel_types::acknowledgement::Acknowledgement; use ibc_core_channel_types::channel::{Counterparty, Order}; @@ -7,11 +9,17 @@ use ibc_core_channel_types::error::{ChannelError, PacketError}; use ibc_core_channel_types::packet::Packet; use ibc_core_channel_types::Version; use ibc_core_host_types::identifiers::{ChannelId, ConnectionId, PortId}; -use ibc_core_router_types::module::ModuleExtras; +use ibc_core_router_types::module::{ModuleExtras, ModuleId}; use ibc_primitives::prelude::*; use ibc_primitives::Signer; -pub trait Module: Debug { +pub trait Module: 'static + Debug { + fn identifier(&self) -> ModuleId { + let mut buf = String::new(); + write!(buf, "{:?}", TypeId::of::()).expect("Never fails"); + ModuleId::new(buf) + } + fn on_chan_open_init_validate( &self, order: Order, From 1f9fecf09bb691d5bc94400d35071ab1de762ebb Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 14 Jun 2024 15:01:29 +0200 Subject: [PATCH 2/8] update ibc-apps --- ibc-apps/ics20-transfer/src/context.rs | 3 ++- ibc-apps/ics20-transfer/src/handler/send_transfer.rs | 4 ++-- ibc-apps/ics721-nft-transfer/src/context.rs | 3 ++- ibc-apps/ics721-nft-transfer/src/handler/send_transfer.rs | 4 ++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ibc-apps/ics20-transfer/src/context.rs b/ibc-apps/ics20-transfer/src/context.rs index 8c22ad386..93aa6cc92 100644 --- a/ibc-apps/ics20-transfer/src/context.rs +++ b/ibc-apps/ics20-transfer/src/context.rs @@ -5,9 +5,10 @@ use ibc_app_transfer_types::{Memo, PrefixedCoin, PrefixedDenom}; use ibc_core::host::types::identifiers::{ChannelId, PortId}; use ibc_core::primitives::prelude::*; use ibc_core::primitives::Signer; +use ibc_core::router::module::Module; /// Methods required in token transfer validation, to be implemented by the host -pub trait TokenTransferValidationContext { +pub trait TokenTransferValidationContext: Module { type AccountId: TryFrom; /// get_port returns the portID for the transfer module. diff --git a/ibc-apps/ics20-transfer/src/handler/send_transfer.rs b/ibc-apps/ics20-transfer/src/handler/send_transfer.rs index 439e5604c..c73eb852c 100644 --- a/ibc-apps/ics20-transfer/src/handler/send_transfer.rs +++ b/ibc-apps/ics20-transfer/src/handler/send_transfer.rs @@ -95,7 +95,7 @@ where } }; - send_packet_validate(send_packet_ctx_a, &packet)?; + send_packet_validate(send_packet_ctx_a, token_ctx_a, &packet)?; Ok(()) } @@ -170,7 +170,7 @@ where } }; - send_packet_execute(send_packet_ctx_a, packet)?; + send_packet_execute(send_packet_ctx_a, token_ctx_a, packet)?; { send_packet_ctx_a.log_message(format!( diff --git a/ibc-apps/ics721-nft-transfer/src/context.rs b/ibc-apps/ics721-nft-transfer/src/context.rs index ede6ee898..5977fcbf8 100644 --- a/ibc-apps/ics721-nft-transfer/src/context.rs +++ b/ibc-apps/ics721-nft-transfer/src/context.rs @@ -3,6 +3,7 @@ use ibc_core::host::types::identifiers::{ChannelId, PortId}; use ibc_core::primitives::prelude::*; use ibc_core::primitives::Signer; +use ibc_core::router::module::Module; use crate::types::error::NftTransferError; use crate::types::{ @@ -35,7 +36,7 @@ pub trait NftClassContext { } /// Read-only methods required in NFT transfer validation context. -pub trait NftTransferValidationContext { +pub trait NftTransferValidationContext: Module { type AccountId: TryFrom + PartialEq; type Nft: NftContext; type NftClass: NftClassContext; diff --git a/ibc-apps/ics721-nft-transfer/src/handler/send_transfer.rs b/ibc-apps/ics721-nft-transfer/src/handler/send_transfer.rs index 4cf1a759c..320d0b723 100644 --- a/ibc-apps/ics721-nft-transfer/src/handler/send_transfer.rs +++ b/ibc-apps/ics721-nft-transfer/src/handler/send_transfer.rs @@ -127,7 +127,7 @@ where } }; - send_packet_validate(send_packet_ctx_a, &packet)?; + send_packet_validate(send_packet_ctx_a, transfer_ctx, &packet)?; Ok(()) } @@ -229,7 +229,7 @@ where } }; - send_packet_execute(send_packet_ctx_a, packet)?; + send_packet_execute(send_packet_ctx_a, transfer_ctx, packet)?; { send_packet_ctx_a.log_message(format!( From ba0f68870313293ad93342f7985bef9cb1fc8e02 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 14 Jun 2024 15:01:52 +0200 Subject: [PATCH 3/8] update ibc-testkit types --- ibc-testkit/src/context.rs | 7 +++ ibc-testkit/src/testapp/ibc/core/core_ctx.rs | 54 +++++++++++++++++++- ibc-testkit/src/testapp/ibc/core/types.rs | 7 ++- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/ibc-testkit/src/context.rs b/ibc-testkit/src/context.rs index 4380de474..ebf6be415 100644 --- a/ibc-testkit/src/context.rs +++ b/ibc-testkit/src/context.rs @@ -19,6 +19,7 @@ use ibc::core::host::types::path::{ SeqAckPath, SeqRecvPath, SeqSendPath, }; use ibc::core::host::{ExecutionContext, ValidationContext}; +use ibc::core::router::module::Module; use ibc::primitives::prelude::*; use ibc::primitives::Timestamp; @@ -386,6 +387,7 @@ where /// This does not bootstrap any corresponding IBC connection or light client. pub fn with_channel( mut self, + module: &impl Module, port_id: PortId, chan_id: ChannelId, channel_end: ChannelEnd, @@ -394,6 +396,11 @@ where self.ibc_store .store_channel(&channel_end_path, channel_end) .expect("error writing to store"); + + self.ibc_store + .claim_port_capability(module.identifier().to_string().into(), &port_id, &chan_id) + .expect("error writing to store"); + self } diff --git a/ibc-testkit/src/testapp/ibc/core/core_ctx.rs b/ibc-testkit/src/testapp/ibc/core/core_ctx.rs index d650cccd1..cf80cec29 100644 --- a/ibc-testkit/src/testapp/ibc/core/core_ctx.rs +++ b/ibc-testkit/src/testapp/ibc/core/core_ctx.rs @@ -18,7 +18,9 @@ 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::identifiers::{ClientId, ConnectionId, Sequence}; +use ibc::core::host::types::identifiers::{ + CapabilityKey, ChannelId, ClientId, ConnectionId, PortId, Sequence, +}; use ibc::core::host::types::path::{ AckPath, ChannelEndPath, ClientConnectionPath, CommitmentPath, ConnectionPath, NextChannelSequencePath, NextClientSequencePath, NextConnectionSequencePath, Path, ReceiptPath, @@ -266,6 +268,43 @@ where fn get_client_validation_context(&self) -> &Self::V { self } + + fn available_port_capability( + &self, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result<(), ContextError> { + (!self + .port_capabilities + .lock() + .contains_key(&(port_id.clone(), channel_id.clone()))) + .then_some(()) + .ok_or_else(|| { + ContextError::ChannelError(ChannelError::CapabilityAlreadyExists { + port_id: port_id.clone(), + channel_id: channel_id.clone(), + }) + }) + } + + fn has_port_capability( + &self, + capability: CapabilityKey, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result<(), ContextError> { + self.port_capabilities + .lock() + .get(&(port_id.clone(), channel_id.clone())) + .filter(|stored_capability| stored_capability == &&capability) + .ok_or_else(|| { + ContextError::ChannelError(ChannelError::CapabilityNotFound { + port_id: port_id.clone(), + channel_id: channel_id.clone(), + }) + }) + .map(|_| ()) + } } /// Trait to provide proofs in gRPC service blanket implementations. @@ -776,6 +815,19 @@ where Ok(()) } + fn claim_port_capability( + &mut self, + capability: CapabilityKey, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result<(), ContextError> { + self.port_capabilities + .lock() + .insert((port_id.clone(), channel_id.clone()), capability); + + Ok(()) + } + fn store_next_sequence_send( &mut self, seq_send_path: &SeqSendPath, diff --git a/ibc-testkit/src/testapp/ibc/core/types.rs b/ibc-testkit/src/testapp/ibc/core/types.rs index a1296cf6a..af61cfc46 100644 --- a/ibc-testkit/src/testapp/ibc/core/types.rs +++ b/ibc-testkit/src/testapp/ibc/core/types.rs @@ -12,7 +12,9 @@ use ibc::core::client::context::client_state::ClientStateValidation; use ibc::core::client::types::Height; use ibc::core::connection::types::ConnectionEnd; use ibc::core::handler::types::events::IbcEvent; -use ibc::core::host::types::identifiers::{ConnectionId, Sequence}; +use ibc::core::host::types::identifiers::{ + CapabilityKey, ChannelId, ConnectionId, PortId, Sequence, +}; use ibc::core::host::types::path::{ AckPath, ChannelEndPath, ClientConnectionPath, ClientConsensusStatePath, ClientStatePath, ClientUpdateHeightPath, ClientUpdateTimePath, CommitmentPath, ConnectionPath, @@ -89,6 +91,8 @@ where pub host_consensus_states: Arc>>, /// Map of older ibc commitment proofs pub ibc_commiment_proofs: Arc>>, + /// Map of port capabilities + pub port_capabilities: Arc>>, /// IBC Events pub events: Arc>>, /// message logs @@ -138,6 +142,7 @@ where packet_commitment_store: TypedStore::new(shared_store.clone()), packet_receipt_store: TypedStore::new(shared_store.clone()), packet_ack_store: TypedStore::new(shared_store.clone()), + port_capabilities: Arc::new(Mutex::new(Default::default())), events: Arc::new(Mutex::new(Vec::new())), logs: Arc::new(Mutex::new(Vec::new())), store: shared_store, From bccd4c514cb5c7ce930a50a5f8d8cb51698de952 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 14 Jun 2024 15:02:40 +0200 Subject: [PATCH 4/8] update tests --- .../core/ics04_channel/acknowledgement.rs | 11 ++++- .../core/ics04_channel/chan_close_confirm.rs | 3 ++ .../core/ics04_channel/chan_close_init.rs | 3 ++ .../tests/core/ics04_channel/chan_open_ack.rs | 5 +++ .../core/ics04_channel/chan_open_confirm.rs | 22 ++++++++-- .../tests/core/ics04_channel/recv_packet.rs | 16 ++++++- .../tests/core/ics04_channel/send_packet.rs | 44 ++++++++++++++++--- .../tests/core/ics04_channel/timeout.rs | 20 ++++++++- .../core/ics04_channel/timeout_on_close.rs | 15 ++++++- 9 files changed, 123 insertions(+), 16 deletions(-) diff --git a/tests-integration/tests/core/ics04_channel/acknowledgement.rs b/tests-integration/tests/core/ics04_channel/acknowledgement.rs index 1afd22fe1..6228241ae 100644 --- a/tests-integration/tests/core/ics04_channel/acknowledgement.rs +++ b/tests-integration/tests/core/ics04_channel/acknowledgement.rs @@ -16,6 +16,7 @@ use ibc::core::primitives::*; use ibc_testkit::context::MockContext; use ibc_testkit::fixtures::core::channel::dummy_raw_msg_acknowledgement; use ibc_testkit::hosts::MockHost; +use ibc_testkit::testapp::ibc::applications::transfer::types::DummyTransferModule; use ibc_testkit::testapp::ibc::core::router::MockRouter; use ibc_testkit::testapp::ibc::core::types::LightClientState; use rstest::*; @@ -128,6 +129,7 @@ fn ack_success_no_packet_commitment(fixture: Fixture) { LightClientState::::with_latest_height(client_height), ) .with_channel( + &DummyTransferModule, PortId::transfer(), ChannelId::zero(), chan_end_on_a_unordered, @@ -162,6 +164,7 @@ fn ack_success_happy_path(fixture: Fixture) { LightClientState::::with_latest_height(client_height), ) .with_channel( + &DummyTransferModule, PortId::transfer(), ChannelId::zero(), chan_end_on_a_unordered, @@ -197,6 +200,7 @@ fn ack_unordered_chan_execute(fixture: Fixture) { } = fixture; let mut ctx = ctx .with_channel( + &DummyTransferModule, PortId::transfer(), ChannelId::zero(), chan_end_on_a_unordered, @@ -237,7 +241,12 @@ fn ack_ordered_chan_execute(fixture: Fixture) { .. } = fixture; let mut ctx = ctx - .with_channel(PortId::transfer(), ChannelId::zero(), chan_end_on_a_ordered) + .with_channel( + &DummyTransferModule, + PortId::transfer(), + ChannelId::zero(), + chan_end_on_a_ordered, + ) .with_connection(ConnectionId::zero(), conn_end_on_a) .with_packet_commitment( msg.packet.port_id_on_a.clone(), diff --git a/tests-integration/tests/core/ics04_channel/chan_close_confirm.rs b/tests-integration/tests/core/ics04_channel/chan_close_confirm.rs index f3491f9ca..571f33a64 100644 --- a/tests-integration/tests/core/ics04_channel/chan_close_confirm.rs +++ b/tests-integration/tests/core/ics04_channel/chan_close_confirm.rs @@ -15,6 +15,7 @@ use ibc_testkit::context::MockContext; use ibc_testkit::fixtures::core::channel::dummy_raw_msg_chan_close_confirm; use ibc_testkit::fixtures::core::connection::dummy_raw_counterparty_conn; use ibc_testkit::hosts::MockHost; +use ibc_testkit::testapp::ibc::applications::transfer::types::DummyTransferModule; use ibc_testkit::testapp::ibc::clients::mock::client_state::client_type as mock_client_type; use ibc_testkit::testapp::ibc::core::router::MockRouter; use ibc_testkit::testapp::ibc::core::types::LightClientState; @@ -61,6 +62,7 @@ fn test_chan_close_confirm_validate() { ) .with_connection(conn_id, conn_end) .with_channel( + &DummyTransferModule, msg_chan_close_confirm.port_id_on_b.clone(), msg_chan_close_confirm.chan_id_on_b, chan_end, @@ -118,6 +120,7 @@ fn test_chan_close_confirm_execute() { ) .with_connection(conn_id, conn_end) .with_channel( + &DummyTransferModule, msg_chan_close_confirm.port_id_on_b.clone(), msg_chan_close_confirm.chan_id_on_b, chan_end, diff --git a/tests-integration/tests/core/ics04_channel/chan_close_init.rs b/tests-integration/tests/core/ics04_channel/chan_close_init.rs index 63fd30d65..6cc0a3052 100644 --- a/tests-integration/tests/core/ics04_channel/chan_close_init.rs +++ b/tests-integration/tests/core/ics04_channel/chan_close_init.rs @@ -15,6 +15,7 @@ use ibc_testkit::context::MockContext; use ibc_testkit::fixtures::core::channel::dummy_raw_msg_chan_close_init; use ibc_testkit::fixtures::core::connection::dummy_raw_counterparty_conn; use ibc_testkit::hosts::MockHost; +use ibc_testkit::testapp::ibc::applications::transfer::types::DummyTransferModule; use ibc_testkit::testapp::ibc::clients::mock::client_state::client_type as mock_client_type; use ibc_testkit::testapp::ibc::core::router::MockRouter; use ibc_testkit::testapp::ibc::core::types::LightClientState; @@ -61,6 +62,7 @@ fn test_chan_close_init_validate() { ) .with_connection(conn_id, conn_end) .with_channel( + &DummyTransferModule, msg_chan_close_init.port_id_on_a.clone(), msg_chan_close_init.chan_id_on_a, chan_end, @@ -119,6 +121,7 @@ fn test_chan_close_init_execute() { ) .with_connection(conn_id, conn_end) .with_channel( + &DummyTransferModule, msg_chan_close_init.port_id_on_a.clone(), msg_chan_close_init.chan_id_on_a, chan_end, diff --git a/tests-integration/tests/core/ics04_channel/chan_open_ack.rs b/tests-integration/tests/core/ics04_channel/chan_open_ack.rs index e4250dd83..1be144c29 100644 --- a/tests-integration/tests/core/ics04_channel/chan_open_ack.rs +++ b/tests-integration/tests/core/ics04_channel/chan_open_ack.rs @@ -16,6 +16,7 @@ use ibc_testkit::context::MockContext; use ibc_testkit::fixtures::core::channel::dummy_raw_msg_chan_open_ack; use ibc_testkit::fixtures::core::connection::dummy_raw_counterparty_conn; use ibc_testkit::hosts::MockHost; +use ibc_testkit::testapp::ibc::applications::transfer::types::DummyTransferModule; use ibc_testkit::testapp::ibc::clients::mock::client_state::client_type as mock_client_type; use ibc_testkit::testapp::ibc::core::router::MockRouter; use ibc_testkit::testapp::ibc::core::types::LightClientState; @@ -98,6 +99,7 @@ fn chan_open_ack_happy_path(fixture: Fixture) { ) .with_connection(conn_id_on_a, conn_end_on_a) .with_channel( + &DummyTransferModule, msg.port_id_on_a.clone(), msg.chan_id_on_a.clone(), chan_end_on_a, @@ -131,6 +133,7 @@ fn chan_open_ack_execute_happy_path(fixture: Fixture) { ) .with_connection(conn_id_on_a, conn_end_on_a) .with_channel( + &DummyTransferModule, msg.port_id_on_a.clone(), msg.chan_id_on_a.clone(), chan_end_on_a, @@ -170,6 +173,7 @@ fn chan_open_ack_fail_no_connection(fixture: Fixture) { LightClientState::::with_latest_height(Height::new(0, proof_height).unwrap()), ) .with_channel( + &DummyTransferModule, msg.port_id_on_a.clone(), msg.chan_id_on_a.clone(), chan_end_on_a, @@ -242,6 +246,7 @@ fn chan_open_ack_fail_channel_wrong_state(fixture: Fixture) { ) .with_connection(conn_id_on_a, conn_end_on_a) .with_channel( + &DummyTransferModule, msg.port_id_on_a.clone(), msg.chan_id_on_a.clone(), wrong_chan_end, diff --git a/tests-integration/tests/core/ics04_channel/chan_open_confirm.rs b/tests-integration/tests/core/ics04_channel/chan_open_confirm.rs index 0b399aa40..09efbd991 100644 --- a/tests-integration/tests/core/ics04_channel/chan_open_confirm.rs +++ b/tests-integration/tests/core/ics04_channel/chan_open_confirm.rs @@ -15,6 +15,7 @@ use ibc_testkit::context::MockContext; use ibc_testkit::fixtures::core::channel::dummy_raw_msg_chan_open_confirm; use ibc_testkit::fixtures::core::connection::dummy_raw_counterparty_conn; use ibc_testkit::hosts::MockHost; +use ibc_testkit::testapp::ibc::applications::transfer::types::DummyTransferModule; use ibc_testkit::testapp::ibc::clients::mock::client_state::client_type as mock_client_type; use ibc_testkit::testapp::ibc::core::router::MockRouter; use ibc_testkit::testapp::ibc::core::types::LightClientState; @@ -94,7 +95,12 @@ fn chan_open_confirm_validate_happy_path(fixture: Fixture) { LightClientState::::with_latest_height(Height::new(0, proof_height).unwrap()), ) .with_connection(conn_id_on_b, conn_end_on_b) - .with_channel(msg.port_id_on_b.clone(), ChannelId::zero(), chan_end_on_b); + .with_channel( + &DummyTransferModule, + msg.port_id_on_b.clone(), + ChannelId::zero(), + chan_end_on_b, + ); let msg_envelope = MsgEnvelope::from(ChannelMsg::from(msg)); @@ -123,7 +129,12 @@ fn chan_open_confirm_execute_happy_path(fixture: Fixture) { LightClientState::::with_latest_height(Height::new(0, proof_height).unwrap()), ) .with_connection(conn_id_on_b, conn_end_on_b) - .with_channel(msg.port_id_on_b.clone(), ChannelId::zero(), chan_end_on_b); + .with_channel( + &DummyTransferModule, + msg.port_id_on_b.clone(), + ChannelId::zero(), + chan_end_on_b, + ); let msg_envelope = MsgEnvelope::from(ChannelMsg::from(msg)); @@ -199,7 +210,12 @@ fn chan_open_confirm_fail_channel_wrong_state(fixture: Fixture) { LightClientState::::with_latest_height(Height::new(0, proof_height).unwrap()), ) .with_connection(conn_id_on_b, conn_end_on_b) - .with_channel(msg.port_id_on_b.clone(), ChannelId::zero(), wrong_chan_end); + .with_channel( + &DummyTransferModule, + msg.port_id_on_b.clone(), + ChannelId::zero(), + wrong_chan_end, + ); let msg_envelope = MsgEnvelope::from(ChannelMsg::from(msg)); diff --git a/tests-integration/tests/core/ics04_channel/recv_packet.rs b/tests-integration/tests/core/ics04_channel/recv_packet.rs index df946f1e3..6c3e041f1 100644 --- a/tests-integration/tests/core/ics04_channel/recv_packet.rs +++ b/tests-integration/tests/core/ics04_channel/recv_packet.rs @@ -17,6 +17,7 @@ use ibc_testkit::context::MockContext; use ibc_testkit::fixtures::core::channel::{dummy_msg_recv_packet, dummy_raw_msg_recv_packet}; use ibc_testkit::fixtures::core::signer::dummy_account_id; use ibc_testkit::hosts::MockHost; +use ibc_testkit::testapp::ibc::applications::transfer::types::DummyTransferModule; use ibc_testkit::testapp::ibc::core::router::MockRouter; use ibc_testkit::testapp::ibc::core::types::LightClientState; use rstest::*; @@ -124,6 +125,7 @@ fn recv_packet_validate_happy_path(fixture: Fixture) { ) .with_connection(ConnectionId::zero(), conn_end_on_b) .with_channel( + &DummyTransferModule, packet.port_id_on_b.clone(), packet.chan_id_on_b.clone(), chan_end_on_b, @@ -190,7 +192,12 @@ fn recv_packet_timeout_expired(fixture: Fixture) { LightClientState::::with_latest_height(client_height), ) .with_connection(ConnectionId::zero(), conn_end_on_b) - .with_channel(PortId::transfer(), ChannelId::zero(), chan_end_on_b) + .with_channel( + &DummyTransferModule, + PortId::transfer(), + ChannelId::zero(), + chan_end_on_b, + ) .with_send_sequence(PortId::transfer(), ChannelId::zero(), 1.into()) .advance_block_up_to_height(host_height); @@ -219,7 +226,12 @@ fn recv_packet_execute_happy_path(fixture: Fixture) { LightClientState::::with_latest_height(client_height), ) .with_connection(ConnectionId::zero(), conn_end_on_b) - .with_channel(PortId::transfer(), ChannelId::zero(), chan_end_on_b); + .with_channel( + &DummyTransferModule, + PortId::transfer(), + ChannelId::zero(), + chan_end_on_b, + ); let msg_env = MsgEnvelope::from(PacketMsg::from(msg)); diff --git a/tests-integration/tests/core/ics04_channel/send_packet.rs b/tests-integration/tests/core/ics04_channel/send_packet.rs index 3a2bace44..dec5343f7 100644 --- a/tests-integration/tests/core/ics04_channel/send_packet.rs +++ b/tests-integration/tests/core/ics04_channel/send_packet.rs @@ -18,6 +18,7 @@ use ibc::core::primitives::*; use ibc_testkit::context::MockContext; use ibc_testkit::fixtures::core::channel::dummy_raw_packet; use ibc_testkit::hosts::MockHost; +use ibc_testkit::testapp::ibc::applications::transfer::types::DummyTransferModule; use ibc_testkit::testapp::ibc::core::types::LightClientState; use test_log::test; @@ -92,6 +93,8 @@ fn send_packet_processing() { packet }; + let dummy_transfer_module = DummyTransferModule; + let tests: Vec = vec![ Test { name: "Processing fails because no channel exists in the context".to_string(), @@ -107,7 +110,12 @@ fn send_packet_processing() { LightClientState::::with_latest_height(client_height), ) .with_connection(ConnectionId::zero(), conn_end_on_a.clone()) - .with_channel(PortId::transfer(), ChannelId::zero(), chan_end_on_a.clone()) + .with_channel( + &dummy_transfer_module, + PortId::transfer(), + ChannelId::zero(), + chan_end_on_a.clone(), + ) .with_send_sequence(PortId::transfer(), ChannelId::zero(), 1.into()), packet, want_pass: true, @@ -120,7 +128,12 @@ fn send_packet_processing() { LightClientState::::with_latest_height(client_height), ) .with_connection(ConnectionId::zero(), conn_end_on_a.clone()) - .with_channel(PortId::transfer(), ChannelId::zero(), chan_end_on_a.clone()) + .with_channel( + &dummy_transfer_module, + PortId::transfer(), + ChannelId::zero(), + chan_end_on_a.clone(), + ) .with_send_sequence(PortId::transfer(), ChannelId::zero(), 1.into()), packet: packet_timeout_equal_client_height, want_pass: true, @@ -133,7 +146,12 @@ fn send_packet_processing() { LightClientState::::with_latest_height(client_height), ) .with_connection(ConnectionId::zero(), conn_end_on_a.clone()) - .with_channel(PortId::transfer(), ChannelId::zero(), chan_end_on_a.clone()) + .with_channel( + &dummy_transfer_module, + PortId::transfer(), + ChannelId::zero(), + chan_end_on_a.clone(), + ) .with_send_sequence(PortId::transfer(), ChannelId::zero(), 1.into()), packet: packet_timeout_one_before_client_height, want_pass: false, @@ -146,7 +164,12 @@ fn send_packet_processing() { LightClientState::::with_latest_height(client_height), ) .with_connection(ConnectionId::zero(), conn_end_on_a.clone()) - .with_channel(PortId::transfer(), ChannelId::zero(), chan_end_on_a.clone()) + .with_channel( + &dummy_transfer_module, + PortId::transfer(), + ChannelId::zero(), + chan_end_on_a.clone(), + ) .with_send_sequence(PortId::transfer(), ChannelId::zero(), 1.into()), packet: packet_with_no_timeout, want_pass: false, @@ -159,7 +182,12 @@ fn send_packet_processing() { LightClientState::::with_latest_height(client_height), ) .with_connection(ConnectionId::zero(), conn_end_on_a) - .with_channel(PortId::transfer(), ChannelId::zero(), chan_end_on_a) + .with_channel( + &dummy_transfer_module, + PortId::transfer(), + ChannelId::zero(), + chan_end_on_a, + ) .with_send_sequence(PortId::transfer(), ChannelId::zero(), 1.into()), packet: packet_with_timestamp_old, want_pass: false, @@ -169,7 +197,11 @@ fn send_packet_processing() { .collect(); for mut test in tests { - let res = send_packet(&mut test.ctx.ibc_store, test.packet.clone()); + let res = send_packet( + &mut test.ctx.ibc_store, + &DummyTransferModule, + test.packet.clone(), + ); // Additionally check the events and the output objects in the result. match res { Ok(()) => { diff --git a/tests-integration/tests/core/ics04_channel/timeout.rs b/tests-integration/tests/core/ics04_channel/timeout.rs index 240ddd4a8..6322e6e27 100644 --- a/tests-integration/tests/core/ics04_channel/timeout.rs +++ b/tests-integration/tests/core/ics04_channel/timeout.rs @@ -18,6 +18,7 @@ use ibc::core::primitives::*; use ibc_testkit::context::MockContext; use ibc_testkit::fixtures::core::channel::dummy_raw_msg_timeout; use ibc_testkit::hosts::MockHost; +use ibc_testkit::testapp::ibc::applications::transfer::types::DummyTransferModule; use ibc_testkit::testapp::ibc::core::router::MockRouter; use ibc_testkit::testapp::ibc::core::types::LightClientState; use rstest::*; @@ -145,6 +146,7 @@ fn timeout_fail_no_consensus_state_for_height(fixture: Fixture) { let mut ctx = ctx .with_channel( + &DummyTransferModule, PortId::transfer(), ChannelId::zero(), chan_end_on_a_unordered, @@ -208,6 +210,7 @@ fn timeout_fail_proof_timeout_not_reached(fixture: Fixture) { ) .with_connection(ConnectionId::zero(), conn_end_on_a) .with_channel( + &DummyTransferModule, PortId::transfer(), ChannelId::zero(), chan_end_on_a_unordered, @@ -242,6 +245,7 @@ fn timeout_success_no_packet_commitment(fixture: Fixture) { } = fixture; let ctx = ctx .with_channel( + &DummyTransferModule, PortId::transfer(), ChannelId::zero(), chan_end_on_a_unordered, @@ -280,6 +284,7 @@ fn timeout_unordered_channel_validate(fixture: Fixture) { ) .with_connection(ConnectionId::zero(), conn_end_on_a) .with_channel( + &DummyTransferModule, PortId::transfer(), ChannelId::zero(), chan_end_on_a_unordered, @@ -319,7 +324,12 @@ fn timeout_ordered_channel_validate(fixture: Fixture) { LightClientState::::with_latest_height(client_height), ) .with_connection(ConnectionId::zero(), conn_end_on_a) - .with_channel(PortId::transfer(), ChannelId::zero(), chan_end_on_a_ordered) + .with_channel( + &DummyTransferModule, + PortId::transfer(), + ChannelId::zero(), + chan_end_on_a_ordered, + ) .with_packet_commitment( packet.port_id_on_a, packet.chan_id_on_a, @@ -347,6 +357,7 @@ fn timeout_unordered_chan_execute(fixture: Fixture) { } = fixture; let mut ctx = ctx .with_channel( + &DummyTransferModule, PortId::transfer(), ChannelId::zero(), chan_end_on_a_unordered, @@ -388,7 +399,12 @@ fn timeout_ordered_chan_execute(fixture: Fixture) { .. } = fixture; let mut ctx = ctx - .with_channel(PortId::transfer(), ChannelId::zero(), chan_end_on_a_ordered) + .with_channel( + &DummyTransferModule, + PortId::transfer(), + ChannelId::zero(), + chan_end_on_a_ordered, + ) .with_connection(ConnectionId::zero(), conn_end_on_a) .with_packet_commitment( msg.packet.port_id_on_a.clone(), diff --git a/tests-integration/tests/core/ics04_channel/timeout_on_close.rs b/tests-integration/tests/core/ics04_channel/timeout_on_close.rs index a454261fd..73e4b4aaa 100644 --- a/tests-integration/tests/core/ics04_channel/timeout_on_close.rs +++ b/tests-integration/tests/core/ics04_channel/timeout_on_close.rs @@ -15,6 +15,7 @@ use ibc::core::primitives::*; use ibc_testkit::context::MockContext; use ibc_testkit::fixtures::core::channel::dummy_raw_msg_timeout_on_close; use ibc_testkit::hosts::MockHost; +use ibc_testkit::testapp::ibc::applications::transfer::types::DummyTransferModule; use ibc_testkit::testapp::ibc::core::router::MockRouter; use ibc_testkit::testapp::ibc::core::types::LightClientState; use rstest::*; @@ -117,7 +118,12 @@ fn timeout_on_close_success_no_packet_commitment(fixture: Fixture) { .. } = fixture; let context = context - .with_channel(PortId::transfer(), ChannelId::zero(), chan_end_on_a) + .with_channel( + &DummyTransferModule, + PortId::transfer(), + ChannelId::zero(), + chan_end_on_a, + ) .with_connection(ConnectionId::zero(), conn_end_on_a); let msg_envelope = MsgEnvelope::from(PacketMsg::from(msg)); @@ -142,7 +148,12 @@ fn timeout_on_close_success_happy_path(fixture: Fixture) { .. } = fixture; let context = context - .with_channel(PortId::transfer(), ChannelId::zero(), chan_end_on_a) + .with_channel( + &DummyTransferModule, + PortId::transfer(), + ChannelId::zero(), + chan_end_on_a, + ) .with_connection(ConnectionId::zero(), conn_end_on_a) .with_packet_commitment( msg.packet.port_id_on_a.clone(), From c1017e6e8f1d88f2792984cb21dba038904e2a58 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 14 Jun 2024 15:23:09 +0200 Subject: [PATCH 5/8] no_std --- ibc-core/ics24-host/types/src/identifiers/capability_key.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ibc-core/ics24-host/types/src/identifiers/capability_key.rs b/ibc-core/ics24-host/types/src/identifiers/capability_key.rs index 5c2927e66..628c10e47 100644 --- a/ibc-core/ics24-host/types/src/identifiers/capability_key.rs +++ b/ibc-core/ics24-host/types/src/identifiers/capability_key.rs @@ -1,4 +1,5 @@ use core::any::TypeId; +use core::fmt::Write; use ibc_primitives::prelude::String; @@ -7,7 +8,9 @@ pub struct CapabilityKey(String); impl From for CapabilityKey { fn from(type_id: TypeId) -> Self { - Self(std::format!("{:?}", type_id)) + let mut buf = String::new(); + write!(buf, "{:?}", type_id).unwrap(); + Self(buf) } } From 956437d3f904c5244bbcd1a3ae14e295f4cad2dc Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Sat, 15 Jun 2024 15:01:38 +0200 Subject: [PATCH 6/8] use PortPath to store capabilities --- ibc-core/ics04-channel/src/context.rs | 12 ++-- .../src/handler/chan_open_init.rs | 12 ++-- .../src/handler/chan_open_try.rs | 12 ++-- .../ics04-channel/src/handler/send_packet.rs | 6 +- ibc-core/ics04-channel/types/src/error.rs | 15 ++--- ibc-core/ics24-host/src/context.rs | 18 ++---- .../types/src/identifiers/capability_key.rs | 1 + ibc-testkit/src/context.rs | 4 +- ibc-testkit/src/testapp/ibc/core/core_ctx.rs | 57 +++++++------------ ibc-testkit/src/testapp/ibc/core/types.rs | 12 ++-- 10 files changed, 63 insertions(+), 86 deletions(-) diff --git a/ibc-core/ics04-channel/src/context.rs b/ibc-core/ics04-channel/src/context.rs index fa5714986..d39e9cd08 100644 --- a/ibc-core/ics04-channel/src/context.rs +++ b/ibc-core/ics04-channel/src/context.rs @@ -6,8 +6,8 @@ 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::identifiers::{ChannelId, ConnectionId, PortId, Sequence}; -use ibc_core_host::types::path::{ChannelEndPath, CommitmentPath, SeqSendPath}; +use ibc_core_host::types::identifiers::{ConnectionId, Sequence}; +use ibc_core_host::types::path::{ChannelEndPath, CommitmentPath, PortPath, SeqSendPath}; use ibc_core_host::{ExecutionContext, ValidationContext}; use ibc_core_router::module::Module; use ibc_primitives::prelude::*; @@ -30,9 +30,8 @@ pub trait SendPacketValidationContext { fn has_port_capability( &self, + port_path: &PortPath, module: &impl Module, - port_id: &PortId, - channel_id: &ChannelId, ) -> Result<(), ContextError>; } @@ -63,11 +62,10 @@ where fn has_port_capability( &self, + port_path: &PortPath, module: &impl Module, - port_id: &PortId, - channel_id: &ChannelId, ) -> Result<(), ContextError> { - self.has_port_capability(module.identifier().to_string().into(), port_id, channel_id) + self.has_port_capability(port_path, module.identifier().to_string().into()) } } 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 38c75c353..9ac96a2d0 100644 --- a/ibc-core/ics04-channel/src/handler/chan_open_init.rs +++ b/ibc-core/ics04-channel/src/handler/chan_open_init.rs @@ -7,7 +7,7 @@ use ibc_core_client::context::prelude::*; use ibc_core_handler_types::error::ContextError; 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}; +use ibc_core_host::types::path::{ChannelEndPath, PortPath, SeqAckPath, SeqRecvPath, SeqSendPath}; use ibc_core_host::{ExecutionContext, ValidationContext}; use ibc_core_router::module::Module; use ibc_primitives::prelude::*; @@ -32,7 +32,12 @@ where &msg.version_proposal, )?; - ctx_a.available_port_capability(&msg.port_id_on_a, &chan_id_on_a)?; + let port_path = PortPath(msg.port_id_on_a); + + // either the capability is available or the module has the capability. + ctx_a.available_port_capability(&port_path).or_else(|_| { + ctx_a.has_port_capability(&port_path, module.identifier().to_string().into()) + })?; Ok(()) } @@ -107,9 +112,8 @@ where } ctx_a.claim_port_capability( + &PortPath(msg.port_id_on_a), module.identifier().to_string().into(), - &msg.port_id_on_a, - &chan_id_on_a, )?; Ok(()) 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 4297364d8..6413c1a94 100644 --- a/ibc-core/ics04-channel/src/handler/chan_open_try.rs +++ b/ibc-core/ics04-channel/src/handler/chan_open_try.rs @@ -10,7 +10,7 @@ use ibc_core_handler_types::error::ContextError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::identifiers::ChannelId; use ibc_core_host::types::path::{ - ChannelEndPath, ClientConsensusStatePath, Path, SeqAckPath, SeqRecvPath, SeqSendPath, + ChannelEndPath, ClientConsensusStatePath, Path, PortPath, SeqAckPath, SeqRecvPath, SeqSendPath, }; use ibc_core_host::{ExecutionContext, ValidationContext}; use ibc_core_router::module::Module; @@ -38,7 +38,12 @@ where &msg.version_supported_on_a, )?; - ctx_b.available_port_capability(&msg.port_id_on_b, &chan_id_on_b)?; + let port_path = PortPath(msg.port_id_on_b); + + // either the capability is available or the module has the capability. + ctx_b.available_port_capability(&port_path).or_else(|_| { + ctx_b.has_port_capability(&port_path, module.identifier().to_string().into()) + })?; Ok(()) } @@ -115,9 +120,8 @@ where } ctx_b.claim_port_capability( + &PortPath(msg.port_id_on_b), module.identifier().to_string().into(), - &msg.port_id_on_b, - &chan_id_on_b, )?; Ok(()) diff --git a/ibc-core/ics04-channel/src/handler/send_packet.rs b/ibc-core/ics04-channel/src/handler/send_packet.rs index 6aa93ce60..609ceb12c 100644 --- a/ibc-core/ics04-channel/src/handler/send_packet.rs +++ b/ibc-core/ics04-channel/src/handler/send_packet.rs @@ -7,7 +7,7 @@ use ibc_core_client::context::prelude::*; use ibc_core_handler_types::error::ContextError; use ibc_core_handler_types::events::{IbcEvent, MessageEvent}; use ibc_core_host::types::path::{ - ChannelEndPath, ClientConsensusStatePath, CommitmentPath, SeqSendPath, + ChannelEndPath, ClientConsensusStatePath, CommitmentPath, PortPath, SeqSendPath, }; use ibc_core_router::module::Module; use ibc_primitives::prelude::*; @@ -33,7 +33,7 @@ pub fn send_packet_validate( module: &impl Module, packet: &Packet, ) -> Result<(), ContextError> { - ctx_a.has_port_capability(module, &packet.port_id_on_a, &packet.chan_id_on_a)?; + ctx_a.has_port_capability(&PortPath(packet.port_id_on_a.clone()), module)?; if !packet.timeout_height_on_b.is_set() && !packet.timeout_timestamp_on_b.is_set() { return Err(ContextError::PacketError(PacketError::MissingTimeout)); @@ -112,7 +112,7 @@ pub fn send_packet_execute( module: &impl Module, packet: Packet, ) -> Result<(), ContextError> { - ctx_a.has_port_capability(module, &packet.port_id_on_a, &packet.chan_id_on_a)?; + ctx_a.has_port_capability(&PortPath(packet.port_id_on_a.clone()), module)?; { let seq_send_path_on_a = SeqSendPath::new(&packet.port_id_on_a, &packet.chan_id_on_a); diff --git a/ibc-core/ics04-channel/types/src/error.rs b/ibc-core/ics04-channel/types/src/error.rs index ac53949fa..dc8952e08 100644 --- a/ibc-core/ics04-channel/types/src/error.rs +++ b/ibc-core/ics04-channel/types/src/error.rs @@ -5,6 +5,7 @@ use ibc_core_client_types::{error as client_error, Height}; use ibc_core_connection_types::error as connection_error; use ibc_core_host_types::error::IdentifierError; use ibc_core_host_types::identifiers::{ChannelId, ConnectionId, PortId, Sequence}; +use ibc_core_host_types::path::PortPath; use ibc_primitives::prelude::*; use ibc_primitives::{ParseTimestampError, Timestamp}; @@ -71,16 +72,10 @@ pub enum ChannelError { InvalidIdentifier(IdentifierError), /// channel counter overflow error CounterOverflow, - /// Capability for `{port_id}/{channel_id}` does not exist - CapabilityNotFound { - port_id: PortId, - channel_id: ChannelId, - }, - /// Capability for `{port_id}/{channel_id}` already exists - CapabilityAlreadyExists { - port_id: PortId, - channel_id: ChannelId, - }, + /// Capability for `{0}` does not exist + CapabilityNotFound(PortPath), + /// Capability for `{0}` already exists + CapabilityAlreadyExists(PortPath), /// other error: `{description}` Other { description: String }, } diff --git a/ibc-core/ics24-host/src/context.rs b/ibc-core/ics24-host/src/context.rs index 16d1a804b..b6513a09d 100644 --- a/ibc-core/ics24-host/src/context.rs +++ b/ibc-core/ics24-host/src/context.rs @@ -10,10 +10,10 @@ use ibc_core_connection_types::version::{pick_version, Version as ConnectionVers 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::identifiers::{CapabilityKey, ChannelId, ConnectionId, PortId, Sequence}; +use ibc_core_host_types::identifiers::{CapabilityKey, ConnectionId, Sequence}; use ibc_core_host_types::path::{ - AckPath, ChannelEndPath, ClientConnectionPath, CommitmentPath, ConnectionPath, ReceiptPath, - SeqAckPath, SeqRecvPath, SeqSendPath, + AckPath, ChannelEndPath, ClientConnectionPath, CommitmentPath, ConnectionPath, PortPath, + ReceiptPath, SeqAckPath, SeqRecvPath, SeqSendPath, }; use ibc_primitives::prelude::*; use ibc_primitives::{Signer, Timestamp}; @@ -126,17 +126,12 @@ pub trait ValidationContext { /// `ExecutionContext::increase_channel_counter`. fn channel_counter(&self) -> Result; - fn available_port_capability( - &self, - port_id: &PortId, - channel_id: &ChannelId, - ) -> Result<(), ContextError>; + fn available_port_capability(&self, port_path: &PortPath) -> Result<(), ContextError>; fn has_port_capability( &self, + port_path: &PortPath, capability: CapabilityKey, - port_id: &PortId, - channel_id: &ChannelId, ) -> Result<(), ContextError>; /// Returns the maximum expected time per block @@ -248,9 +243,8 @@ pub trait ExecutionContext: ValidationContext { fn claim_port_capability( &mut self, + port_path: &PortPath, capability: CapabilityKey, - port_id: &PortId, - channel_id: &ChannelId, ) -> Result<(), ContextError>; /// Emit the given IBC event diff --git a/ibc-core/ics24-host/types/src/identifiers/capability_key.rs b/ibc-core/ics24-host/types/src/identifiers/capability_key.rs index 628c10e47..1c9f2d914 100644 --- a/ibc-core/ics24-host/types/src/identifiers/capability_key.rs +++ b/ibc-core/ics24-host/types/src/identifiers/capability_key.rs @@ -3,6 +3,7 @@ use core::fmt::Write; use ibc_primitives::prelude::String; +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, Eq, PartialEq)] pub struct CapabilityKey(String); diff --git a/ibc-testkit/src/context.rs b/ibc-testkit/src/context.rs index ebf6be415..4c1984ddb 100644 --- a/ibc-testkit/src/context.rs +++ b/ibc-testkit/src/context.rs @@ -16,7 +16,7 @@ use ibc::core::handler::types::msgs::MsgEnvelope; use ibc::core::host::types::identifiers::{ChannelId, ClientId, ConnectionId, PortId, Sequence}; use ibc::core::host::types::path::{ ChannelEndPath, ClientConsensusStatePath, ClientStatePath, CommitmentPath, ConnectionPath, - SeqAckPath, SeqRecvPath, SeqSendPath, + PortPath, SeqAckPath, SeqRecvPath, SeqSendPath, }; use ibc::core::host::{ExecutionContext, ValidationContext}; use ibc::core::router::module::Module; @@ -398,7 +398,7 @@ where .expect("error writing to store"); self.ibc_store - .claim_port_capability(module.identifier().to_string().into(), &port_id, &chan_id) + .claim_port_capability(&PortPath(port_id), module.identifier().to_string().into()) .expect("error writing to store"); self diff --git a/ibc-testkit/src/testapp/ibc/core/core_ctx.rs b/ibc-testkit/src/testapp/ibc/core/core_ctx.rs index cf80cec29..af7c26b5a 100644 --- a/ibc-testkit/src/testapp/ibc/core/core_ctx.rs +++ b/ibc-testkit/src/testapp/ibc/core/core_ctx.rs @@ -18,13 +18,11 @@ 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::identifiers::{ - CapabilityKey, ChannelId, ClientId, ConnectionId, PortId, Sequence, -}; +use ibc::core::host::types::identifiers::{CapabilityKey, ClientId, ConnectionId, Sequence}; use ibc::core::host::types::path::{ AckPath, ChannelEndPath, ClientConnectionPath, CommitmentPath, ConnectionPath, - NextChannelSequencePath, NextClientSequencePath, NextConnectionSequencePath, Path, ReceiptPath, - SeqAckPath, SeqRecvPath, SeqSendPath, + NextChannelSequencePath, NextClientSequencePath, NextConnectionSequencePath, Path, PortPath, + ReceiptPath, SeqAckPath, SeqRecvPath, SeqSendPath, }; use ibc::core::host::{ClientStateRef, ConsensusStateRef, ExecutionContext, ValidationContext}; use ibc::core::primitives::prelude::*; @@ -235,10 +233,7 @@ where ) -> Result { Ok(self .packet_ack_store - .get( - StoreHeight::Pending, - &AckPath::new(&ack_path.port_id, &ack_path.channel_id, ack_path.sequence), - ) + .get(StoreHeight::Pending, ack_path) .ok_or(PacketError::PacketAcknowledgementNotFound { sequence: ack_path.sequence, })?) @@ -269,39 +264,26 @@ where self } - fn available_port_capability( - &self, - port_id: &PortId, - channel_id: &ChannelId, - ) -> Result<(), ContextError> { - (!self - .port_capabilities - .lock() - .contains_key(&(port_id.clone(), channel_id.clone()))) - .then_some(()) - .ok_or_else(|| { - ContextError::ChannelError(ChannelError::CapabilityAlreadyExists { - port_id: port_id.clone(), - channel_id: channel_id.clone(), + fn available_port_capability(&self, port_path: &PortPath) -> Result<(), ContextError> { + self.port_capabilities + .get(StoreHeight::Pending, port_path) + .is_none() + .then_some(()) + .ok_or_else(|| { + ContextError::ChannelError(ChannelError::CapabilityAlreadyExists(port_path.clone())) }) - }) } fn has_port_capability( &self, + port_path: &PortPath, capability: CapabilityKey, - port_id: &PortId, - channel_id: &ChannelId, ) -> Result<(), ContextError> { self.port_capabilities - .lock() - .get(&(port_id.clone(), channel_id.clone())) - .filter(|stored_capability| stored_capability == &&capability) + .get(StoreHeight::Pending, port_path) + .filter(|stored_capability| stored_capability == &capability) .ok_or_else(|| { - ContextError::ChannelError(ChannelError::CapabilityNotFound { - port_id: port_id.clone(), - channel_id: channel_id.clone(), - }) + ContextError::ChannelError(ChannelError::CapabilityNotFound(port_path.clone())) }) .map(|_| ()) } @@ -817,13 +799,14 @@ where fn claim_port_capability( &mut self, + port_path: &PortPath, capability: CapabilityKey, - port_id: &PortId, - channel_id: &ChannelId, ) -> Result<(), ContextError> { self.port_capabilities - .lock() - .insert((port_id.clone(), channel_id.clone()), capability); + .set(port_path.clone(), capability) + .map_err(|_| ChannelError::Other { + description: "Port capability claim store error".to_string(), + })?; Ok(()) } diff --git a/ibc-testkit/src/testapp/ibc/core/types.rs b/ibc-testkit/src/testapp/ibc/core/types.rs index af61cfc46..1e7e7d018 100644 --- a/ibc-testkit/src/testapp/ibc/core/types.rs +++ b/ibc-testkit/src/testapp/ibc/core/types.rs @@ -12,14 +12,12 @@ use ibc::core::client::context::client_state::ClientStateValidation; use ibc::core::client::types::Height; use ibc::core::connection::types::ConnectionEnd; use ibc::core::handler::types::events::IbcEvent; -use ibc::core::host::types::identifiers::{ - CapabilityKey, ChannelId, ConnectionId, PortId, Sequence, -}; +use ibc::core::host::types::identifiers::{CapabilityKey, ConnectionId, Sequence}; use ibc::core::host::types::path::{ AckPath, ChannelEndPath, ClientConnectionPath, ClientConsensusStatePath, ClientStatePath, ClientUpdateHeightPath, ClientUpdateTimePath, CommitmentPath, ConnectionPath, - NextChannelSequencePath, NextClientSequencePath, NextConnectionSequencePath, ReceiptPath, - SeqAckPath, SeqRecvPath, SeqSendPath, + NextChannelSequencePath, NextClientSequencePath, NextConnectionSequencePath, PortPath, + ReceiptPath, SeqAckPath, SeqRecvPath, SeqSendPath, }; use ibc::core::primitives::prelude::*; use ibc::core::primitives::Timestamp; @@ -92,7 +90,7 @@ where /// Map of older ibc commitment proofs pub ibc_commiment_proofs: Arc>>, /// Map of port capabilities - pub port_capabilities: Arc>>, + pub port_capabilities: JsonStore, PortPath, CapabilityKey>, /// IBC Events pub events: Arc>>, /// message logs @@ -142,7 +140,7 @@ where packet_commitment_store: TypedStore::new(shared_store.clone()), packet_receipt_store: TypedStore::new(shared_store.clone()), packet_ack_store: TypedStore::new(shared_store.clone()), - port_capabilities: Arc::new(Mutex::new(Default::default())), + port_capabilities: TypedStore::new(shared_store.clone()), events: Arc::new(Mutex::new(Vec::new())), logs: Arc::new(Mutex::new(Vec::new())), store: shared_store, From 7a8f2e1018942235e95ea5b65e101d23c8021bdd Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Sat, 15 Jun 2024 15:08:30 +0200 Subject: [PATCH 7/8] derive traits for CapabilityKey --- .../types/src/identifiers/capability_key.rs | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/ibc-core/ics24-host/types/src/identifiers/capability_key.rs b/ibc-core/ics24-host/types/src/identifiers/capability_key.rs index 1c9f2d914..d26eaed6b 100644 --- a/ibc-core/ics24-host/types/src/identifiers/capability_key.rs +++ b/ibc-core/ics24-host/types/src/identifiers/capability_key.rs @@ -1,28 +1,41 @@ use core::any::TypeId; use core::fmt::Write; -use ibc_primitives::prelude::String; +use ibc_primitives::prelude::*; +#[cfg_attr( + feature = "parity-scale-codec", + derive( + parity_scale_codec::Encode, + parity_scale_codec::Decode, + scale_info::TypeInfo + ) +)] +#[cfg_attr( + feature = "borsh", + derive(borsh::BorshSerialize, borsh::BorshDeserialize) +)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct CapabilityKey(String); +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct CapabilityKey(Vec); impl From for CapabilityKey { fn from(type_id: TypeId) -> Self { let mut buf = String::new(); write!(buf, "{:?}", type_id).unwrap(); - Self(buf) + buf.into() } } impl From for CapabilityKey { fn from(value: String) -> Self { - Self(value) + Self(value.as_bytes().to_vec()) } } -impl AsRef for CapabilityKey { - fn as_ref(&self) -> &str { - self.0.as_str() +impl AsRef<[u8]> for CapabilityKey { + fn as_ref(&self) -> &[u8] { + self.0.as_slice() } } From b8e3b589bb2a7451e4ea742ffd10e92dbddb6114 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Sat, 15 Jun 2024 15:15:20 +0200 Subject: [PATCH 8/8] avoid TypeId for ModuleId --- ibc-core/ics26-routing/src/module.rs | 8 +------- .../src/testapp/ibc/applications/nft_transfer/module.rs | 6 +++++- .../src/testapp/ibc/applications/transfer/module.rs | 6 +++++- ibc-testkit/src/testapp/ibc/core/types.rs | 8 ++++++++ 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/ibc-core/ics26-routing/src/module.rs b/ibc-core/ics26-routing/src/module.rs index 47ddbfaee..b046a5a3b 100644 --- a/ibc-core/ics26-routing/src/module.rs +++ b/ibc-core/ics26-routing/src/module.rs @@ -1,7 +1,5 @@ -use core::any::TypeId; /// The trait that defines an IBC application use core::fmt::Debug; -use core::fmt::Write; use ibc_core_channel_types::acknowledgement::Acknowledgement; use ibc_core_channel_types::channel::{Counterparty, Order}; @@ -14,11 +12,7 @@ use ibc_primitives::prelude::*; use ibc_primitives::Signer; pub trait Module: 'static + Debug { - fn identifier(&self) -> ModuleId { - let mut buf = String::new(); - write!(buf, "{:?}", TypeId::of::()).expect("Never fails"); - ModuleId::new(buf) - } + fn identifier(&self) -> ModuleId; fn on_chan_open_init_validate( &self, diff --git a/ibc-testkit/src/testapp/ibc/applications/nft_transfer/module.rs b/ibc-testkit/src/testapp/ibc/applications/nft_transfer/module.rs index 06652a1dd..81f8e23cf 100644 --- a/ibc-testkit/src/testapp/ibc/applications/nft_transfer/module.rs +++ b/ibc-testkit/src/testapp/ibc/applications/nft_transfer/module.rs @@ -7,11 +7,15 @@ use ibc::core::host::types::identifiers::{ChannelId, ConnectionId, PortId}; use ibc::core::primitives::prelude::*; use ibc::core::primitives::Signer; use ibc::core::router::module::Module; -use ibc::core::router::types::module::ModuleExtras; +use ibc::core::router::types::module::{ModuleExtras, ModuleId}; use super::types::DummyNftTransferModule; impl Module for DummyNftTransferModule { + fn identifier(&self) -> ModuleId { + ModuleId::new("nft-transfer".to_string()) + } + fn on_chan_open_init_validate( &self, _order: Order, diff --git a/ibc-testkit/src/testapp/ibc/applications/transfer/module.rs b/ibc-testkit/src/testapp/ibc/applications/transfer/module.rs index 2246c893b..c1de20212 100644 --- a/ibc-testkit/src/testapp/ibc/applications/transfer/module.rs +++ b/ibc-testkit/src/testapp/ibc/applications/transfer/module.rs @@ -7,11 +7,15 @@ use ibc::core::host::types::identifiers::{ChannelId, ConnectionId, PortId}; use ibc::core::primitives::prelude::*; use ibc::core::primitives::Signer; use ibc::core::router::module::Module; -use ibc::core::router::types::module::ModuleExtras; +use ibc::core::router::types::module::{ModuleExtras, ModuleId}; use super::types::DummyTransferModule; impl Module for DummyTransferModule { + fn identifier(&self) -> ModuleId { + ModuleId::new("transfer".to_string()) + } + fn on_chan_open_init_validate( &self, _order: Order, diff --git a/ibc-testkit/src/testapp/ibc/core/types.rs b/ibc-testkit/src/testapp/ibc/core/types.rs index 1e7e7d018..12742c0fb 100644 --- a/ibc-testkit/src/testapp/ibc/core/types.rs +++ b/ibc-testkit/src/testapp/ibc/core/types.rs @@ -227,6 +227,10 @@ mod tests { } impl Module for FooModule { + fn identifier(&self) -> ModuleId { + ModuleId::new("foomodule".to_string()) + } + fn on_chan_open_init_validate( &self, _order: Order, @@ -327,6 +331,10 @@ mod tests { struct BarModule; impl Module for BarModule { + fn identifier(&self) -> ModuleId { + ModuleId::new("barmodule".to_string()) + } + fn on_chan_open_init_validate( &self, _order: Order,