diff --git a/.changelog/unreleased/improvements/ibc-relayer/4098-deserialize-ics20-v2-packet-data-with-protobuf.md b/.changelog/unreleased/improvements/ibc-relayer/4098-deserialize-ics20-v2-packet-data-with-protobuf.md new file mode 100644 index 0000000000..96cc10baa8 --- /dev/null +++ b/.changelog/unreleased/improvements/ibc-relayer/4098-deserialize-ics20-v2-packet-data-with-protobuf.md @@ -0,0 +1,2 @@ +- Deserialize ICS20 v2 packet data using Protobuf instead of JSON + ([\#4098](https://github.com/informalsystems/hermes/issues/4098)) \ No newline at end of file diff --git a/crates/relayer/src/link.rs b/crates/relayer/src/link.rs index 3d87499480..e264a590e3 100644 --- a/crates/relayer/src/link.rs +++ b/crates/relayer/src/link.rs @@ -145,6 +145,21 @@ impl Link { )); } + // Query the channel if it exists in order to retrieve the channel version. + // If the channel doesn't exist or the query fails, set the version to None. + let maybe_channel_a = a_chain.query_channel( + QueryChannelRequest { + port_id: opts.src_port_id.clone(), + channel_id: opts.src_channel_id.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::Yes, + ); + let channel_version = match maybe_channel_a { + Ok((channel_a, _)) => Some(channel_a.version), + Err(_) => None, + }; + let channel = Channel { ordering: a_channel.ordering, a_side: ChannelSide::new( @@ -153,7 +168,7 @@ impl Link { a_connection_id, opts.src_port_id.clone(), Some(opts.src_channel_id.clone()), - None, + channel_version.clone(), ), b_side: ChannelSide::new( b_chain.clone(), @@ -161,7 +176,7 @@ impl Link { a_connection.counterparty().connection_id().unwrap().clone(), a_channel.counterparty().port_id.clone(), Some(b_channel_id.clone()), - None, + channel_version, ), connection_delay: a_connection.delay_period(), }; diff --git a/crates/relayer/src/link/relay_path.rs b/crates/relayer/src/link/relay_path.rs index bb1d917540..02af243b21 100644 --- a/crates/relayer/src/link/relay_path.rs +++ b/crates/relayer/src/link/relay_path.rs @@ -2,13 +2,15 @@ use alloc::collections::BTreeMap as HashMap; use alloc::collections::VecDeque; use ibc_relayer_types::core::ics04_channel::packet::Sequence; use ibc_relayer_types::core::ics04_channel::version::Version; +use prost::Message; +use serde::de::Error as _; use serde_json::Error; use std::ops::Sub; use std::time::{Duration, Instant}; use ibc_proto::google::protobuf::Any; -use ibc_proto::ibc::applications::transfer::v2::FungibleTokenPacketData as RawPacketData; -use ibc_proto::ibc::applications::transfer::v2::FungibleTokenPacketDataV2 as RawPacketDataV2; +use ibc_proto::ibc::applications::transfer::v2::FungibleTokenPacketData; +use ibc_proto::ibc::applications::transfer::v2::FungibleTokenPacketDataV2; use itertools::Itertools; use tracing::{debug, error, info, span, trace, warn, Level}; @@ -2020,12 +2022,12 @@ fn extract_memo_and_receiver( data: &[u8], ) -> Result<(String, String), Error> { if channel_version.is_ics20_v2() { - match serde_json::from_slice::(data) { + match FungibleTokenPacketDataV2::decode(data) { Ok(packet_data) => Ok((packet_data.memo, packet_data.receiver)), - Err(e) => Err(e), + Err(e) => Err(Error::custom(e.to_string())), } } else { - match serde_json::from_slice::(data) { + match serde_json::from_slice::(data) { Ok(packet_data) => Ok((packet_data.memo, packet_data.receiver)), Err(e) => Err(e), } diff --git a/tools/integration-test/src/tests/ics20_filter/memo.rs b/tools/integration-test/src/tests/ics20_filter/memo.rs index e46fad7ff0..f02da4bbf5 100644 --- a/tools/integration-test/src/tests/ics20_filter/memo.rs +++ b/tools/integration-test/src/tests/ics20_filter/memo.rs @@ -1,16 +1,26 @@ use byte_unit::Byte; -use ibc_relayer::config::types::ics20_field_size_limit::Ics20FieldSizeLimit; +use ibc_relayer::{ + channel::version::Version, config::types::ics20_field_size_limit::Ics20FieldSizeLimit, +}; use ibc_test_framework::prelude::*; #[test] fn test_memo_filter() -> Result<(), Error> { - run_binary_channel_test(&IbcMemoFilterTest) + run_binary_channel_test(&IbcMemoFilterTest { ics20_version: 1 }) +} + +#[cfg(any(doc, feature = "ics20-v2"))] +#[test] +fn test_memo_filter_ics20_v2() -> Result<(), Error> { + run_binary_channel_test(&IbcMemoFilterTest { ics20_version: 2 }) } const MEMO_SIZE_LIMIT: usize = 2000; -pub struct IbcMemoFilterTest; +pub struct IbcMemoFilterTest { + pub ics20_version: u64, +} impl TestOverrides for IbcMemoFilterTest { fn modify_relayer_config(&self, config: &mut Config) { @@ -19,6 +29,10 @@ impl TestOverrides for IbcMemoFilterTest { config.mode.clients.misbehaviour = false; } + + fn channel_version(&self) -> Version { + Version::ics20(self.ics20_version) + } } impl BinaryChannelTest for IbcMemoFilterTest {