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

New validation for keeper fields #740

Merged
merged 9 commits into from
Feb 21, 2023
Merged

New validation for keeper fields #740

merged 9 commits into from
Feb 21, 2023

Conversation

shaspitz
Copy link
Contributor

@shaspitz shaspitz commented Feb 15, 2023

Description

cosmos/gaia#2197 fixed an incorrect ordering of keeper initialization in gaia's app.go. Before Simon's fix, gaia's ccv provider keeper held a pointer reference to a zeroed (outdated) external keeper. In short, ccv keepers should never have references to nil pointers, or references to concrete types which are zero-valued for that type. This PR adds a test which validates what I've described.

This new test would have caught the mentioned evidence keeper bug, and will hopefully prevent new bugs or regressions of this same kind in the future.

To confirm test behavior, I've created two gaia branches that import this PR's ICS branch, see comparison. One branch does fail w/o Simon's fix, and the other branch passes w/ the fix

Type of change

  • Testing: Adds testing

Regression tests

n/a

New behavior tests

n/a

@shaspitz shaspitz marked this pull request as ready for review February 15, 2023 22:08
Copy link
Contributor

@sainoe sainoe left a comment

Choose a reason for hiding this comment

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

Great work @smarshall-spitzbart

Copy link
Contributor

@MSalopek MSalopek left a comment

Choose a reason for hiding this comment

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

Thank you for raising the issue and going through all this effort!

I understand the concern, but please consider making a validator func instead of exposing private fields.

The provided tests are already checking that the fields are not zero values.

x/ccv/provider/keeper/keeper.go Outdated Show resolved Hide resolved
@shaspitz
Copy link
Contributor Author

The provided tests are already checking that the fields are not zero values.

This is not true, as no e2e test caught the evidence keeper bug. All e2e tests have to be manually crafted and its easy to overlook their use, especially for external contributors.

That being said, I'm not opposed to the idea of making this a runtime check with panics instead of a test

@MSalopek
Copy link
Contributor

The provided tests are already checking that the fields are not zero values.

This is not true, as no e2e test caught the evidence keeper bug. All e2e tests have to be manually crafted and its easy to overlook their use, especially for external contributors.

That being said, I'm not opposed to the idea of making this a runtime check with panics instead of a test

Meant to say:

the tests provided in this PR are only checking for zero values

Apologies for my bad english

@shaspitz shaspitz changed the title New test for keeper fields New validation for keeper fields Feb 16, 2023
@shaspitz
Copy link
Contributor Author

@MSalopek thanks for the feedback! The panic design is indeed better than what I first designed, now we don't have to expose private fields. I've updated the PR accordingly, and updated the gaia branches originally mentioned in the PR description. The gaia branches pass/fail as expected 👍

@shaspitz shaspitz requested a review from MSalopek February 16, 2023 18:29
Copy link
Contributor

@MSalopek MSalopek left a comment

Choose a reason for hiding this comment

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

@smarshall-spitzbart Thank you for updating the PR!


// Validates that the provider keeper is initialized with non-zero and
// non-nil values for all its fields. Otherwise this method will panic.
func (k Keeper) mustValidateFields() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Wondering in the future if it's worth refactoring to have mustValidateFields be generic for keepers, then pass in a set of validations instead per keeper....

validations := map[string]func(Keeper) bool{
	"number of fields in provider keeper is not 13": func(keeper Keeper) bool { return reflect.ValueOf(k).NumField() != 13 },
	"cdc is zero-valued or nil": func(k Keeper) bool { return reflect.ValueOf(k.cdc).IsZero() },
	"storeKey is zero-valued or nil": func(keeper Keeper) bool { return reflect.ValueOf(k.storeKey).IsZero()},
}

...

func (k Keeper) mustValidateFields(validations map[string]func(Keeper) bool) {
	for errMessage, failedValidation := range validations {
		if failedValidation(k) {
			panic(errMessage)
		}
	}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a solid idea! Although in our repo there will only ever be 2 keepers defined, so maybe not worth adding the additional code and complexity? That sort of functionality living within the sdk repo would make the most sense to me.

Lmk if you strongly disagree and I can refactor in a future PR

@shaspitz shaspitz merged commit afd1b2b into main Feb 21, 2023
@shaspitz shaspitz deleted the test-external-keeper-refs branch February 21, 2023 19:17
@shaspitz shaspitz mentioned this pull request Mar 13, 2023
8 tasks
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.

4 participants