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

abci::CheckTx equivalent for IBC module #1203

Merged
merged 5 commits into from
Jul 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()),
}
}
}