Skip to content

Commit

Permalink
Add borsh derive for MsgTransfer (#845)
Browse files Browse the repository at this point in the history
* add borsh derive for `MsgTransfer`

* changelog
  • Loading branch information
plafer authored Aug 30, 2023
1 parent 56e7e62 commit 1833df5
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Add borsh derive for `MsgTransfer`
([#845](https://github.com/cosmos/ibc-rs/pull/845))
67 changes: 66 additions & 1 deletion crates/ibc/src/applications/transfer/amount.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Contains the `Amount` type, which represents amounts of tokens transferred.
use crate::prelude::*;
use core::{ops::Deref, str::FromStr};
use derive_more::{Display, From, Into};

Expand Down Expand Up @@ -28,6 +29,54 @@ impl parity_scale_codec::WrapperTypeDecode for Amount {
#[cfg(feature = "parity-scale-codec")]
impl parity_scale_codec::WrapperTypeEncode for Amount {}

#[cfg(feature = "borsh")]
impl borsh::BorshSerialize for Amount {
fn serialize<W: borsh::maybestd::io::Write>(
&self,
writer: &mut W,
) -> borsh::maybestd::io::Result<()> {
// Note: a "word" is 8 bytes (i.e. a u64)
let words = self.as_slice();
let bytes: Vec<u8> = words.iter().flat_map(|word| word.to_be_bytes()).collect();

writer.write_all(&bytes)
}
}
#[cfg(feature = "borsh")]
impl borsh::BorshDeserialize for Amount {
fn deserialize_reader<R: borsh::maybestd::io::Read>(
reader: &mut R,
) -> borsh::maybestd::io::Result<Self> {
const NUM_BYTES_IN_U64: usize = 8;
const NUM_WORDS_IN_U256: usize = 4;

let mut buf = [0; 32];
let bytes_read = reader.read(&mut buf)?;
if bytes_read != 32 {
return Err(borsh::maybestd::io::Error::new(
borsh::maybestd::io::ErrorKind::InvalidInput,
format!("Expected to read 32 bytes, read {bytes_read}"),
));
}

let words: Vec<u64> = buf
.chunks_exact(NUM_BYTES_IN_U64)
.map(|word| {
let word: [u8; NUM_BYTES_IN_U64] = word
.try_into()
.expect("exact chunks of 8 bytes are expected to be 8 bytes");
u64::from_be_bytes(word)
})
.collect();

let four_words: [u64; NUM_WORDS_IN_U256] = words
.try_into()
.expect("U256 is always 4 four words, and we confirmed that we read 32 bytes");

Ok(four_words.into())
}
}

impl Deref for Amount {
type Target = [u64; 4];

Expand Down Expand Up @@ -83,10 +132,10 @@ where
}

#[cfg(test)]
#[cfg(feature = "serde")]
mod tests {
use super::Amount;

#[cfg(feature = "serde")]
#[test]
fn serde_amount() {
let value = Amount::from(42);
Expand All @@ -96,4 +145,20 @@ mod tests {
let de: Amount = serde_json::from_slice(binary.as_ref()).expect("can deserialize");
assert_eq!(de, value);
}

#[cfg(feature = "borsh")]
#[test]
fn borsh_amount() {
use borsh::BorshDeserialize;

let value = Amount::from(42);
let serialized = borsh::to_vec(&value).unwrap();

// Amount is supposed to be a U256 according to the spec, which is 32 bytes
assert_eq!(serialized.len(), 32);

let value_deserialized = Amount::try_from_slice(&serialized).unwrap();

assert_eq!(value, value_deserialized);
}
}
4 changes: 4 additions & 0 deletions crates/ibc/src/applications/transfer/coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ pub type RawCoin = Coin<String>;
feature = "parity-scale-codec",
derive(parity_scale_codec::Encode, parity_scale_codec::Decode,)
)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Coin<D> {
/// Denomination
Expand Down
16 changes: 16 additions & 0 deletions crates/ibc/src/applications/transfer/denom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ use crate::serializers::serde_string;
scale_info::TypeInfo
)
)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Display)]
pub struct BaseDenom(String);
Expand Down Expand Up @@ -62,6 +66,10 @@ impl FromStr for BaseDenom {
scale_info::TypeInfo
)
)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
Expand Down Expand Up @@ -97,6 +105,10 @@ impl Display for TracePrefix {
scale_info::TypeInfo
)
)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord, From)]
Expand Down Expand Up @@ -198,6 +210,10 @@ impl Display for TracePath {
scale_info::TypeInfo
)
)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct PrefixedDenom {
/// A series of `{port-id}/{channel-id}`s for tracing the source of the token.
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/applications/transfer/msgs/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ pub(crate) const TYPE_URL: &str = "/ibc.applications.transfer.v1.MsgTransfer";
feature = "parity-scale-codec",
derive(parity_scale_codec::Encode, parity_scale_codec::Decode,)
)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct MsgTransfer {
/// the port on which the packet will be sent
pub port_id_on_a: PortId,
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/applications/transfer/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ use crate::signer::Signer;
feature = "parity-scale-codec",
derive(parity_scale_codec::Encode, parity_scale_codec::Decode,)
)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PacketData {
pub token: PrefixedCoin,
Expand Down

0 comments on commit 1833df5

Please sign in to comment.