Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make connection events compatible with ibc-go #191

Merged
merged 13 commits into from
Oct 26, 2022
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Make connection events compatible with ibc-go
([#145](https://github.com/cosmos/ibc-rs/issues/145))
206 changes: 122 additions & 84 deletions crates/ibc/src/core/ics03_connection/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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<ConnectionId>,
struct Attributes {
pub connection_id: ConnectionId,
pub client_id: ClientId,
pub counterparty_connection_id: Option<ConnectionId>,
pub counterparty_client_id: ClientId,
Expand All @@ -32,56 +32,67 @@ pub struct Attributes {
/// we will be able to remove the `.parse().unwrap()` calls.
impl From<Attributes> for Vec<Tag> {
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(),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: opened this issue in tendermint-rs to eventually clean up the .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<Attributes> for OpenInit {
fn from(attrs: Attributes) -> Self {
OpenInit(attrs)
pub fn connection_id(&self) -> &ConnectionId {
&self.0.connection_id
}
}

impl From<OpenInit> 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
}
}

Expand All @@ -96,26 +107,35 @@ impl From<OpenInit> 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<Attributes> for OpenTry {
fn from(attrs: Attributes) -> Self {
OpenTry(attrs)
pub fn connection_id(&self) -> &ConnectionId {
&self.0.connection_id
}
}

impl From<OpenTry> 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
}
}

Expand All @@ -130,26 +150,35 @@ impl From<OpenTry> 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<Attributes> for OpenAck {
fn from(attrs: Attributes) -> Self {
OpenAck(attrs)
pub fn connection_id(&self) -> &ConnectionId {
&self.0.connection_id
}
}

impl From<OpenAck> 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
}
}

Expand All @@ -164,26 +193,35 @@ impl From<OpenAck> 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<Attributes> for OpenConfirm {
fn from(attrs: Attributes) -> Self {
OpenConfirm(attrs)
}
}

impl From<OpenConfirm> 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
}
}

Expand Down
32 changes: 17 additions & 15 deletions crates/ibc/src/core/ics03_connection/handler/conn_open_ack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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())?;
Expand All @@ -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(),
Expand Down Expand Up @@ -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();
Expand All @@ -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))
}

Expand Down
Loading