Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

imp(ics23): fallible conversion for ProofSpec, LeafOp, InnerSpec #1160

Merged

Conversation

tuantran1702
Copy link
Contributor

@tuantran1702 tuantran1702 commented Apr 8, 2024

Closes: #1108

Description

Add conversion checks for ProofSpec, LeafOp, and InnerSpec structs.


PR author checklist:

  • Added changelog entry, using unclog.
  • Added tests.
  • Linked to GitHub issue.
  • Updated code comments and documentation (e.g., docs/).
  • Tagged one reviewer who will be the one responsible for shepherding this PR.

Reviewer checklist:

  • Reviewed Files changed in the GitHub PR explorer.
  • Manually tested (in case integration/unit/mock tests are absent).

/cc @Farhad-Shabani @rnbguy

@tuantran1702 tuantran1702 marked this pull request as draft April 8, 2024 18:16
@tuantran1702 tuantran1702 marked this pull request as ready for review April 8, 2024 18:23
Copy link
Collaborator

@rnbguy rnbguy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good ! 👍 Thanks for the PR

Requested some changes.

ibc-core/ics23-commitment/types/src/specs.rs Outdated Show resolved Hide resolved
return Err(CommitmentError::InvalidDepthRange(spec.min_depth, spec.max_depth));
}

let leaf_spec = spec.leaf_spec.map(|lop| LeafOp::from(lop)).map(|lop| lop.0);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let leaf_spec = spec.leaf_spec.map(|lop| LeafOp::from(lop)).map(|lop| lop.0);
let leaf_spec = spec.leaf_spec.map(LeafOp::from).map(|lop| lop.0);

Comment on lines 50 to 54
let mut specs = Vec::new();
for raw_spec in ics23_specs {
let spec = ProofSpec::try_from(raw_spec)?;
specs.push(spec);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use

let specs = ics23_specs
  .into_iter()
  .map(ProofSpec::try_from)
  .collect::<Result<Vec<_>, _>>()?;

Comment on lines 559 to 580
// Test {
// name: "Invalid (empty) proof specs".to_string(),
// params: ClientStateParams {
// proof_specs: Vec::<Ics23ProofSpec>::new(),
// ..default_params.clone()
// },
// want_pass: false,
// },
// Test {
// name: "Invalid (empty) proof specs depth range".to_string(),
// params: ClientStateParams {
// proof_specs: vec![Ics23ProofSpec {
// leaf_spec: None,
// inner_spec: None,
// min_depth: 2,
// max_depth: 1,
// prehash_key_before_comparison: false,
// }],
// ..default_params
// },
// want_pass: false,
// },
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add these tests? I guess that these failed to be created - because of try_from. In that case, add them as unit tests for your new TryFrom implementations.

ibc-core/ics23-commitment/types/src/specs.rs Outdated Show resolved Hide resolved
Comment on lines 144 to 149
if inner_spec.child_size <= 0 {
return Err(CommitmentError::InvalidChildSize(inner_spec.child_size));
}
if inner_spec.min_prefix_length > inner_spec.max_prefix_length
|| inner_spec.min_prefix_length < 0
|| inner_spec.max_prefix_length < 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add comments about the failure cases.

Comment on lines 72 to 74
if spec.max_depth < spec.min_depth
|| spec.min_depth < 0
|| spec.max_depth < 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add comments about the failure case.

example: why 0 is case is allowed.

Copy link
Contributor Author

@tuantran1702 tuantran1702 Apr 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I am not certain about this, given some thought, I guess when min_depth or max_depth is negative, it specify that no lower or upper bound is enforced on the number of allowed InnerOps(proof specs) As a result something like min_depth=2, max_depth=-1 is perfectly fine.
Would love to hear your opinion @rnbguy, I think the failure case should be limited to only if spec.max_depth>0 && spec.min_depth>0 && spec.max_depth < spec.min_depth

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey sorry for not explaining myself 😅 I know the logic. I suggested adding them in the comments.

You can refer to the comments in protobuf definitions.

Copy link
Contributor Author

@tuantran1702 tuantran1702 Apr 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rnbguy yes but do you think

spec.max_depth < spec.min_depth
            || spec.min_depth < 0
            || spec.max_depth < 0

is correct or it should be as I mention?

Copy link
Collaborator

@rnbguy rnbguy Apr 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last comment is not right. The error case should be following, as you mentioned already,

0 < spec.min_depth && 0 < spec.max_depth && spec.max_depth < spec.min_depth

So, if both of min_depth and max_depth are greater than zero, min_depth <= max_depth. Add the logic in the comment to avoid confusion.

Copy link
Collaborator

@rnbguy rnbguy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a few last requests 🙏

ibc-core/ics23-commitment/types/src/error.rs Outdated Show resolved Hide resolved
Comment on lines -559 to -566
Test {
name: "Invalid (empty) proof specs".to_string(),
params: ClientStateParams {
proof_specs: Vec::<Ics23ProofSpec>::new().into(),
..default_params.clone()
},
want_pass: false,
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, we can leave this test here, no?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove it after disallowing empty proof specs in Vec<RawProofSpec>::try_from.

min_depth: 2,
max_depth: 1,
prehash_key_before_comparison: false,
}].into(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to confirm - this test is removed because min_depth: 2 and max_depth: 1 is not a valid Ics23ProofSpec after deserialization from protobuf?

I think, it's still ok to leave them here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update: this will fail when unwrapping. so this must be removed.

ibc-core/ics23-commitment/types/src/specs.rs Outdated Show resolved Hide resolved
ibc-core/ics23-commitment/types/src/specs.rs Outdated Show resolved Hide resolved
ibc-core/ics23-commitment/types/src/specs.rs Outdated Show resolved Hide resolved
Comment on lines 152 to 154
if inner_spec.max_prefix_length < inner_spec.min_prefix_length
|| inner_spec.min_prefix_length < 0
|| inner_spec.max_prefix_length < 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment here as well?

The point here is - these values are used regardless they are negative. So they must be positive. I am not sure why this is not specified in ics23. In Go impl, they are just used as integers.

Comment on lines 194 to 230
let valid_raw_proof_spec = vec![
RawProofSpec {
leaf_spec: None,
inner_spec: None,
max_depth: 5,
min_depth: 3,
prehash_key_before_comparison: false,
},
RawProofSpec {
leaf_spec: None,
inner_spec: None,
max_depth: -3,
min_depth: 3,
prehash_key_before_comparison: false,
},
RawProofSpec {
leaf_spec: None,
inner_spec: None,
max_depth: 2,
min_depth: -6,
prehash_key_before_comparison: false,
},
RawProofSpec {
leaf_spec: None,
inner_spec: None,
max_depth: -2,
min_depth: -6,
prehash_key_before_comparison: false,
},
RawProofSpec {
leaf_spec: None,
inner_spec: None,
max_depth: -6,
min_depth: -2,
prehash_key_before_comparison: false,
},
];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please use parametrized case from rstest here?

Comment on lines 262 to 303
let invalid_raw_inner_spec = vec![
RawInnerSpec {
child_order: vec![1],
child_size: 2,
min_prefix_length: 2,
max_prefix_length: 1,
empty_child: vec![],
hash: 1,
},
RawInnerSpec {
child_order: vec![1],
child_size: 2,
min_prefix_length: -1,
max_prefix_length: 1,
empty_child: vec![],
hash: 1,
},
RawInnerSpec {
child_order: vec![1],
child_size: 2,
min_prefix_length: 1,
max_prefix_length: -1,
empty_child: vec![],
hash: 1,
},
RawInnerSpec {
child_order: vec![1],
child_size: 2,
min_prefix_length: -1,
max_prefix_length: -1,
empty_child: vec![],
hash: 1,
},
RawInnerSpec {
child_order: vec![1],
child_size: 2,
min_prefix_length: 2,
max_prefix_length: 1,
empty_child: vec![],
hash: 1,
},
];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parametrized cases from rstest here too 🙂

@rnbguy
Copy link
Collaborator

rnbguy commented Apr 12, 2024

hey. we had a discussion about the error scenarios for prefix_length and depth. we decided to go with only non-negative numbers.

So, the error conditions for:

  • [min_depth, max_depth] should be (0 < max_depth && 0 < min_depth && max_depth < min_depth) || max_depth < 0 || min_depth < 0.
  • [min_prefix_length, max_prefix_length] should be max_prefix_length < min_prefix_length || max_prefix_length < 0 || min_prefix_length < 0

sorry for any confusion from my earlier comments.

@rnbguy
Copy link
Collaborator

rnbguy commented Apr 13, 2024

can you give me permission to edit your PR? I want to make some changes before we merge.

@rnbguy
Copy link
Collaborator

rnbguy commented Apr 13, 2024

Ah, I just noticed that LeafOp is mentioned but you didn't add its conversion checks.

@tuantran1702
Copy link
Contributor Author

can you give me permission to edit your PR? I want to make some changes before we merge.

isaacs/github#1681 Yeah I guess I couldn't enable this, not able to find the option in my own PR. Could you kindly suggest the changes and I would resolve it asap.

Ah, I just noticed that LeafOp is mentioned but you didn't add its conversion checks.

I think there's no need to add conversion check for LeafOp because LeafOp's i32 fields hold enum value, thus limiting their value.

@rnbguy
Copy link
Collaborator

rnbguy commented Apr 15, 2024

Could you kindly suggest the changes and I would resolve it asap.

Ah, I wasn't aware. I pushed changes to my branch rano/pr/1160. It's rebased from your fork - so you can just git pull <remote for cosmos/ibc-rs> rano/pr/1160

LeafOp

The enum values should be validated. I added the respective changes at my branch.

@rnbguy rnbguy changed the title Imp(ics23): Add conversion checks imp(ics23): fallible conversion for ProofSpec, LeafOp, InnerSpec Apr 15, 2024
Copy link
Collaborator

@rnbguy rnbguy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @tropicaldog ! 🙏

Copy link
Member

@Farhad-Shabani Farhad-Shabani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Thank you!

@Farhad-Shabani Farhad-Shabani added this pull request to the merge queue Apr 16, 2024
Merged via the queue into cosmos:main with commit 45d3250 Apr 16, 2024
15 checks passed
Farhad-Shabani pushed a commit that referenced this pull request Sep 9, 2024
#1160)

* feat(ics23): add conversion checks

* fix compiler error

* comment out depth range tests

* Update ibc-core/ics23-commitment/types/src/specs.rs

Co-authored-by: Rano | Ranadeep <[email protected]>
Signed-off-by: Tuan Tran <[email protected]>

* Update ibc-core/ics23-commitment/types/src/specs.rs

fix for consistency

Co-authored-by: Rano | Ranadeep <[email protected]>
Signed-off-by: Tuan Tran <[email protected]>

* add tests and linting

* refactor loop

* Update ibc-core/ics23-commitment/types/src/specs.rs

Co-authored-by: Rano | Ranadeep <[email protected]>
Signed-off-by: Tuan Tran <[email protected]>

* Update ibc-core/ics23-commitment/types/src/specs.rs

Co-authored-by: Rano | Ranadeep <[email protected]>
Signed-off-by: Tuan Tran <[email protected]>

* add parameterized test

* Update ibc-core/ics23-commitment/types/src/specs.rs

Co-authored-by: Rano | Ranadeep <[email protected]>
Signed-off-by: Tuan Tran <[email protected]>

* update err comment

* update tests

* add rstest in dev-deps

* code opt

* add HashOp and LengthOp validations

* code opt

* update the range validation predicates and comments

* empty proof specs are disallowed

* rename test fn

* update test cases

---------

Signed-off-by: Tuan Tran <[email protected]>
Co-authored-by: Rano | Ranadeep <[email protected]>
Co-authored-by: Ranadeep Biswas <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[ICS23] add conversion checks for ProofSpec, LeafOp, and InnerSpec structs
3 participants