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

Prototype of BFT abstractions and Streamlet; add static type checking #22

Merged
merged 9 commits into from
Dec 7, 2023

Conversation

daira
Copy link
Collaborator

@daira daira commented Oct 23, 2023

fixes #6
fixes #23

@daira daira added the enhancement New feature or request label Oct 23, 2023
simtfl/bft/__init__.py Outdated Show resolved Hide resolved

for i in range(2):
proposal = PermissionedBFTProposal(current)
self.assertTrue(proposal.is_valid())
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
self.assertTrue(proposal.is_valid())
proposal.assert_valid()
self.assertTrue(proposal.is_valid())

Copy link
Contributor

Choose a reason for hiding this comment

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

Why are both lines necessary? Is this "verification-in-depth" which redundantly checks the same condition through different code paths, or are those checks intentionally distinct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We call proposal.assert_valid() first because if the proposal is (incorrectly) not valid, that will tell us why — whereas is_valid() will catch the exception and lose error information. Then we test that is_valid() is implemented correctly for the True case.

Copy link
Contributor

Choose a reason for hiding this comment

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

I still don't understand the second statement.

Aren't the two lines entirely equivalent, so long as assert_valid is defined as follows?

def assert_valid(self):
  assert self.is_valid()

I just looked it up, and it seems equivalent, though the dependency is inverted so we have:

    def is_valid(self) -> bool:
        """Is this proposal valid?"""
        try:
            self.assert_valid()
            return True
        except AssertionError:
            return False

My question is "is there ever a case where assert_valid and is_valid will not be entirely equivalent modulo boolean return vs raising AssertionError?

That could be the case if a subclass of PermissionedBFTProposal overrides both methods and makes them logically non-equivalent. So I would refine my question to these two clauses:

  • Is it possible / useful for subclasses to override these two methods in a manner in which they aren't logically equivalent (modulo raise-vs-return)?
  • If not, is the purpose of these two lines to ensure all subclasses have implemented those two methods as logically equivalent (module raise-vs-return)?

If the answer to the first clause is 'no', then we could add a doc string or maybe a type signature to def is_valid to prohibit overriding that method as a maintenance improvement / clarification.

@daira daira force-pushed the bft-abstractions branch 3 times, most recently from 460715e to 0163018 Compare October 25, 2023 16:57
Signed-off-by: Daira Emma Hopwood <[email protected]>
Signed-off-by: Daira Emma Hopwood <[email protected]>
@daira daira marked this pull request as ready for review December 5, 2023 19:38
@daira daira changed the title Prototype of BFT abstractions Prototype of BFT abstractions and Streamlet Dec 5, 2023
Co-authored-by: Nate Wilcox <[email protected]>
Signed-off-by: Daira Emma Hopwood <[email protected]>
@daira daira force-pushed the bft-abstractions branch 4 times, most recently from 297a96b to 01aa384 Compare December 6, 2023 00:47
@daira daira changed the title Prototype of BFT abstractions and Streamlet Prototype of BFT abstractions and Streamlet; add static type checking Dec 6, 2023
Enforce the annotations in `check.sh` using `pyanalyze`.

Signed-off-by: Daira Emma Hopwood <[email protected]>
Copy link
Contributor

@nathan-at-least nathan-at-least left a comment

Choose a reason for hiding this comment

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

UtACK, with one (repeated) clarification question.

Type annotations are super helpful for me! Thanks.


for i in range(2):
proposal = PermissionedBFTProposal(current)
self.assertTrue(proposal.is_valid())
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are both lines necessary? Is this "verification-in-depth" which redundantly checks the same condition through different code paths, or are those checks intentionally distinct?

simtfl/bft/__init__.py Show resolved Hide resolved
@daira daira merged commit a1641c8 into Electric-Coin-Company:main Dec 7, 2023
2 checks passed
@daira daira deleted the bft-abstractions branch December 7, 2023 11:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add static type annotations and checking Define BFT abstractions and Streamlet (honest behaviour only)
2 participants