Skip to content

Commit 4bbf564

Browse files
committed
wip
1 parent e9702bd commit 4bbf564

File tree

2 files changed

+51
-37
lines changed

2 files changed

+51
-37
lines changed

crates/ibc/src/core/ics24_host/identifier.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,24 @@ impl ChainId {
118118
/// A convenient method to check if the `ChainId` forms a valid identifier
119119
/// with the desired min/max length. However, ICS-24 does not specify a
120120
/// certain min or max lengths for chain identifiers.
121+
///
122+
/// Note that in case of identifiers with revision number, if `min_length <
123+
/// 3`, the function will take minimum length constraints of three. This is
124+
/// because it’s not possible to construct a valid identifier with a prefix
125+
/// and revision number which is shorter than three characters.
126+
///
127+
/// # Panics
128+
///
129+
/// Panics if `min_length > max_length`.
130+
///
131+
/// Furthermore, if the identifier has revision number, panics if
132+
/// `max_length - min_length < 19` since difference in length between
133+
/// shortest and longest revision number is 19 characters.
121134
pub fn validate_length(&self, min_length: u64, max_length: u64) -> Result<(), IdentifierError> {
122135
match self.split_chain_id() {
123-
Ok((chain_name, _)) => validate_prefix_length(chain_name, min_length, max_length),
136+
Ok((chain_name, _)) => {
137+
validate_prefix_length(chain_name, min_length.max(3), max_length)
138+
}
124139
_ => validate_identifier_length(&self.id, min_length, max_length),
125140
}
126141
}
@@ -139,7 +154,7 @@ impl FromStr for ChainId {
139154
match parse_chain_id_string(id) {
140155
Ok((chain_name, revision_number)) => {
141156
// Validate if the chain name with revision number has a valid length.
142-
validate_prefix_length(chain_name, 1, 64)?;
157+
validate_prefix_length(chain_name, 3, 64)?;
143158
Ok(Self {
144159
id: id.into(),
145160
revision_number,

crates/ibc/src/core/ics24_host/identifier/validate.rs

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub fn validate_identifier_chars(id: &str) -> Result<(), Error> {
2727
/// [`ICS-24`](https://github.com/cosmos/ibc/tree/main/spec/core/ics-024-host-requirements#paths-identifiers-separators)]
2828
/// spec.
2929
pub fn validate_identifier_length(id: &str, min: u64, max: u64) -> Result<(), Error> {
30-
assert!(0 < min && min <= max);
30+
assert!(max >= min);
3131

3232
// Check identifier length is between given min/max
3333
if !(min..=max).contains(&(id.len() as u64)) {
@@ -46,39 +46,30 @@ pub fn validate_prefix_length(
4646
min_id_length: u64,
4747
max_id_length: u64,
4848
) -> Result<(), Error> {
49-
assert!(max_id_length >= min_id_length);
49+
// Check that
50+
// 1. min_id_length allows for the shortest possible identifier such as
51+
// `p-0`,
52+
// 2. difference in length between minimum and maximum constraint allows for
53+
// full range of revision numbers. The shortest revision number is just
54+
// one digit; the longest is len(u64::MAX) which is
55+
assert!(
56+
min_id_length >= 3 && max_id_length.saturating_sub(min_id_length) >= 19,
57+
"{min_id_length} {max_id_length}"
58+
);
5059

5160
if prefix.is_empty() {
5261
return Err(Error::InvalidPrefix {
5362
prefix: prefix.into(),
5463
});
5564
}
5665

57-
// Statically checks if the prefix forms a valid identifier length when constructed with `u64::MAX`
58-
// len(prefix + '-' + u64::MAX) <= max_id_length (minimum prefix length is 1)
59-
if max_id_length < 22 {
60-
return Err(Error::InvalidLength {
61-
id: prefix.into(),
62-
min: 0,
63-
max: 0,
64-
});
65-
}
66-
67-
// Checks if the prefix forms a valid identifier length when constructed with `u64::MIN`
68-
// len('-' + u64::MIN) = 2
69-
validate_identifier_length(
70-
prefix,
71-
min_id_length.saturating_sub(2),
72-
max_id_length.saturating_sub(2),
73-
)?;
74-
75-
// Checks if the prefix forms a valid identifier length when constructed with `u64::MAX`
76-
// len('-' + u64::MAX) = 21
77-
validate_identifier_length(
78-
prefix,
79-
min_id_length.saturating_sub(21),
80-
max_id_length.saturating_sub(21),
81-
)?;
66+
// 1. The shortest identifier constructed from prefix is `<prefix>-0` so the
67+
// prefix must be at least min_id_length - 2 characters long for that to
68+
// be valid identifier.
69+
// 2. The longest identifier is `<prefix>-<u64::MAX>` (which adds 21
70+
// characters to the prefix as len('-' + u64::MAX) = 21) so the prefix
71+
// must be at most max_id_length - 21 characters long.
72+
validate_identifier_length(prefix, min_id_length.saturating_sub(2), max_id_length - 21)?;
8273

8374
Ok(())
8475
}
@@ -236,15 +227,14 @@ mod tests {
236227
}
237228

238229
#[rstest]
239-
#[case::empty_prefix("", 1, 64, false)]
240-
#[case::max_is_low("a", 1, 10, false)]
241-
#[case::u64_max_is_too_big("a", 3, 21, false)]
242-
#[case::u64_min_is_too_small("a", 4, 22, false)]
243-
#[case::u64_min_max_boundary("a", 3, 22, true)]
244-
#[case("chainA", 1, 32, true)]
245-
#[case("chainA", 1, 64, true)]
230+
#[case::at_bounds("a", 3, 22, true)]
231+
#[case::u64_max_too_long("ab", 3, 22, false)]
232+
#[case::at_bounds_foo("foo", 5, 25, true)]
233+
#[case::u64_min_too_short("fo", 5, 25, false)]
234+
#[case("chainA", 3, 32, true)]
235+
#[case("chainA", 3, 64, true)]
246236
#[test_log::test]
247-
fn test_prefix_length_validation(
237+
fn test_prefix_length_validation_success(
248238
#[case] prefix: &str,
249239
#[case] min: u64,
250240
#[case] max: u64,
@@ -253,4 +243,13 @@ mod tests {
253243
let result = validate_prefix_length(prefix, min, max);
254244
assert_eq!(result.is_ok(), success);
255245
}
246+
247+
#[rstest]
248+
#[case::min_is_low(2, 21)]
249+
#[case::max_is_low(3, 21)]
250+
#[should_panic]
251+
#[test_log::test]
252+
fn test_prefix_length_validation_panic(#[case] min: u64, #[case] max: u64) {
253+
let _ = validate_prefix_length("a", min, max);
254+
}
256255
}

0 commit comments

Comments
 (0)