Skip to content

Commit

Permalink
abci::CheckTx equivalent for IBC module (#1203)
Browse files Browse the repository at this point in the history
* Impl TryFrom<Any> for Ics26Envelope

* Add decode()

* Use decode() in deliver()

* Update CHANGELOG.md

Co-authored-by: Adi Seredinschi <adi@informal.systems>
  • Loading branch information
hu55a1n1 and adizere authored Jul 20, 2021
1 parent cbdfef2 commit b61f677
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 125 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

- [ibc]
- Enable `pub` access to verification methods of ICS 03 & 04 ([#1198])
- Add `ics26_routing::handler::decode` function ([#1194])

- [ibc-relayer-cli]
- Added `upgrade-clients` CLI ([#763])
Expand All @@ -28,9 +29,11 @@
[#1094]: https://github.com/informalsystems/ibc-rs/issues/1094
[#1114]: https://github.com/informalsystems/ibc-rs/issues/1114
[#1192]: https://github.com/informalsystems/ibc-rs/issues/1192
[#1194]: https://github.com/informalsystems/ibc-rs/issues/1194
[#1198]: https://github.com/informalsystems/ibc-rs/issues/1198
[#1200]: https://github.com/informalsystems/ibc-rs/issues/1200


## v0.6.0
*July 12th, 2021*

Expand Down
129 changes: 8 additions & 121 deletions modules/src/ics26_routing/handler.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,17 @@
use core::convert::TryInto;
use prost_types::Any;
use tendermint_proto::Protobuf;

use crate::application::ics20_fungible_token_transfer::msgs::transfer;
use crate::application::ics20_fungible_token_transfer::relay_application_logic::send_transfer::send_transfer as ics20_msg_dispatcher;
use crate::ics02_client::handler::dispatch as ics2_msg_dispatcher;
use crate::ics02_client::msgs::{create_client, update_client, upgrade_client, ClientMsg};
use crate::ics03_connection::handler::dispatch as ics3_msg_dispatcher;
use crate::ics03_connection::msgs::{
conn_open_ack, conn_open_confirm, conn_open_init, conn_open_try, ConnectionMsg,
};
use crate::ics04_channel::handler::channel_dispatch as ics4_msg_dispatcher;
use crate::ics04_channel::handler::packet_dispatch as ics04_packet_msg_dispatcher;
use crate::{events::IbcEvent, handler::HandlerOutput};

use crate::ics04_channel::msgs::{
acknowledgement, chan_close_confirm, chan_close_init, chan_open_ack, chan_open_confirm,
chan_open_init, chan_open_try, recv_packet, timeout, timeout_on_close, ChannelMsg, PacketMsg,
};
use crate::ics26_routing::context::Ics26Context;
use crate::ics26_routing::error::{Error, Kind};
use crate::ics26_routing::msgs::Ics26Envelope::{
self, Ics20Msg, Ics2Msg, Ics3Msg, Ics4ChannelMsg, Ics4PacketMsg,
};
use crate::{events::IbcEvent, handler::HandlerOutput};

/// Mimics the DeliverTx ABCI interface, but a slightly lower level. No need for authentication
/// info or signature checks here.
Expand All @@ -40,115 +30,7 @@ where

for any_msg in messages {
// Decode the proto message into a domain message, creating an ICS26 envelope.
let envelope = match any_msg.type_url.as_str() {
// ICS2 messages
create_client::TYPE_URL => {
// Pop out the message and then wrap it in the corresponding type.
let domain_msg = create_client::MsgCreateAnyClient::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics2Msg(ClientMsg::CreateClient(domain_msg)))
}
update_client::TYPE_URL => {
let domain_msg = update_client::MsgUpdateAnyClient::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics2Msg(ClientMsg::UpdateClient(domain_msg)))
}
upgrade_client::TYPE_URL => {
let domain_msg = upgrade_client::MsgUpgradeAnyClient::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics2Msg(ClientMsg::UpgradeClient(domain_msg)))
}

// ICS03
conn_open_init::TYPE_URL => {
let domain_msg = conn_open_init::MsgConnectionOpenInit::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics3Msg(ConnectionMsg::ConnectionOpenInit(domain_msg)))
}
conn_open_try::TYPE_URL => {
let domain_msg = conn_open_try::MsgConnectionOpenTry::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics3Msg(ConnectionMsg::ConnectionOpenTry(Box::new(
domain_msg,
))))
}
conn_open_ack::TYPE_URL => {
let domain_msg = conn_open_ack::MsgConnectionOpenAck::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics3Msg(ConnectionMsg::ConnectionOpenAck(Box::new(
domain_msg,
))))
}
conn_open_confirm::TYPE_URL => {
let domain_msg =
conn_open_confirm::MsgConnectionOpenConfirm::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics3Msg(ConnectionMsg::ConnectionOpenConfirm(domain_msg)))
}

// ICS04 channel messages
chan_open_init::TYPE_URL => {
let domain_msg = chan_open_init::MsgChannelOpenInit::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics4ChannelMsg(ChannelMsg::ChannelOpenInit(domain_msg)))
}
chan_open_try::TYPE_URL => {
let domain_msg = chan_open_try::MsgChannelOpenTry::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics4ChannelMsg(ChannelMsg::ChannelOpenTry(domain_msg)))
}
chan_open_ack::TYPE_URL => {
let domain_msg = chan_open_ack::MsgChannelOpenAck::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics4ChannelMsg(ChannelMsg::ChannelOpenAck(domain_msg)))
}
chan_open_confirm::TYPE_URL => {
let domain_msg =
chan_open_confirm::MsgChannelOpenConfirm::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics4ChannelMsg(ChannelMsg::ChannelOpenConfirm(domain_msg)))
}
chan_close_init::TYPE_URL => {
let domain_msg = chan_close_init::MsgChannelCloseInit::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics4ChannelMsg(ChannelMsg::ChannelCloseInit(domain_msg)))
}
chan_close_confirm::TYPE_URL => {
let domain_msg =
chan_close_confirm::MsgChannelCloseConfirm::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics4ChannelMsg(ChannelMsg::ChannelCloseConfirm(domain_msg)))
}
// ICS20 - 04 - Send packet
transfer::TYPE_URL => {
let domain_msg = transfer::MsgTransfer::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics20Msg(domain_msg))
}
// ICS04 packet messages
recv_packet::TYPE_URL => {
let domain_msg = recv_packet::MsgRecvPacket::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics4PacketMsg(PacketMsg::RecvPacket(domain_msg)))
}
acknowledgement::TYPE_URL => {
let domain_msg = acknowledgement::MsgAcknowledgement::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics4PacketMsg(PacketMsg::AckPacket(domain_msg)))
}
timeout::TYPE_URL => {
let domain_msg = timeout::MsgTimeout::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics4PacketMsg(PacketMsg::ToPacket(domain_msg)))
}
timeout_on_close::TYPE_URL => {
let domain_msg = timeout_on_close::MsgTimeoutOnClose::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics4PacketMsg(PacketMsg::ToClosePacket(domain_msg)))
}

_ => Err(Kind::UnknownMessageTypeUrl(any_msg.type_url)),
}?;
let envelope = decode(any_msg)?;

// Process the envelope, and accumulate any events that were generated.
let mut output = dispatch(&mut ctx_interim, envelope)?;
Expand All @@ -161,6 +43,11 @@ where
Ok(res)
}

/// Attempts to convert a message into a [Ics26Envelope] message
pub fn decode(message: Any) -> Result<Ics26Envelope, Error> {
message.try_into()
}

/// Top-level ICS dispatch function. Routes incoming IBC messages to their corresponding module.
/// Returns a handler output with empty result of type `HandlerOutput<()>` which contains the log
/// and events produced after processing the input `msg`.
Expand Down
158 changes: 154 additions & 4 deletions modules/src/ics26_routing/msgs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
use crate::application::ics20_fungible_token_transfer::msgs::transfer::MsgTransfer;
use crate::ics02_client::msgs::ClientMsg;
use crate::ics04_channel::msgs::ChannelMsg;
use crate::{ics03_connection::msgs::ConnectionMsg, ics04_channel::msgs::PacketMsg};
use core::convert::TryFrom;
use prost_types::Any;

use crate::application::ics20_fungible_token_transfer::msgs::{transfer, transfer::MsgTransfer};
use crate::ics02_client::msgs::{create_client, update_client, upgrade_client, ClientMsg};
use crate::ics03_connection::msgs::{
conn_open_ack, conn_open_confirm, conn_open_init, conn_open_try, ConnectionMsg,
};
use crate::ics04_channel::msgs::{
acknowledgement, chan_close_confirm, chan_close_init, chan_open_ack, chan_open_confirm,
chan_open_init, chan_open_try, recv_packet, timeout, timeout_on_close, ChannelMsg, PacketMsg,
};
use crate::ics26_routing::error::{Error, Kind};
use tendermint_proto::Protobuf;

/// Enumeration of all messages that the local ICS26 module is capable of routing.
#[derive(Clone, Debug)]
Expand All @@ -12,3 +22,143 @@ pub enum Ics26Envelope {
Ics4PacketMsg(PacketMsg),
Ics20Msg(MsgTransfer),
}

impl TryFrom<Any> for Ics26Envelope {
type Error = Error;

fn try_from(any_msg: Any) -> Result<Self, Self::Error> {
match any_msg.type_url.as_str() {
// ICS2 messages
create_client::TYPE_URL => {
// Pop out the message and then wrap it in the corresponding type.
let domain_msg = create_client::MsgCreateAnyClient::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics2Msg(ClientMsg::CreateClient(domain_msg)))
}
update_client::TYPE_URL => {
let domain_msg = update_client::MsgUpdateAnyClient::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics2Msg(ClientMsg::UpdateClient(domain_msg)))
}
upgrade_client::TYPE_URL => {
let domain_msg = upgrade_client::MsgUpgradeAnyClient::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics2Msg(ClientMsg::UpgradeClient(domain_msg)))
}

// ICS03
conn_open_init::TYPE_URL => {
let domain_msg = conn_open_init::MsgConnectionOpenInit::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics3Msg(ConnectionMsg::ConnectionOpenInit(
domain_msg,
)))
}
conn_open_try::TYPE_URL => {
let domain_msg = conn_open_try::MsgConnectionOpenTry::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics3Msg(ConnectionMsg::ConnectionOpenTry(
Box::new(domain_msg),
)))
}
conn_open_ack::TYPE_URL => {
let domain_msg = conn_open_ack::MsgConnectionOpenAck::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics3Msg(ConnectionMsg::ConnectionOpenAck(
Box::new(domain_msg),
)))
}
conn_open_confirm::TYPE_URL => {
let domain_msg =
conn_open_confirm::MsgConnectionOpenConfirm::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics3Msg(
ConnectionMsg::ConnectionOpenConfirm(domain_msg),
))
}

// ICS04 channel messages
chan_open_init::TYPE_URL => {
let domain_msg = chan_open_init::MsgChannelOpenInit::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics4ChannelMsg(ChannelMsg::ChannelOpenInit(
domain_msg,
)))
}
chan_open_try::TYPE_URL => {
let domain_msg = chan_open_try::MsgChannelOpenTry::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics4ChannelMsg(ChannelMsg::ChannelOpenTry(
domain_msg,
)))
}
chan_open_ack::TYPE_URL => {
let domain_msg = chan_open_ack::MsgChannelOpenAck::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics4ChannelMsg(ChannelMsg::ChannelOpenAck(
domain_msg,
)))
}
chan_open_confirm::TYPE_URL => {
let domain_msg =
chan_open_confirm::MsgChannelOpenConfirm::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics4ChannelMsg(
ChannelMsg::ChannelOpenConfirm(domain_msg),
))
}
chan_close_init::TYPE_URL => {
let domain_msg = chan_close_init::MsgChannelCloseInit::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics4ChannelMsg(ChannelMsg::ChannelCloseInit(
domain_msg,
)))
}
chan_close_confirm::TYPE_URL => {
let domain_msg =
chan_close_confirm::MsgChannelCloseConfirm::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics4ChannelMsg(
ChannelMsg::ChannelCloseConfirm(domain_msg),
))
}
// ICS20 - 04 - Send packet
transfer::TYPE_URL => {
let domain_msg = transfer::MsgTransfer::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics20Msg(domain_msg))
}
// ICS04 packet messages
recv_packet::TYPE_URL => {
let domain_msg = recv_packet::MsgRecvPacket::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics4PacketMsg(PacketMsg::RecvPacket(
domain_msg,
)))
}
acknowledgement::TYPE_URL => {
let domain_msg = acknowledgement::MsgAcknowledgement::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics4PacketMsg(PacketMsg::AckPacket(
domain_msg,
)))
}
timeout::TYPE_URL => {
let domain_msg = timeout::MsgTimeout::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics4PacketMsg(PacketMsg::ToPacket(
domain_msg,
)))
}
timeout_on_close::TYPE_URL => {
let domain_msg = timeout_on_close::MsgTimeoutOnClose::decode_vec(&any_msg.value)
.map_err(|e| Kind::MalformedMessageBytes.context(e))?;
Ok(Ics26Envelope::Ics4PacketMsg(PacketMsg::ToClosePacket(
domain_msg,
)))
}

_ => Err(Kind::UnknownMessageTypeUrl(any_msg.type_url).into()),
}
}
}

0 comments on commit b61f677

Please sign in to comment.