diff --git a/.changelog/unreleased/bug-fixes/1262-deserialize-height-without-revision-number.md b/.changelog/unreleased/bug-fixes/1262-deserialize-height-without-revision-number.md new file mode 100644 index 000000000..3cc3205f9 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/1262-deserialize-height-without-revision-number.md @@ -0,0 +1,2 @@ +- [ibc-core-client-types] Serde support for `Height` without `revision_number` + ([#1262](https://github.com/cosmos/ibc-rs/issues/1262)). diff --git a/ibc-core/ics02-client/types/Cargo.toml b/ibc-core/ics02-client/types/Cargo.toml index 8e8451371..f774601db 100644 --- a/ibc-core/ics02-client/types/Cargo.toml +++ b/ibc-core/ics02-client/types/Cargo.toml @@ -42,7 +42,8 @@ parity-scale-codec = { workspace = true, optional = true } scale-info = { workspace = true, optional = true } [dev-dependencies] -rstest = { workspace = true } +rstest = { workspace = true } +serde-json = { workspace = true } [features] default = [ "std" ] diff --git a/ibc-core/ics02-client/types/src/height.rs b/ibc-core/ics02-client/types/src/height.rs index 1ae788add..92ad6fd34 100644 --- a/ibc-core/ics02-client/types/src/height.rs +++ b/ibc-core/ics02-client/types/src/height.rs @@ -31,6 +31,7 @@ use crate::error::ClientError; #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct Height { /// Previously known as "epoch" + #[cfg_attr(feature = "serde", serde(default))] revision_number: u64, /// The height of a block @@ -179,37 +180,52 @@ impl FromStr for Height { } } -#[test] -fn test_valid_height() { - assert_eq!( - "1-1".parse::().unwrap(), - Height { - revision_number: 1, - revision_height: 1 - } - ); - assert_eq!( - "1-10".parse::().unwrap(), - Height { - revision_number: 1, - revision_height: 10 - } - ); -} - -#[test] -fn test_invalid_height() { - assert!("0-0".parse::().is_err()); - assert!("0-".parse::().is_err()); - assert!("-0".parse::().is_err()); - assert!("-".parse::().is_err()); - assert!("1-1-1".parse::().is_err()); - - let decoding_err = "1".parse::().unwrap_err(); - let decoding_err = decoding_err.to_string(); - assert!(decoding_err.contains("height `1` not properly formatted")); - - let decoding_err = "".parse::().unwrap_err(); - let decoding_err = decoding_err.to_string(); - assert!(decoding_err.contains("height `` not properly formatted")); +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_valid_height() { + assert_eq!( + "1-1".parse::().unwrap(), + Height { + revision_number: 1, + revision_height: 1 + } + ); + assert_eq!( + "1-10".parse::().unwrap(), + Height { + revision_number: 1, + revision_height: 10 + } + ); + } + + #[test] + fn test_invalid_height() { + assert!("0-0".parse::().is_err()); + assert!("0-".parse::().is_err()); + assert!("-0".parse::().is_err()); + assert!("-".parse::().is_err()); + assert!("1-1-1".parse::().is_err()); + + let decoding_err = "1".parse::().unwrap_err(); + let decoding_err = decoding_err.to_string(); + assert!(decoding_err.contains("height `1` not properly formatted")); + + let decoding_err = "".parse::().unwrap_err(); + let decoding_err = decoding_err.to_string(); + assert!(decoding_err.contains("height `` not properly formatted")); + } + + #[test] + fn test_empty_rev_number_deserialization() { + // #1262: ibc-go uses `omitempty` in JSON serialization + let json_str = r#"{"revision_height": 10}"#; + let actual: Height = serde_json::from_str(json_str).unwrap(); + let expected = Height::new(0, 10).unwrap(); + + assert_eq!(actual, expected); + } }