diff --git a/.changelog/unreleased/breaking-changes/145-compatible-connection-events.md b/.changelog/unreleased/breaking-changes/145-compatible-connection-events.md new file mode 100644 index 000000000..e34d77d1e --- /dev/null +++ b/.changelog/unreleased/breaking-changes/145-compatible-connection-events.md @@ -0,0 +1,2 @@ +- Make connection events compatible with ibc-go + ([#145](https://github.com/cosmos/ibc-rs/issues/145)) \ No newline at end of file diff --git a/crates/ibc/src/core/ics03_connection/events.rs b/crates/ibc/src/core/ics03_connection/events.rs index 912b95bef..5db480af7 100644 --- a/crates/ibc/src/core/ics03_connection/events.rs +++ b/crates/ibc/src/core/ics03_connection/events.rs @@ -5,7 +5,7 @@ use tendermint::abci::tag::Tag; use tendermint::abci::Event as AbciEvent; use crate::core::ics24_host::identifier::{ClientId, ConnectionId}; -use crate::events::{IbcEvent, IbcEventType}; +use crate::events::IbcEventType; use crate::prelude::*; /// The content of the `key` field for the attribute containing the connection identifier. @@ -15,8 +15,8 @@ pub const COUNTERPARTY_CONN_ID_ATTRIBUTE_KEY: &str = "counterparty_connection_id pub const COUNTERPARTY_CLIENT_ID_ATTRIBUTE_KEY: &str = "counterparty_client_id"; #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)] -pub struct Attributes { - pub connection_id: Option, +struct Attributes { + pub connection_id: ConnectionId, pub client_id: ClientId, pub counterparty_connection_id: Option, pub counterparty_client_id: ClientId, @@ -32,56 +32,67 @@ pub struct Attributes { /// we will be able to remove the `.parse().unwrap()` calls. impl From for Vec { fn from(a: Attributes) -> Self { - let mut attributes = vec![]; - if let Some(conn_id) = a.connection_id { - let conn_id = Tag { - key: CONN_ID_ATTRIBUTE_KEY.parse().unwrap(), - value: conn_id.to_string().parse().unwrap(), - }; - attributes.push(conn_id); - } + let conn_id = Tag { + key: CONN_ID_ATTRIBUTE_KEY.parse().unwrap(), + value: a.connection_id.to_string().parse().unwrap(), + }; + let client_id = Tag { key: CLIENT_ID_ATTRIBUTE_KEY.parse().unwrap(), value: a.client_id.to_string().parse().unwrap(), }; - attributes.push(client_id); - if let Some(conn_id) = a.counterparty_connection_id { - let conn_id = Tag { - key: COUNTERPARTY_CONN_ID_ATTRIBUTE_KEY.parse().unwrap(), - value: conn_id.to_string().parse().unwrap(), - }; - attributes.push(conn_id); - } + + let counterparty_conn_id = Tag { + key: COUNTERPARTY_CONN_ID_ATTRIBUTE_KEY.parse().unwrap(), + value: match a.counterparty_connection_id { + Some(counterparty_conn_id) => counterparty_conn_id.to_string().parse().unwrap(), + None => "".parse().unwrap(), + }, + }; + let counterparty_client_id = Tag { key: COUNTERPARTY_CLIENT_ID_ATTRIBUTE_KEY.parse().unwrap(), value: a.counterparty_client_id.to_string().parse().unwrap(), }; - attributes.push(counterparty_client_id); - attributes + + vec![ + conn_id, + client_id, + counterparty_client_id, + counterparty_conn_id, + ] } } #[derive(Clone, Debug, PartialEq, Eq, Serialize)] -pub struct OpenInit(pub Attributes); +pub struct OpenInit(Attributes); impl OpenInit { - pub fn attributes(&self) -> &Attributes { - &self.0 + /// Per our convention, this event is generated on chain A. + pub fn new( + conn_id_on_a: ConnectionId, + client_id_on_a: ClientId, + client_id_on_b: ClientId, + ) -> Self { + Self(Attributes { + connection_id: conn_id_on_a, + client_id: client_id_on_a, + counterparty_connection_id: None, + counterparty_client_id: client_id_on_b, + }) } - pub fn connection_id(&self) -> Option<&ConnectionId> { - self.0.connection_id.as_ref() - } -} -impl From for OpenInit { - fn from(attrs: Attributes) -> Self { - OpenInit(attrs) + pub fn connection_id(&self) -> &ConnectionId { + &self.0.connection_id } -} - -impl From for IbcEvent { - fn from(v: OpenInit) -> Self { - IbcEvent::OpenInitConnection(v) + pub fn client_id(&self) -> &ClientId { + &self.0.client_id + } + pub fn counterparty_connection_id(&self) -> Option<&ConnectionId> { + self.0.counterparty_connection_id.as_ref() + } + pub fn counterparty_client_id(&self) -> &ClientId { + &self.0.counterparty_client_id } } @@ -96,26 +107,35 @@ impl From for AbciEvent { } #[derive(Clone, Debug, PartialEq, Eq, Serialize)] -pub struct OpenTry(pub Attributes); +pub struct OpenTry(Attributes); impl OpenTry { - pub fn attributes(&self) -> &Attributes { - &self.0 + /// Per our convention, this event is generated on chain B. + pub fn new( + conn_id_on_b: ConnectionId, + client_id_on_b: ClientId, + conn_id_on_a: ConnectionId, + client_id_on_a: ClientId, + ) -> Self { + Self(Attributes { + connection_id: conn_id_on_b, + client_id: client_id_on_b, + counterparty_connection_id: Some(conn_id_on_a), + counterparty_client_id: client_id_on_a, + }) } - pub fn connection_id(&self) -> Option<&ConnectionId> { - self.0.connection_id.as_ref() - } -} -impl From for OpenTry { - fn from(attrs: Attributes) -> Self { - OpenTry(attrs) + pub fn connection_id(&self) -> &ConnectionId { + &self.0.connection_id } -} - -impl From for IbcEvent { - fn from(v: OpenTry) -> Self { - IbcEvent::OpenTryConnection(v) + pub fn client_id(&self) -> &ClientId { + &self.0.client_id + } + pub fn counterparty_connection_id(&self) -> Option<&ConnectionId> { + self.0.counterparty_connection_id.as_ref() + } + pub fn counterparty_client_id(&self) -> &ClientId { + &self.0.counterparty_client_id } } @@ -130,26 +150,35 @@ impl From for AbciEvent { } #[derive(Clone, Debug, PartialEq, Eq, Serialize)] -pub struct OpenAck(pub Attributes); +pub struct OpenAck(Attributes); impl OpenAck { - pub fn attributes(&self) -> &Attributes { - &self.0 + /// Per our convention, this event is generated on chain A. + pub fn new( + conn_id_on_a: ConnectionId, + client_id_on_a: ClientId, + conn_id_on_b: ConnectionId, + client_id_on_b: ClientId, + ) -> Self { + Self(Attributes { + connection_id: conn_id_on_a, + client_id: client_id_on_a, + counterparty_connection_id: Some(conn_id_on_b), + counterparty_client_id: client_id_on_b, + }) } - pub fn connection_id(&self) -> Option<&ConnectionId> { - self.0.connection_id.as_ref() - } -} -impl From for OpenAck { - fn from(attrs: Attributes) -> Self { - OpenAck(attrs) + pub fn connection_id(&self) -> &ConnectionId { + &self.0.connection_id } -} - -impl From for IbcEvent { - fn from(v: OpenAck) -> Self { - IbcEvent::OpenAckConnection(v) + pub fn client_id(&self) -> &ClientId { + &self.0.client_id + } + pub fn counterparty_connection_id(&self) -> Option<&ConnectionId> { + self.0.counterparty_connection_id.as_ref() + } + pub fn counterparty_client_id(&self) -> &ClientId { + &self.0.counterparty_client_id } } @@ -164,26 +193,35 @@ impl From for AbciEvent { } #[derive(Clone, Debug, PartialEq, Eq, Serialize)] -pub struct OpenConfirm(pub Attributes); +pub struct OpenConfirm(Attributes); impl OpenConfirm { - pub fn attributes(&self) -> &Attributes { - &self.0 - } - pub fn connection_id(&self) -> Option<&ConnectionId> { - self.0.connection_id.as_ref() - } -} - -impl From for OpenConfirm { - fn from(attrs: Attributes) -> Self { - OpenConfirm(attrs) - } -} - -impl From for IbcEvent { - fn from(v: OpenConfirm) -> Self { - IbcEvent::OpenConfirmConnection(v) + /// Per our convention, this event is generated on chain B. + pub fn new( + conn_id_on_b: ConnectionId, + client_id_on_b: ClientId, + conn_id_on_a: ConnectionId, + client_id_on_a: ClientId, + ) -> Self { + Self(Attributes { + connection_id: conn_id_on_b, + client_id: client_id_on_b, + counterparty_connection_id: Some(conn_id_on_a), + counterparty_client_id: client_id_on_a, + }) + } + + pub fn connection_id(&self) -> &ConnectionId { + &self.0.connection_id + } + pub fn client_id(&self) -> &ClientId { + &self.0.client_id + } + pub fn counterparty_connection_id(&self) -> Option<&ConnectionId> { + self.0.counterparty_connection_id.as_ref() + } + pub fn counterparty_client_id(&self) -> &ClientId { + &self.0.counterparty_client_id } } diff --git a/crates/ibc/src/core/ics03_connection/handler/conn_open_ack.rs b/crates/ibc/src/core/ics03_connection/handler/conn_open_ack.rs index ae6e39335..5f9e204df 100644 --- a/crates/ibc/src/core/ics03_connection/handler/conn_open_ack.rs +++ b/crates/ibc/src/core/ics03_connection/handler/conn_open_ack.rs @@ -3,7 +3,7 @@ use crate::core::ics03_connection::connection::{ConnectionEnd, Counterparty, State}; use crate::core::ics03_connection::context::ConnectionReader; use crate::core::ics03_connection::error::Error; -use crate::core::ics03_connection::events::Attributes; +use crate::core::ics03_connection::events::OpenAck; use crate::core::ics03_connection::handler::ConnectionResult; use crate::core::ics03_connection::msgs::conn_open_ack::MsgConnectionOpenAck; use crate::events::IbcEvent; @@ -38,6 +38,14 @@ pub(crate) fn process( return Err(Error::connection_mismatch(msg.conn_id_on_a)); } + let client_id_on_a = conn_end_on_a.client_id(); + let client_id_on_b = conn_end_on_a.counterparty().client_id(); + + let conn_id_on_b = conn_end_on_a + .counterparty() + .connection_id() + .ok_or_else(Error::invalid_counterparty)?; + // Proof verification. { let client_state_of_b_on_a = ctx_a.client_state(conn_end_on_a.client_id())?; @@ -46,14 +54,8 @@ pub(crate) fn process( let prefix_on_a = ctx_a.commitment_prefix(); let prefix_on_b = conn_end_on_a.counterparty().prefix(); - let client_id_on_a = conn_end_on_a.client_id(); - let client_id_on_b = conn_end_on_a.counterparty().client_id(); { - let conn_id_on_b = conn_end_on_a - .counterparty() - .connection_id() - .ok_or_else(Error::invalid_counterparty)?; let expected_conn_end_on_b = ConnectionEnd::new( State::TryOpen, client_id_on_b.clone(), @@ -107,6 +109,14 @@ pub(crate) fn process( } // Success + output.emit(IbcEvent::OpenAckConnection(OpenAck::new( + msg.conn_id_on_a.clone(), + client_id_on_a.clone(), + conn_id_on_b.clone(), + client_id_on_b.clone(), + ))); + output.log("success: conn_open_ack verification passed"); + let result = { let new_conn_end_on_a = { let mut counterparty = conn_end_on_a.counterparty().clone(); @@ -126,14 +136,6 @@ pub(crate) fn process( } }; - let event_attributes = Attributes { - connection_id: Some(result.connection_id.clone()), - ..Default::default() - }; - - output.emit(IbcEvent::OpenAckConnection(event_attributes.into())); - output.log("success: conn_open_ack verification passed"); - Ok(output.with_result(result)) } diff --git a/crates/ibc/src/core/ics03_connection/handler/conn_open_confirm.rs b/crates/ibc/src/core/ics03_connection/handler/conn_open_confirm.rs index 6a840893a..1e157b8ae 100644 --- a/crates/ibc/src/core/ics03_connection/handler/conn_open_confirm.rs +++ b/crates/ibc/src/core/ics03_connection/handler/conn_open_confirm.rs @@ -3,7 +3,7 @@ use crate::core::ics03_connection::connection::{ConnectionEnd, Counterparty, State}; use crate::core::ics03_connection::context::ConnectionReader; use crate::core::ics03_connection::error::Error; -use crate::core::ics03_connection::events::Attributes; +use crate::core::ics03_connection::events::OpenConfirm; use crate::core::ics03_connection::handler::{ConnectionIdState, ConnectionResult}; use crate::core::ics03_connection::msgs::conn_open_confirm::MsgConnectionOpenConfirm; use crate::events::IbcEvent; @@ -21,6 +21,12 @@ pub(crate) fn process( if !conn_end_on_b.state_matches(&State::TryOpen) { return Err(Error::connection_mismatch(msg.conn_id_on_b)); } + let client_id_on_a = conn_end_on_b.counterparty().client_id(); + let client_id_on_b = conn_end_on_b.client_id(); + let conn_id_on_a = conn_end_on_b + .counterparty() + .connection_id() + .ok_or_else(Error::invalid_counterparty)?; // Verify proofs { @@ -28,12 +34,6 @@ pub(crate) fn process( let consensus_state_of_a_on_b = ctx_b.client_consensus_state(conn_end_on_b.client_id(), msg.proof_height_on_a)?; - let client_id_on_a = conn_end_on_b.counterparty().client_id(); - let client_id_on_b = conn_end_on_b.client_id(); - let conn_id_on_a = conn_end_on_b - .counterparty() - .connection_id() - .ok_or_else(Error::invalid_counterparty)?; let prefix_on_a = conn_end_on_b.counterparty().prefix(); let prefix_on_b = ctx_b.commitment_prefix(); @@ -62,6 +62,14 @@ pub(crate) fn process( } // Success + output.emit(IbcEvent::OpenConfirmConnection(OpenConfirm::new( + msg.conn_id_on_b.clone(), + client_id_on_b.clone(), + conn_id_on_a.clone(), + client_id_on_a.clone(), + ))); + output.log("success: conn_open_confirm verification passed"); + let result = { let new_conn_end_on_b = { let mut new_conn_end_on_b = conn_end_on_b; @@ -77,14 +85,6 @@ pub(crate) fn process( } }; - let event_attributes = Attributes { - connection_id: Some(result.connection_id.clone()), - ..Default::default() - }; - - output.emit(IbcEvent::OpenConfirmConnection(event_attributes.into())); - output.log("success: conn_open_confirm verification passed"); - Ok(output.with_result(result)) } diff --git a/crates/ibc/src/core/ics03_connection/handler/conn_open_init.rs b/crates/ibc/src/core/ics03_connection/handler/conn_open_init.rs index dffe27493..6760e202a 100644 --- a/crates/ibc/src/core/ics03_connection/handler/conn_open_init.rs +++ b/crates/ibc/src/core/ics03_connection/handler/conn_open_init.rs @@ -3,7 +3,7 @@ use crate::core::ics03_connection::connection::{ConnectionEnd, State}; use crate::core::ics03_connection::context::ConnectionReader; use crate::core::ics03_connection::error::Error; -use crate::core::ics03_connection::events::Attributes; +use crate::core::ics03_connection::events::OpenInit; use crate::core::ics03_connection::handler::ConnectionResult; use crate::core::ics03_connection::msgs::conn_open_init::MsgConnectionOpenInit; use crate::core::ics24_host::identifier::ConnectionId; @@ -51,17 +51,21 @@ pub(crate) fn process( connection_id_state: ConnectionIdState::Generated, }; - let event_attributes = Attributes { - connection_id: Some(conn_id_on_a.clone()), - ..Default::default() - }; - - output.emit(IbcEvent::OpenInitConnection(event_attributes.into())); output.log(format!( "success: conn_open_init: generated new connection identifier: {}", conn_id_on_a )); + { + let client_id_on_b = msg.counterparty.client_id().clone(); + + output.emit(IbcEvent::OpenInitConnection(OpenInit::new( + conn_id_on_a, + msg.client_id_on_a, + client_id_on_b, + ))); + } + Ok(output.with_result(result)) } diff --git a/crates/ibc/src/core/ics03_connection/handler/conn_open_try.rs b/crates/ibc/src/core/ics03_connection/handler/conn_open_try.rs index e4f425935..545897de7 100644 --- a/crates/ibc/src/core/ics03_connection/handler/conn_open_try.rs +++ b/crates/ibc/src/core/ics03_connection/handler/conn_open_try.rs @@ -3,7 +3,7 @@ use crate::core::ics03_connection::connection::{ConnectionEnd, Counterparty, State}; use crate::core::ics03_connection::context::ConnectionReader; use crate::core::ics03_connection::error::Error; -use crate::core::ics03_connection::events::Attributes; +use crate::core::ics03_connection::events::OpenTry; use crate::core::ics03_connection::handler::ConnectionResult; use crate::core::ics03_connection::msgs::conn_open_try::MsgConnectionOpenTry; use crate::core::ics24_host::identifier::ConnectionId; @@ -48,21 +48,22 @@ pub(crate) fn process( msg.delay_period, ); + let client_id_on_a = msg.counterparty.client_id(); + let conn_id_on_a = conn_end_on_b + .counterparty() + .connection_id() + .ok_or_else(Error::invalid_counterparty)?; + // Verify proofs { let client_state_of_a_on_b = ctx_b.client_state(conn_end_on_b.client_id())?; let consensus_state_of_a_on_b = ctx_b.client_consensus_state(conn_end_on_b.client_id(), msg.proofs_height_on_a)?; - let client_id_on_a = msg.counterparty.client_id(); let prefix_on_a = conn_end_on_b.counterparty().prefix(); let prefix_on_b = ctx_b.commitment_prefix(); { - let conn_id_on_a = conn_end_on_b - .counterparty() - .connection_id() - .ok_or_else(Error::invalid_counterparty)?; let versions_on_a = msg.counterparty_versions; let expected_conn_end_on_a = ConnectionEnd::new( State::Init, @@ -113,20 +114,20 @@ pub(crate) fn process( } // Success + output.emit(IbcEvent::OpenTryConnection(OpenTry::new( + conn_id_on_b.clone(), + msg.client_id_on_b, + conn_id_on_a.clone(), + client_id_on_a.clone(), + ))); + output.log("success: conn_open_try verification passed"); + let result = ConnectionResult { - connection_id: conn_id_on_b.clone(), + connection_id: conn_id_on_b, connection_end: conn_end_on_b, connection_id_state: ConnectionIdState::Generated, }; - let event_attributes = Attributes { - connection_id: Some(conn_id_on_b), - ..Default::default() - }; - - output.emit(IbcEvent::OpenTryConnection(event_attributes.into())); - output.log("success: conn_open_try verification passed"); - Ok(output.with_result(result)) } diff --git a/crates/ibc/src/events.rs b/crates/ibc/src/events.rs index ca9b33718..9a7e4a552 100644 --- a/crates/ibc/src/events.rs +++ b/crates/ibc/src/events.rs @@ -11,7 +11,6 @@ use crate::core::ics02_client::error as client_error; use crate::core::ics02_client::events::{self as ClientEvents}; use crate::core::ics03_connection::error as connection_error; use crate::core::ics03_connection::events as ConnectionEvents; -use crate::core::ics03_connection::events::Attributes as ConnectionAttributes; use crate::core::ics04_channel::error as channel_error; use crate::core::ics04_channel::events as ChannelEvents; use crate::core::ics04_channel::events::Attributes as ChannelAttributes; @@ -303,16 +302,6 @@ impl IbcEvent { } } - pub fn connection_attributes(&self) -> Option<&ConnectionAttributes> { - match self { - IbcEvent::OpenInitConnection(ev) => Some(ev.attributes()), - IbcEvent::OpenTryConnection(ev) => Some(ev.attributes()), - IbcEvent::OpenAckConnection(ev) => Some(ev.attributes()), - IbcEvent::OpenConfirmConnection(ev) => Some(ev.attributes()), - _ => None, - } - } - pub fn packet(&self) -> Option<&Packet> { match self { IbcEvent::SendPacket(ev) => Some(&ev.packet),