Skip to content

Commit

Permalink
Derive borsh for MsgEnvelope (#846)
Browse files Browse the repository at this point in the history
* Add BorshSerialize/Deserialize to MsgEnvelope

* add tests

* changelog
  • Loading branch information
plafer authored Sep 1, 2023
1 parent 1833df5 commit 2c28380
Show file tree
Hide file tree
Showing 24 changed files with 274 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Add borsh derive for `MsgEnvelope`
([#846](https://github.com/cosmos/ibc-rs/pull/846))
4 changes: 4 additions & 0 deletions crates/ibc/src/core/ics02_client/msgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ pub mod upgrade_client;

/// Encodes all the different client messages
#[allow(dead_code)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug)]
pub enum ClientMsg {
CreateClient(MsgCreateClient),
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/core/ics02_client/msgs/create_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ use crate::signer::Signer;
pub(crate) const TYPE_URL: &str = "/ibc.core.client.v1.MsgCreateClient";

/// A type of message that triggers the creation of a new on-chain (IBC) client.
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MsgCreateClient {
pub client_state: Any,
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/core/ics02_client/msgs/misbehaviour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ use crate::signer::Signer;
pub(crate) const TYPE_URL: &str = "/ibc.core.client.v1.MsgSubmitMisbehaviour";

/// A type of message that submits client misbehaviour proof.
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MsgSubmitMisbehaviour {
/// client unique identifier
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/core/ics02_client/msgs/update_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ pub(crate) const TYPE_URL: &str = "/ibc.core.client.v1.MsgUpdateClient";
/// either with new headers, or evidence of misbehaviour.
/// Note that some types of misbehaviour can be detected when a headers
/// are updated (`UpdateKind::UpdateClient`).
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MsgUpdateClient {
pub client_id: ClientId,
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/core/ics02_client/msgs/upgrade_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ use crate::signer::Signer;
pub(crate) const TYPE_URL: &str = "/ibc.core.client.v1.MsgUpgradeClient";

/// A type of message that triggers the upgrade of an on-chain (IBC) client.
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq)]
pub struct MsgUpgradeClient {
// client unique identifier
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/core/ics03_connection/msgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ pub mod conn_open_init;
pub mod conn_open_try;

/// Enumeration of all possible messages that the ICS3 protocol processes.
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ConnectionMsg {
OpenInit(MsgConnectionOpenInit),
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/core/ics03_connection/msgs/conn_open_ack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ pub(crate) const TYPE_URL: &str = "/ibc.core.connection.v1.MsgConnectionOpenAck"

/// Per our convention, this message is sent to chain A.
/// The handler will check proofs of chain B.
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MsgConnectionOpenAck {
/// ConnectionId that chain A has chosen for it's ConnectionEnd
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ pub(crate) const TYPE_URL: &str = "/ibc.core.connection.v1.MsgConnectionOpenConf

/// Per our convention, this message is sent to chain B.
/// The handler will check proofs of chain A.
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MsgConnectionOpenConfirm {
/// ConnectionId that chain B has chosen for it's ConnectionEnd
Expand Down
75 changes: 75 additions & 0 deletions crates/ibc/src/core/ics03_connection/msgs/conn_open_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,64 @@ impl Msg for MsgConnectionOpenInit {
}
}

/// This module encapsulates the workarounds we need to do to implement
/// `BorshSerialize` and `BorshDeserialize` on `MsgConnectionOpenInit`
#[cfg(feature = "borsh")]
mod borsh_impls {
use borsh::{
maybestd::io::{self, Read},
BorshDeserialize, BorshSerialize,
};

use super::*;

#[derive(BorshSerialize, BorshDeserialize)]
pub struct InnerMsgConnectionOpenInit {
/// ClientId on chain A that the connection is being opened for
pub client_id_on_a: ClientId,
pub counterparty: Counterparty,
pub version: Option<Version>,
pub delay_period_nanos: u64,
pub signer: Signer,
}

impl BorshSerialize for MsgConnectionOpenInit {
fn serialize<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
let delay_period_nanos: u64 =
self.delay_period.as_nanos().try_into().map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
format!("Duration too long: {} nanos", self.delay_period.as_nanos()),
)
})?;

let inner = InnerMsgConnectionOpenInit {
client_id_on_a: self.client_id_on_a.clone(),
counterparty: self.counterparty.clone(),
version: self.version.clone(),
delay_period_nanos,
signer: self.signer.clone(),
};

inner.serialize(writer)
}
}

impl BorshDeserialize for MsgConnectionOpenInit {
fn deserialize_reader<R: Read>(reader: &mut R) -> io::Result<Self> {
let inner = InnerMsgConnectionOpenInit::deserialize_reader(reader)?;

Ok(MsgConnectionOpenInit {
client_id_on_a: inner.client_id_on_a,
counterparty: inner.counterparty,
version: inner.version,
delay_period: Duration::from_nanos(inner.delay_period_nanos),
signer: inner.signer,
})
}
}
}

impl Protobuf<RawMsgConnectionOpenInit> for MsgConnectionOpenInit {}

impl TryFrom<RawMsgConnectionOpenInit> for MsgConnectionOpenInit {
Expand Down Expand Up @@ -239,4 +297,21 @@ mod tests {
msg_with_counterpary_conn_id_some_back
);
}

/// Test that borsh serialization/deserialization works well with delay periods up to u64::MAX
#[cfg(feature = "borsh")]
#[test]
fn test_borsh() {
let mut raw = get_dummy_raw_msg_conn_open_init();
raw.delay_period = u64::MAX;
let msg = MsgConnectionOpenInit::try_from(raw.clone()).unwrap();

let serialized = borsh::to_vec(&msg).unwrap();

let msg_deserialized =
<MsgConnectionOpenInit as borsh::BorshDeserialize>::try_from_slice(&serialized)
.unwrap();

assert_eq!(msg, msg_deserialized);
}
}
109 changes: 109 additions & 0 deletions crates/ibc/src/core/ics03_connection/msgs/conn_open_try.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,99 @@ impl Msg for MsgConnectionOpenTry {
TYPE_URL.to_string()
}
}
#[allow(deprecated)]
#[cfg(feature = "borsh")]
mod borsh_impls {
use borsh::{
maybestd::io::{self, Read},
BorshDeserialize, BorshSerialize,
};

use super::*;

#[derive(BorshSerialize, BorshDeserialize)]
pub struct InnerMsgConnectionOpenTry {
/// ClientId on B that the connection is being opened for
pub client_id_on_b: ClientId,
/// ClientState of client tracking chain B on chain A
pub client_state_of_b_on_a: Any,
/// ClientId, ConnectionId and prefix of chain A
pub counterparty: Counterparty,
/// Versions supported by chain A
pub versions_on_a: Vec<Version>,
/// proof of ConnectionEnd stored on Chain A during ConnOpenInit
pub proof_conn_end_on_a: CommitmentProofBytes,
/// proof that chain A has stored ClientState of chain B on its client
pub proof_client_state_of_b_on_a: CommitmentProofBytes,
/// proof that chain A has stored ConsensusState of chain B on its client
pub proof_consensus_state_of_b_on_a: CommitmentProofBytes,
/// Height at which all proofs in this message were taken
pub proofs_height_on_a: Height,
/// height of latest header of chain A that updated the client on chain B
pub consensus_height_of_b_on_a: Height,
pub delay_period_nanos: u64,
pub signer: Signer,
/// optional proof of host state machines (chain B) that are unable to
/// introspect their own consensus state
pub proof_consensus_state_of_b: Option<CommitmentProofBytes>,

#[deprecated(since = "0.22.0")]
/// Only kept here for proper conversion to/from the raw type
previous_connection_id: String,
}

impl BorshSerialize for MsgConnectionOpenTry {
fn serialize<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
let delay_period_nanos: u64 =
self.delay_period.as_nanos().try_into().map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
format!("Duration too long: {} nanos", self.delay_period.as_nanos()),
)
})?;

let inner = InnerMsgConnectionOpenTry {
client_id_on_b: self.client_id_on_b.clone(),
client_state_of_b_on_a: self.client_state_of_b_on_a.clone(),
counterparty: self.counterparty.clone(),
versions_on_a: self.versions_on_a.clone(),
proof_conn_end_on_a: self.proof_conn_end_on_a.clone(),
proof_client_state_of_b_on_a: self.proof_client_state_of_b_on_a.clone(),
proof_consensus_state_of_b_on_a: self.proof_consensus_state_of_b_on_a.clone(),
proofs_height_on_a: self.proofs_height_on_a,
consensus_height_of_b_on_a: self.consensus_height_of_b_on_a,
delay_period_nanos,
signer: self.signer.clone(),
proof_consensus_state_of_b: self.proof_consensus_state_of_b.clone(),
previous_connection_id: self.previous_connection_id.clone(),
};

inner.serialize(writer)
}
}

impl BorshDeserialize for MsgConnectionOpenTry {
fn deserialize_reader<R: Read>(reader: &mut R) -> io::Result<Self> {
let inner = InnerMsgConnectionOpenTry::deserialize_reader(reader)?;

Ok(MsgConnectionOpenTry {
client_id_on_b: inner.client_id_on_b,
client_state_of_b_on_a: inner.client_state_of_b_on_a,
counterparty: inner.counterparty,
versions_on_a: inner.versions_on_a,
proof_conn_end_on_a: inner.proof_conn_end_on_a,
proof_client_state_of_b_on_a: inner.proof_client_state_of_b_on_a,
proof_consensus_state_of_b_on_a: inner.proof_consensus_state_of_b_on_a,
proofs_height_on_a: inner.proofs_height_on_a,
consensus_height_of_b_on_a: inner.consensus_height_of_b_on_a,
delay_period: Duration::from_nanos(inner.delay_period_nanos),
signer: inner.signer,
proof_consensus_state_of_b: inner.proof_consensus_state_of_b,
previous_connection_id: inner.previous_connection_id,
})
}
}
}

impl Protobuf<RawMsgConnectionOpenTry> for MsgConnectionOpenTry {}

Expand Down Expand Up @@ -357,4 +450,20 @@ mod tests {
assert_eq!(raw, raw_back);
assert_eq!(msg, msg_back);
}

/// Test that borsh serialization/deserialization works well with delay periods up to u64::MAX
#[cfg(feature = "borsh")]
#[test]
fn test_borsh() {
let mut raw = get_dummy_raw_msg_conn_open_try(10, 34);
raw.delay_period = u64::MAX;
let msg = MsgConnectionOpenTry::try_from(raw.clone()).unwrap();

let serialized = borsh::to_vec(&msg).unwrap();

let msg_deserialized =
<MsgConnectionOpenTry as borsh::BorshDeserialize>::try_from_slice(&serialized).unwrap();

assert_eq!(msg, msg_deserialized);
}
}
8 changes: 8 additions & 0 deletions crates/ibc/src/core/ics04_channel/msgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ pub use timeout_on_close::MsgTimeoutOnClose;
use crate::core::ics24_host::identifier::PortId;

/// All channel messages
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ChannelMsg {
OpenInit(MsgChannelOpenInit),
Expand All @@ -42,6 +46,10 @@ pub enum ChannelMsg {
}

/// All packet messages
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum PacketMsg {
Recv(MsgRecvPacket),
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/core/ics04_channel/msgs/acknowledgement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ pub(crate) const TYPE_URL: &str = "/ibc.core.channel.v1.MsgAcknowledgement";
///
/// Message definition for packet acknowledgements.
///
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MsgAcknowledgement {
pub packet: Packet,
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/core/ics04_channel/msgs/chan_close_confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ pub(crate) const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelCloseConfirm";
/// datagram).
/// Per our convention, this message is sent to chain B.
///
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MsgChannelCloseConfirm {
pub port_id_on_b: PortId,
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/core/ics04_channel/msgs/chan_close_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ pub(crate) const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelCloseInit";
/// Message definition for the first step in the channel close handshake (`ChanCloseInit` datagram).
/// Per our convention, this message is sent to chain A.
///
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MsgChannelCloseInit {
pub port_id_on_a: PortId,
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/core/ics04_channel/msgs/chan_open_ack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ pub(crate) const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelOpenAck";
/// Message definition for the third step in the channel open handshake (`ChanOpenAck` datagram).
///
/// Per our convention, this message is sent to chain A.
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MsgChannelOpenAck {
pub port_id_on_a: PortId,
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/core/ics04_channel/msgs/chan_open_confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ pub(crate) const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelOpenConfirm";
/// datagram).
/// Per our convention, this message is sent to chain B.
///
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MsgChannelOpenConfirm {
pub port_id_on_b: PortId,
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/core/ics04_channel/msgs/chan_open_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ pub(crate) const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelOpenInit";
/// Message definition for the first step in the channel open handshake (`ChanOpenInit` datagram).
/// Per our convention, this message is sent to chain A.
///
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MsgChannelOpenInit {
pub port_id_on_a: PortId,
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/core/ics04_channel/msgs/chan_open_try.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ pub(crate) const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelOpenTry";
/// Message definition for the second step in the channel open handshake (`ChanOpenTry` datagram).
/// Per our convention, this message is sent to chain B.
///
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MsgChannelOpenTry {
pub port_id_on_b: PortId,
Expand Down
Loading

0 comments on commit 2c28380

Please sign in to comment.