From f62c356808a13a60feb17c8c9f41940de4df22db Mon Sep 17 00:00:00 2001
From: Farhad Shabani <Farhad.Shabani@gmail.com>
Date: Fri, 1 Dec 2023 08:13:13 -0800
Subject: [PATCH] imp: minimize prost dependency (#998)

---
 ...992-making-cosmwasm-compile-apps-transfers.md |  4 ----
 .../992-more-rigorous-cosmwasm-check.md          |  3 +++
 .../997-minimize-prost-dependency.md             |  2 ++
 ibc-clients/ics07-tendermint/Cargo.toml          |  2 --
 ibc-clients/ics07-tendermint/src/client_state.rs | 16 +++-------------
 ibc-core/ics02-client/Cargo.toml                 |  5 -----
 ibc-core/ics02-client/context/Cargo.toml         |  2 --
 .../ics02-client/src/handler/update_client.rs    |  4 ++--
 ibc-core/ics02-client/types/src/error.rs         |  2 --
 ibc-core/ics03-connection/Cargo.toml             |  5 -----
 .../src/handler/conn_open_ack.rs                 |  4 ++--
 .../src/handler/conn_open_try.rs                 |  4 ++--
 ibc-core/ics04-channel/Cargo.toml                |  5 -----
 ibc-core/ics04-channel/src/handler/timeout.rs    | 10 +---------
 .../src/handler/timeout_on_close.rs              | 10 +---------
 ibc-core/ics04-channel/types/src/error.rs        |  2 --
 ibc-core/ics24-host/Cargo.toml                   |  2 --
 ibc-core/ics24-host/cosmos/Cargo.toml            |  2 --
 .../ics24-host/types/src/identifiers/sequence.rs | 11 +++++++++++
 ibc-core/ics26-routing/Cargo.toml                |  2 --
 ibc-primitives/src/traits/proto.rs               | 11 +++++++++++
 21 files changed, 38 insertions(+), 70 deletions(-)
 delete mode 100644 .changelog/unreleased/improvements/992-making-cosmwasm-compile-apps-transfers.md
 create mode 100644 .changelog/unreleased/improvements/992-more-rigorous-cosmwasm-check.md
 create mode 100644 .changelog/unreleased/improvements/997-minimize-prost-dependency.md

diff --git a/.changelog/unreleased/improvements/992-making-cosmwasm-compile-apps-transfers.md b/.changelog/unreleased/improvements/992-making-cosmwasm-compile-apps-transfers.md
deleted file mode 100644
index 961a043a66..0000000000
--- a/.changelog/unreleased/improvements/992-making-cosmwasm-compile-apps-transfers.md
+++ /dev/null
@@ -1,4 +0,0 @@
-- More rigorous CosmWasm check by upgrading dependencies and including `std` and
-  `schema` features for `ibc-core`.
-  ([\#992](https://github.com/cosmos/ibc-rs/pull/992))
-  
diff --git a/.changelog/unreleased/improvements/992-more-rigorous-cosmwasm-check.md b/.changelog/unreleased/improvements/992-more-rigorous-cosmwasm-check.md
new file mode 100644
index 0000000000..7540c8a9d8
--- /dev/null
+++ b/.changelog/unreleased/improvements/992-more-rigorous-cosmwasm-check.md
@@ -0,0 +1,3 @@
+- [`cw-check`] More rigorous CosmWasm check by upgrading dependencies and
+  including `std` and `schema` features for `ibc-core`.
+  ([\#992](https://github.com/cosmos/ibc-rs/pull/992))
diff --git a/.changelog/unreleased/improvements/997-minimize-prost-dependency.md b/.changelog/unreleased/improvements/997-minimize-prost-dependency.md
new file mode 100644
index 0000000000..eb5cabc3de
--- /dev/null
+++ b/.changelog/unreleased/improvements/997-minimize-prost-dependency.md
@@ -0,0 +1,2 @@
+- [`ibc-primitives`] Minimize `prost` dependency by introducing `ToVec` trait
+ ([\#997](https://github.com/cosmos/ibc-rs/issues/997))
diff --git a/ibc-clients/ics07-tendermint/Cargo.toml b/ibc-clients/ics07-tendermint/Cargo.toml
index 22a46ae289..a66ab41ba4 100644
--- a/ibc-clients/ics07-tendermint/Cargo.toml
+++ b/ibc-clients/ics07-tendermint/Cargo.toml
@@ -18,7 +18,6 @@ all-features = true
 
 [dependencies]
 # external dependencies
-prost = { workspace = true }
 serde = { workspace = true, optional = true }
 
 # ibc dependencies
@@ -36,7 +35,6 @@ tendermint-light-client-verifier = { workspace = true, features = ["rust-crypto"
 [features]
 default = ["std"]
 std = [
-    "prost/std",
     "serde/std",
     "ibc-client-tendermint-types/std",
     "ibc-core-client/std",
diff --git a/ibc-clients/ics07-tendermint/src/client_state.rs b/ibc-clients/ics07-tendermint/src/client_state.rs
index 515ebf6272..8797ad3bb1 100644
--- a/ibc-clients/ics07-tendermint/src/client_state.rs
+++ b/ibc-clients/ics07-tendermint/src/client_state.rs
@@ -33,7 +33,7 @@ use ibc_core_host::types::path::{
 };
 use ibc_core_host::ExecutionContext;
 use ibc_primitives::prelude::*;
-use prost::Message;
+use ibc_primitives::ToVec;
 
 use super::consensus_state::ConsensusState as TmConsensusState;
 use crate::context::{
@@ -169,32 +169,22 @@ impl ClientStateCommon for ClientState {
 
         let last_height = self.latest_height().revision_height();
 
-        let mut client_state_value = Vec::new();
-        upgraded_client_state
-            .encode(&mut client_state_value)
-            .map_err(ClientError::Encode)?;
-
         // Verify the proof of the upgraded client state
         self.verify_membership(
             &upgrade_path_prefix,
             &proof_upgrade_client,
             root,
             Path::UpgradeClient(UpgradeClientPath::UpgradedClientState(last_height)),
-            client_state_value,
+            upgraded_client_state.to_vec(),
         )?;
 
-        let mut cons_state_value = Vec::new();
-        upgraded_consensus_state
-            .encode(&mut cons_state_value)
-            .map_err(ClientError::Encode)?;
-
         // Verify the proof of the upgraded consensus state
         self.verify_membership(
             &upgrade_path_prefix,
             &proof_upgrade_consensus_state,
             root,
             Path::UpgradeClient(UpgradeClientPath::UpgradedClientConsensusState(last_height)),
-            cons_state_value,
+            upgraded_consensus_state.to_vec(),
         )?;
 
         Ok(())
diff --git a/ibc-core/ics02-client/Cargo.toml b/ibc-core/ics02-client/Cargo.toml
index 5e82d07365..bcb30f5616 100644
--- a/ibc-core/ics02-client/Cargo.toml
+++ b/ibc-core/ics02-client/Cargo.toml
@@ -17,10 +17,6 @@ description  = """
 all-features = true
 
 [dependencies]
-# external dependencies
-prost = { workspace = true }
-
-# ibc dependencies
 ibc-core-client-types     = { workspace = true }
 ibc-core-client-context   = { workspace = true }
 ibc-core-commitment-types = { workspace = true }
@@ -31,7 +27,6 @@ ibc-primitives            = { workspace = true }
 [features]
 default = ["std"]
 std = [
-    "prost/std",
     "ibc-core-client-types/std",
     "ibc-core-client-context/std",
     "ibc-core-commitment-types/std",
diff --git a/ibc-core/ics02-client/context/Cargo.toml b/ibc-core/ics02-client/context/Cargo.toml
index 3b19788b7f..789b53ad86 100644
--- a/ibc-core/ics02-client/context/Cargo.toml
+++ b/ibc-core/ics02-client/context/Cargo.toml
@@ -21,7 +21,6 @@ all-features = true
 # external dependencies
 derive_more     = { workspace = true }
 displaydoc      = { workspace = true }
-prost           = { workspace = true }
 subtle-encoding = { workspace = true }
 
 # ibc dependencies
@@ -39,7 +38,6 @@ tendermint = { workspace = true }
 default = ["std"]
 std = [
     "displaydoc/std",
-    "prost/std",
     "subtle-encoding/std",
     "ibc-core-client-types/std",
     "ibc-core-commitment-types/std",
diff --git a/ibc-core/ics02-client/src/handler/update_client.rs b/ibc-core/ics02-client/src/handler/update_client.rs
index 8970bc5276..a9d6862d5f 100644
--- a/ibc-core/ics02-client/src/handler/update_client.rs
+++ b/ibc-core/ics02-client/src/handler/update_client.rs
@@ -11,7 +11,7 @@ use ibc_core_handler_types::error::ContextError;
 use ibc_core_handler_types::events::{IbcEvent, MessageEvent};
 use ibc_core_host::{ExecutionContext, ValidationContext};
 use ibc_primitives::prelude::*;
-use prost::Message;
+use ibc_primitives::ToVec;
 
 pub fn validate<Ctx>(ctx: &Ctx, msg: MsgUpdateOrMisbehaviour) -> Result<(), ContextError>
 where
@@ -108,7 +108,7 @@ where
                     client_state.client_type(),
                     *consensus_height,
                     consensus_heights,
-                    header.encode_to_vec(),
+                    header.to_vec(),
                 ))
             };
             ctx.emit_ibc_event(IbcEvent::Message(MessageEvent::Client))?;
diff --git a/ibc-core/ics02-client/types/src/error.rs b/ibc-core/ics02-client/types/src/error.rs
index ab40103f1e..27cf5304b1 100644
--- a/ibc-core/ics02-client/types/src/error.rs
+++ b/ibc-core/ics02-client/types/src/error.rs
@@ -58,8 +58,6 @@ pub enum ClientError {
     MissingRawConsensusState,
     /// invalid client id in the update client message: `{0}`
     InvalidMsgUpdateClientId(IdentifierError),
-    /// encode error: `{0}`
-    Encode(prost::EncodeError),
     /// decode error: `{0}`
     Decode(prost::DecodeError),
     /// invalid client identifier error: `{0}`
diff --git a/ibc-core/ics03-connection/Cargo.toml b/ibc-core/ics03-connection/Cargo.toml
index 56f51110e6..f7531db798 100644
--- a/ibc-core/ics03-connection/Cargo.toml
+++ b/ibc-core/ics03-connection/Cargo.toml
@@ -17,10 +17,6 @@ description  = """
 all-features = true
 
 [dependencies]
-# external dependencies
-prost = { workspace = true }
-
-# ibc dependencies
 ibc-core-client           = { workspace = true }
 ibc-core-connection-types = { workspace = true }
 ibc-core-host             = { workspace = true }
@@ -30,7 +26,6 @@ ibc-primitives            = { workspace = true }
 [features]
 default = ["std"]
 std = [
-    "prost/std",
     "ibc-core-client/std",
     "ibc-core-connection-types/std",
     "ibc-core-host/std",
diff --git a/ibc-core/ics03-connection/src/handler/conn_open_ack.rs b/ibc-core/ics03-connection/src/handler/conn_open_ack.rs
index af44a4ee9b..ca5fdb5fab 100644
--- a/ibc-core/ics03-connection/src/handler/conn_open_ack.rs
+++ b/ibc-core/ics03-connection/src/handler/conn_open_ack.rs
@@ -14,7 +14,7 @@ use ibc_core_host::types::path::{ClientConsensusStatePath, ClientStatePath, Conn
 use ibc_core_host::{ExecutionContext, ValidationContext};
 use ibc_primitives::prelude::*;
 use ibc_primitives::proto::Protobuf;
-use prost::Message;
+use ibc_primitives::ToVec;
 
 pub fn validate<Ctx>(ctx_a: &Ctx, msg: MsgConnectionOpenAck) -> Result<(), ContextError>
 where
@@ -106,7 +106,7 @@ where
                 &msg.proof_client_state_of_a_on_b,
                 consensus_state_of_b_on_a.root(),
                 Path::ClientState(ClientStatePath::new(vars.client_id_on_b())),
-                msg.client_state_of_a_on_b.encode_to_vec(),
+                msg.client_state_of_a_on_b.to_vec(),
             )
             .map_err(|e| ConnectionError::ClientStateVerificationFailure {
                 client_id: vars.client_id_on_b().clone(),
diff --git a/ibc-core/ics03-connection/src/handler/conn_open_try.rs b/ibc-core/ics03-connection/src/handler/conn_open_try.rs
index 6d70604f92..61bd339a27 100644
--- a/ibc-core/ics03-connection/src/handler/conn_open_try.rs
+++ b/ibc-core/ics03-connection/src/handler/conn_open_try.rs
@@ -15,7 +15,7 @@ use ibc_core_host::types::path::{
 use ibc_core_host::{ExecutionContext, ValidationContext};
 use ibc_primitives::prelude::*;
 use ibc_primitives::proto::Protobuf;
-use prost::Message;
+use ibc_primitives::ToVec;
 
 pub fn validate<Ctx>(ctx_b: &Ctx, msg: MsgConnectionOpenTry) -> Result<(), ContextError>
 where
@@ -101,7 +101,7 @@ where
                 &msg.proof_client_state_of_b_on_a,
                 consensus_state_of_a_on_b.root(),
                 Path::ClientState(ClientStatePath::new(client_id_on_a)),
-                msg.client_state_of_b_on_a.encode_to_vec(),
+                msg.client_state_of_b_on_a.to_vec(),
             )
             .map_err(|e| ConnectionError::ClientStateVerificationFailure {
                 client_id: msg.client_id_on_b.clone(),
diff --git a/ibc-core/ics04-channel/Cargo.toml b/ibc-core/ics04-channel/Cargo.toml
index ba955ef673..d2b5edf99f 100644
--- a/ibc-core/ics04-channel/Cargo.toml
+++ b/ibc-core/ics04-channel/Cargo.toml
@@ -17,10 +17,6 @@ description  = """
 all-features = true
 
 [dependencies]
-# external dependencies
-prost = { workspace = true }
-
-# ibc dependencies
 ibc-core-client           = { workspace = true }
 ibc-core-connection       = { workspace = true }
 ibc-core-channel-types    = { workspace = true }
@@ -33,7 +29,6 @@ ibc-primitives            = { workspace = true }
 [features]
 default = ["std"]
 std = [
-    "prost/std",
     "ibc-core-client/std",
     "ibc-core-connection/std",
     "ibc-core-channel-types/std",
diff --git a/ibc-core/ics04-channel/src/handler/timeout.rs b/ibc-core/ics04-channel/src/handler/timeout.rs
index 28cfd65876..0cfed7c03d 100644
--- a/ibc-core/ics04-channel/src/handler/timeout.rs
+++ b/ibc-core/ics04-channel/src/handler/timeout.rs
@@ -15,7 +15,6 @@ use ibc_core_host::types::path::{
 use ibc_core_host::{ExecutionContext, ValidationContext};
 use ibc_core_router::module::Module;
 use ibc_primitives::prelude::*;
-use prost::Message;
 
 use super::timeout_on_close;
 
@@ -231,19 +230,12 @@ where
             let seq_recv_path_on_b =
                 SeqRecvPath::new(&msg.packet.port_id_on_b, &msg.packet.chan_id_on_b);
 
-            let mut value = Vec::new();
-            u64::from(msg.packet.seq_on_a)
-                .encode(&mut value)
-                .map_err(|_| PacketError::CannotEncodeSequence {
-                    sequence: msg.packet.seq_on_a,
-                })?;
-
             client_state_of_b_on_a.verify_membership(
                 conn_end_on_a.counterparty().prefix(),
                 &msg.proof_unreceived_on_b,
                 consensus_state_of_b_on_a.root(),
                 Path::SeqRecv(seq_recv_path_on_b),
-                value,
+                msg.packet.seq_on_a.to_vec(),
             )
         } else {
             let receipt_path_on_b = ReceiptPath::new(
diff --git a/ibc-core/ics04-channel/src/handler/timeout_on_close.rs b/ibc-core/ics04-channel/src/handler/timeout_on_close.rs
index 641f0483c8..c08c0e8d36 100644
--- a/ibc-core/ics04-channel/src/handler/timeout_on_close.rs
+++ b/ibc-core/ics04-channel/src/handler/timeout_on_close.rs
@@ -13,7 +13,6 @@ use ibc_core_host::types::path::{
 use ibc_core_host::ValidationContext;
 use ibc_primitives::prelude::*;
 use ibc_primitives::proto::Protobuf;
-use prost::Message;
 
 pub fn validate<Ctx>(ctx_a: &Ctx, msg: &MsgTimeoutOnClose) -> Result<(), ContextError>
 where
@@ -135,19 +134,12 @@ where
             }
             let seq_recv_path_on_b = SeqRecvPath::new(&packet.port_id_on_b, &packet.chan_id_on_b);
 
-            let mut value = Vec::new();
-            u64::from(packet.seq_on_a).encode(&mut value).map_err(|_| {
-                PacketError::CannotEncodeSequence {
-                    sequence: packet.seq_on_a,
-                }
-            })?;
-
             client_state_of_b_on_a.verify_membership(
                 conn_end_on_a.counterparty().prefix(),
                 &msg.proof_unreceived_on_b,
                 consensus_state_of_b_on_a.root(),
                 Path::SeqRecv(seq_recv_path_on_b),
-                value,
+                packet.seq_on_a.to_vec(),
             )
         } else {
             let receipt_path_on_b = ReceiptPath::new(
diff --git a/ibc-core/ics04-channel/types/src/error.rs b/ibc-core/ics04-channel/types/src/error.rs
index 13e33db9cc..652ad08787 100644
--- a/ibc-core/ics04-channel/types/src/error.rs
+++ b/ibc-core/ics04-channel/types/src/error.rs
@@ -164,8 +164,6 @@ pub enum PacketError {
         port_id: PortId,
         channel_id: ChannelId,
     },
-    /// Cannot encode sequence `{sequence}`
-    CannotEncodeSequence { sequence: Sequence },
     /// other error: `{description}`
     Other { description: String },
 }
diff --git a/ibc-core/ics24-host/Cargo.toml b/ibc-core/ics24-host/Cargo.toml
index 664d3da237..0726eea080 100644
--- a/ibc-core/ics24-host/Cargo.toml
+++ b/ibc-core/ics24-host/Cargo.toml
@@ -21,7 +21,6 @@ all-features = true
 # external dependencies
 derive_more      = { workspace = true }
 displaydoc       = { workspace = true }
-prost            = { workspace = true }
 subtle-encoding  = { workspace = true }
 
 # ibc dependencies
@@ -41,7 +40,6 @@ rstest = { workspace = true }
 default = ["std"]
 std = [
     "displaydoc/std",
-    "prost/std",
     "subtle-encoding/std",
     "ibc-core-client-types/std",
     "ibc-core-client-context/std",
diff --git a/ibc-core/ics24-host/cosmos/Cargo.toml b/ibc-core/ics24-host/cosmos/Cargo.toml
index 45a427b811..bbe7d7bb20 100644
--- a/ibc-core/ics24-host/cosmos/Cargo.toml
+++ b/ibc-core/ics24-host/cosmos/Cargo.toml
@@ -22,7 +22,6 @@ all-features = true
 borsh           = { workspace = true, optional = true}
 derive_more     = { workspace = true }
 displaydoc      = { workspace = true }
-prost           = { workspace = true }
 serde           = { workspace = true, optional = true }
 sha2            = { workspace = true }
 subtle-encoding = { workspace = true }
@@ -50,7 +49,6 @@ scale-info         = { workspace = true, optional = true }
 default = ["std"]
 std = [
     "displaydoc/std",
-    "prost/std",
     "serde/std",
     "sha2/std",
     "subtle-encoding/std",
diff --git a/ibc-core/ics24-host/types/src/identifiers/sequence.rs b/ibc-core/ics24-host/types/src/identifiers/sequence.rs
index db6d9c5608..ece48903b5 100644
--- a/ibc-core/ics24-host/types/src/identifiers/sequence.rs
+++ b/ibc-core/ics24-host/types/src/identifiers/sequence.rs
@@ -1,4 +1,5 @@
 use ibc_primitives::prelude::*;
+use ibc_primitives::ToVec;
 
 use crate::error::IdentifierError;
 
@@ -34,16 +35,26 @@ impl core::str::FromStr for Sequence {
 }
 
 impl Sequence {
+    /// Gives the sequence number.
     pub fn value(&self) -> u64 {
         self.0
     }
+
+    /// Returns `true` if the sequence number is zero.
     pub fn is_zero(&self) -> bool {
         self.0 == 0
     }
 
+    /// Increments the sequence number by one.
     pub fn increment(&self) -> Sequence {
         Sequence(self.0 + 1)
     }
+
+    /// Encodes the sequence number into a `Vec<u8>` using
+    /// `prost::Message::encode_to_vec`.
+    pub fn to_vec(&self) -> Vec<u8> {
+        self.0.to_vec()
+    }
 }
 
 impl From<u64> for Sequence {
diff --git a/ibc-core/ics26-routing/Cargo.toml b/ibc-core/ics26-routing/Cargo.toml
index 91e75f476f..482bf719d8 100644
--- a/ibc-core/ics26-routing/Cargo.toml
+++ b/ibc-core/ics26-routing/Cargo.toml
@@ -20,7 +20,6 @@ all-features = true
 # external dependencies
 derive_more     = { workspace = true }
 displaydoc      = { workspace = true }
-prost           = { workspace = true }
 subtle-encoding = { workspace = true }
 
 # ibc dependencies
@@ -33,7 +32,6 @@ ibc-core-router-types  = { workspace = true }
 default = ["std"]
 std = [
     "displaydoc/std",
-    "prost/std",
     "subtle-encoding/std",
     "ibc-primitives/std",
     "ibc-core-channel-types/std",
diff --git a/ibc-primitives/src/traits/proto.rs b/ibc-primitives/src/traits/proto.rs
index b08589014d..686350b2d0 100644
--- a/ibc-primitives/src/traits/proto.rs
+++ b/ibc-primitives/src/traits/proto.rs
@@ -31,3 +31,14 @@ where
     <Self as TryFrom<P>>::Error: Display,
 {
 }
+
+/// Convenient trait for converting types to a raw Protobuf `Vec<u8>`.
+pub trait ToVec {
+    fn to_vec(&self) -> Vec<u8>;
+}
+
+impl<T: prost::Message> ToVec for T {
+    fn to_vec(&self) -> Vec<u8> {
+        self.encode_to_vec()
+    }
+}