Skip to content

Commit ada3c94

Browse files
authored
Add borsh derive for MsgTransfer (#845)
* add borsh derive for `MsgTransfer` * changelog
1 parent d955e56 commit ada3c94

File tree

6 files changed

+96
-1
lines changed

6 files changed

+96
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- Add borsh derive for `MsgTransfer`
2+
([#845](https://github.com/cosmos/ibc-rs/pull/845))

crates/ibc/src/applications/transfer/amount.rs

+66-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Contains the `Amount` type, which represents amounts of tokens transferred.
22
3+
use crate::prelude::*;
34
use core::{ops::Deref, str::FromStr};
45
use derive_more::{Display, From, Into};
56

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

32+
#[cfg(feature = "borsh")]
33+
impl borsh::BorshSerialize for Amount {
34+
fn serialize<W: borsh::maybestd::io::Write>(
35+
&self,
36+
writer: &mut W,
37+
) -> borsh::maybestd::io::Result<()> {
38+
// Note: a "word" is 8 bytes (i.e. a u64)
39+
let words = self.as_slice();
40+
let bytes: Vec<u8> = words.iter().flat_map(|word| word.to_be_bytes()).collect();
41+
42+
writer.write_all(&bytes)
43+
}
44+
}
45+
#[cfg(feature = "borsh")]
46+
impl borsh::BorshDeserialize for Amount {
47+
fn deserialize_reader<R: borsh::maybestd::io::Read>(
48+
reader: &mut R,
49+
) -> borsh::maybestd::io::Result<Self> {
50+
const NUM_BYTES_IN_U64: usize = 8;
51+
const NUM_WORDS_IN_U256: usize = 4;
52+
53+
let mut buf = [0; 32];
54+
let bytes_read = reader.read(&mut buf)?;
55+
if bytes_read != 32 {
56+
return Err(borsh::maybestd::io::Error::new(
57+
borsh::maybestd::io::ErrorKind::InvalidInput,
58+
format!("Expected to read 32 bytes, read {bytes_read}"),
59+
));
60+
}
61+
62+
let words: Vec<u64> = buf
63+
.chunks_exact(NUM_BYTES_IN_U64)
64+
.map(|word| {
65+
let word: [u8; NUM_BYTES_IN_U64] = word
66+
.try_into()
67+
.expect("exact chunks of 8 bytes are expected to be 8 bytes");
68+
u64::from_be_bytes(word)
69+
})
70+
.collect();
71+
72+
let four_words: [u64; NUM_WORDS_IN_U256] = words
73+
.try_into()
74+
.expect("U256 is always 4 four words, and we confirmed that we read 32 bytes");
75+
76+
Ok(four_words.into())
77+
}
78+
}
79+
3180
impl Deref for Amount {
3281
type Target = [u64; 4];
3382

@@ -83,10 +132,10 @@ where
83132
}
84133

85134
#[cfg(test)]
86-
#[cfg(feature = "serde")]
87135
mod tests {
88136
use super::Amount;
89137

138+
#[cfg(feature = "serde")]
90139
#[test]
91140
fn serde_amount() {
92141
let value = Amount::from(42);
@@ -96,4 +145,20 @@ mod tests {
96145
let de: Amount = serde_json::from_slice(binary.as_ref()).expect("can deserialize");
97146
assert_eq!(de, value);
98147
}
148+
149+
#[cfg(feature = "borsh")]
150+
#[test]
151+
fn borsh_amount() {
152+
use borsh::BorshDeserialize;
153+
154+
let value = Amount::from(42);
155+
let serialized = borsh::to_vec(&value).unwrap();
156+
157+
// Amount is supposed to be a U256 according to the spec, which is 32 bytes
158+
assert_eq!(serialized.len(), 32);
159+
160+
let value_deserialized = Amount::try_from_slice(&serialized).unwrap();
161+
162+
assert_eq!(value, value_deserialized);
163+
}
99164
}

crates/ibc/src/applications/transfer/coin.rs

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ pub type RawCoin = Coin<String>;
2525
feature = "parity-scale-codec",
2626
derive(parity_scale_codec::Encode, parity_scale_codec::Decode,)
2727
)]
28+
#[cfg_attr(
29+
feature = "borsh",
30+
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
31+
)]
2832
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
2933
pub struct Coin<D> {
3034
/// Denomination

crates/ibc/src/applications/transfer/denom.rs

+16
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ use crate::serializers::serde_string;
2727
scale_info::TypeInfo
2828
)
2929
)]
30+
#[cfg_attr(
31+
feature = "borsh",
32+
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
33+
)]
3034
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
3135
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Display)]
3236
pub struct BaseDenom(String);
@@ -62,6 +66,10 @@ impl FromStr for BaseDenom {
6266
scale_info::TypeInfo
6367
)
6468
)]
69+
#[cfg_attr(
70+
feature = "borsh",
71+
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
72+
)]
6573
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6674
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
6775
#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
@@ -97,6 +105,10 @@ impl Display for TracePrefix {
97105
scale_info::TypeInfo
98106
)
99107
)]
108+
#[cfg_attr(
109+
feature = "borsh",
110+
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
111+
)]
100112
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
101113
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
102114
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord, From)]
@@ -198,6 +210,10 @@ impl Display for TracePath {
198210
scale_info::TypeInfo
199211
)
200212
)]
213+
#[cfg_attr(
214+
feature = "borsh",
215+
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
216+
)]
201217
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
202218
pub struct PrefixedDenom {
203219
/// A series of `{port-id}/{channel-id}`s for tracing the source of the token.

crates/ibc/src/applications/transfer/msgs/transfer.rs

+4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ pub(crate) const TYPE_URL: &str = "/ibc.applications.transfer.v1.MsgTransfer";
2929
feature = "parity-scale-codec",
3030
derive(parity_scale_codec::Encode, parity_scale_codec::Decode,)
3131
)]
32+
#[cfg_attr(
33+
feature = "borsh",
34+
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
35+
)]
3236
pub struct MsgTransfer {
3337
/// the port on which the packet will be sent
3438
pub port_id_on_a: PortId,

crates/ibc/src/applications/transfer/packet.rs

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ use crate::signer::Signer;
2424
feature = "parity-scale-codec",
2525
derive(parity_scale_codec::Encode, parity_scale_codec::Decode,)
2626
)]
27+
#[cfg_attr(
28+
feature = "borsh",
29+
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
30+
)]
2731
#[derive(Clone, Debug, PartialEq, Eq)]
2832
pub struct PacketData {
2933
pub token: PrefixedCoin,

0 commit comments

Comments
 (0)