diff --git a/.changelog/unreleased/improvements/163-verify-ibc-to-abci-event.md b/.changelog/unreleased/improvements/163-verify-ibc-to-abci-event.md new file mode 100644 index 000000000..34de06b1d --- /dev/null +++ b/.changelog/unreleased/improvements/163-verify-ibc-to-abci-event.md @@ -0,0 +1,2 @@ +- Add tests to verify `AbciEvent` match the expected Ibc events +([#163](https://github.com/cosmos/ibc-rs/issues/163)). \ No newline at end of file diff --git a/crates/ibc/src/core/ics02_client/events.rs b/crates/ibc/src/core/ics02_client/events.rs index f5c15e063..a3237b609 100644 --- a/crates/ibc/src/core/ics02_client/events.rs +++ b/crates/ibc/src/core/ics02_client/events.rs @@ -390,3 +390,96 @@ impl From for abci::Event { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::header::MockHeader; + use crate::timestamp::Timestamp; + use ibc_proto::google::protobuf::Any; + use tendermint::abci::Event as AbciEvent; + + #[test] + fn ibc_to_abci_client_events() { + struct Test { + kind: IbcEventType, + event: AbciEvent, + expected_keys: Vec<&'static str>, + expected_values: Vec<&'static str>, + } + + let client_type = ClientType::new("07-tendermint".to_string()); + let client_id = ClientId::new(client_type.clone(), 0).unwrap(); + let consensus_height = Height::new(0, 5).unwrap(); + let consensus_heights = vec![Height::new(0, 5).unwrap(), Height::new(0, 7).unwrap()]; + let header: Any = MockHeader::new(consensus_height) + .with_timestamp(Timestamp::none()) + .into(); + let expected_keys = vec![ + "client_id", + "client_type", + "consensus_height", + "consensus_heights", + "header", + ]; + + let expected_values = vec![ + "07-tendermint-0", + "07-tendermint", + "0-5", + "0-5,0-7", + "0a021005", + ]; + + let tests: Vec = vec![ + Test { + kind: IbcEventType::CreateClient, + event: CreateClient::new(client_id.clone(), client_type.clone(), consensus_height) + .into(), + expected_keys: expected_keys[0..3].to_vec(), + expected_values: expected_values[0..3].to_vec(), + }, + Test { + kind: IbcEventType::UpdateClient, + event: UpdateClient::new( + client_id.clone(), + client_type.clone(), + consensus_height, + consensus_heights, + header, + ) + .into(), + expected_keys: expected_keys.clone(), + expected_values: expected_values.clone(), + }, + Test { + kind: IbcEventType::UpgradeClient, + event: UpgradeClient::new(client_id.clone(), client_type.clone(), consensus_height) + .into(), + expected_keys: expected_keys[0..3].to_vec(), + expected_values: expected_values[0..3].to_vec(), + }, + Test { + kind: IbcEventType::ClientMisbehaviour, + event: ClientMisbehaviour::new(client_id, client_type).into(), + expected_keys: expected_keys[0..2].to_vec(), + expected_values: expected_values[0..2].to_vec(), + }, + ]; + + for t in tests { + assert_eq!(t.event.kind, t.kind.as_str()); + assert_eq!(t.expected_keys.len(), t.event.attributes.len()); + for (i, e) in t.event.attributes.iter().enumerate() { + assert_eq!(e.key, t.expected_keys[i], "key mismatch for {:?}", t.kind); + } + for (i, e) in t.event.attributes.iter().enumerate() { + assert_eq!( + e.value, t.expected_values[i], + "value mismatch for {:?}", + t.kind + ); + } + } + } +} diff --git a/crates/ibc/src/core/ics03_connection/events.rs b/crates/ibc/src/core/ics03_connection/events.rs index ff26875c2..d25558e43 100644 --- a/crates/ibc/src/core/ics03_connection/events.rs +++ b/crates/ibc/src/core/ics03_connection/events.rs @@ -281,3 +281,108 @@ impl From for abci::Event { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::core::ics02_client::client_type::ClientType; + use tendermint::abci::Event as AbciEvent; + + #[test] + fn ibc_to_abci_connection_events() { + struct Test { + kind: IbcEventType, + event: AbciEvent, + expected_keys: Vec<&'static str>, + expected_values: Vec<&'static str>, + } + + let client_type = ClientType::new("07-tendermint".to_string()); + let conn_id_on_a = ConnectionId::default(); + let client_id_on_a = ClientId::new(client_type.clone(), 0).unwrap(); + let conn_id_on_b = ConnectionId::new(1); + let client_id_on_b = ClientId::new(client_type, 1).unwrap(); + let expected_keys = vec![ + "connection_id", + "client_id", + "counterparty_client_id", + "counterparty_connection_id", + ]; + let expected_values = vec![ + "connection-0", + "07-tendermint-0", + "07-tendermint-1", + "connection-1", + ]; + + let tests: Vec = vec![ + Test { + kind: IbcEventType::OpenInitConnection, + event: OpenInit::new( + conn_id_on_a.clone(), + client_id_on_a.clone(), + client_id_on_b.clone(), + ) + .into(), + expected_keys: expected_keys.clone(), + expected_values: expected_values + .iter() + .enumerate() + .map(|(i, v)| if i == 3 { "" } else { v }) + .collect(), + }, + Test { + kind: IbcEventType::OpenTryConnection, + event: OpenTry::new( + conn_id_on_b.clone(), + client_id_on_b.clone(), + conn_id_on_a.clone(), + client_id_on_a.clone(), + ) + .into(), + expected_keys: expected_keys.clone(), + expected_values: expected_values.iter().rev().cloned().collect(), + }, + Test { + kind: IbcEventType::OpenAckConnection, + event: OpenAck::new( + conn_id_on_a.clone(), + client_id_on_a.clone(), + conn_id_on_b.clone(), + client_id_on_b.clone(), + ) + .into(), + expected_keys: expected_keys.clone(), + expected_values: expected_values.clone(), + }, + Test { + kind: IbcEventType::OpenConfirmConnection, + event: OpenConfirm::new(conn_id_on_b, client_id_on_b, conn_id_on_a, client_id_on_a) + .into(), + expected_keys: expected_keys.clone(), + expected_values: expected_values.iter().rev().cloned().collect(), + }, + ]; + + for t in tests { + assert_eq!(t.kind.as_str(), t.event.kind); + assert_eq!(t.expected_keys.len(), t.event.attributes.len()); + for (i, e) in t.event.attributes.iter().enumerate() { + assert_eq!( + e.key, + t.expected_keys[i], + "key mismatch for {:?}", + t.kind.as_str() + ); + } + for (i, e) in t.event.attributes.iter().enumerate() { + assert_eq!( + e.value, + t.expected_values[i], + "value mismatch for {:?}", + t.kind.as_str() + ); + } + } + } +} diff --git a/crates/ibc/src/core/ics04_channel/events.rs b/crates/ibc/src/core/ics04_channel/events.rs index bb214128d..77e531836 100644 --- a/crates/ibc/src/core/ics04_channel/events.rs +++ b/crates/ibc/src/core/ics04_channel/events.rs @@ -1058,3 +1058,150 @@ impl TryFrom for abci::Event { }) } } + +#[cfg(test)] +mod tests { + use super::*; + use tendermint::abci::Event as AbciEvent; + + #[test] + fn ibc_to_abci_channel_events() { + struct Test { + kind: IbcEventType, + event: AbciEvent, + expected_keys: Vec<&'static str>, + expected_values: Vec<&'static str>, + } + + let port_id = PortId::transfer(); + let channel_id = ChannelId::new(0); + let connection_id = ConnectionId::new(0); + let counterparty_port_id = PortId::transfer(); + let counterparty_channel_id = ChannelId::new(1); + let version = Version::new("ics20-1".to_string()); + let expected_keys = vec![ + "port_id", + "channel_id", + "counterparty_port_id", + "counterparty_channel_id", + "connection_id", + "version", + ]; + let expected_values = vec![ + "transfer", + "channel-0", + "transfer", + "channel-1", + "connection-0", + "ics20-1", + ]; + + let tests: Vec = vec![ + Test { + kind: IbcEventType::OpenInitChannel, + event: OpenInit::new( + port_id.clone(), + channel_id.clone(), + counterparty_port_id.clone(), + connection_id.clone(), + version.clone(), + ) + .into(), + expected_keys: expected_keys.clone(), + expected_values: expected_values + .iter() + .enumerate() + .map(|(i, v)| if i == 3 { "" } else { v }) + .collect(), + }, + Test { + kind: IbcEventType::OpenTryChannel, + event: OpenTry::new( + port_id.clone(), + channel_id.clone(), + counterparty_port_id.clone(), + counterparty_channel_id.clone(), + connection_id.clone(), + version, + ) + .into(), + expected_keys: expected_keys.clone(), + expected_values: expected_values.clone(), + }, + Test { + kind: IbcEventType::OpenAckChannel, + event: OpenAck::new( + port_id.clone(), + channel_id.clone(), + counterparty_port_id.clone(), + counterparty_channel_id.clone(), + connection_id.clone(), + ) + .into(), + expected_keys: expected_keys[0..5].to_vec(), + expected_values: expected_values[0..5].to_vec(), + }, + Test { + kind: IbcEventType::OpenConfirmChannel, + event: OpenConfirm::new( + port_id.clone(), + channel_id.clone(), + counterparty_port_id.clone(), + counterparty_channel_id.clone(), + connection_id.clone(), + ) + .into(), + expected_keys: expected_keys[0..5].to_vec(), + expected_values: expected_values[0..5].to_vec(), + }, + Test { + kind: IbcEventType::CloseInitChannel, + event: CloseInit::new( + port_id.clone(), + channel_id.clone(), + counterparty_port_id.clone(), + counterparty_channel_id.clone(), + connection_id.clone(), + ) + .into(), + expected_keys: expected_keys[0..5].to_vec(), + expected_values: expected_values[0..5].to_vec(), + }, + Test { + kind: IbcEventType::CloseConfirmChannel, + event: CloseConfirm::new( + port_id, + channel_id, + counterparty_port_id, + counterparty_channel_id, + connection_id, + ) + .into(), + expected_keys: expected_keys[0..5].to_vec(), + expected_values: expected_values[0..5].to_vec(), + }, + ]; + + for t in tests { + assert_eq!(t.kind.as_str(), t.event.kind); + assert_eq!(t.expected_keys.len(), t.event.attributes.len()); + for (i, e) in t.event.attributes.iter().enumerate() { + assert_eq!( + e.key, + t.expected_keys[i], + "key mismatch for {:?}", + t.kind.as_str() + ); + } + assert_eq!(t.expected_values.len(), t.event.attributes.len()); + for (i, e) in t.event.attributes.iter().enumerate() { + assert_eq!( + e.value, + t.expected_values[i], + "value mismatch for {:?}", + t.kind.as_str() + ); + } + } + } +} diff --git a/crates/ibc/src/core/ics04_channel/events/channel_attributes.rs b/crates/ibc/src/core/ics04_channel/events/channel_attributes.rs index 05f75e2ef..e858527bb 100644 --- a/crates/ibc/src/core/ics04_channel/events/channel_attributes.rs +++ b/crates/ibc/src/core/ics04_channel/events/channel_attributes.rs @@ -13,9 +13,10 @@ const CHANNEL_ID_ATTRIBUTE_KEY: &str = "channel_id"; const PORT_ID_ATTRIBUTE_KEY: &str = "port_id"; /// This attribute key is public so that OpenInit can use it to convert itself /// to an `AbciEvent` -pub const COUNTERPARTY_CHANNEL_ID_ATTRIBUTE_KEY: &str = "counterparty_channel_id"; +pub(super) const COUNTERPARTY_CHANNEL_ID_ATTRIBUTE_KEY: &str = "counterparty_channel_id"; const COUNTERPARTY_PORT_ID_ATTRIBUTE_KEY: &str = "counterparty_port_id"; const VERSION_ATTRIBUTE_KEY: &str = "version"; + #[cfg_attr( feature = "parity-scale-codec", derive(