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

PEP 484 Type Hints for pyUmbral #189

Merged
merged 5 commits into from
Jul 9, 2018
Merged

Conversation

KPrasch
Copy link
Member

@KPrasch KPrasch commented Jul 6, 2018

Goal

Passing mypy checks, PEP 484 compliance.

Adds type annotations to the following modules:
  • _pre.py
  • config.py
  • curvebn.py
  • dem.py
  • fragments.py
  • keys.py
  • opensll.py - Skipped
  • params.py
  • point.py
  • pre.py
  • signing.py
  • utils.py

See: #183

@KPrasch
Copy link
Member Author

KPrasch commented Jul 7, 2018

The remaining modules (curvebn, openssl, and point) use ctypes that are a little harder to annotate. Perhaps we can introduce types with > 1 Pull Request.

@tuxxy
Copy link
Contributor

tuxxy commented Jul 7, 2018

The remaining modules (curvebn, openssl, and point) use ctypes that are a little harder to annotate.

Yes, I think it's just CData. Given the generic name, I have tried to name the params to be similar to the C structs that are passed in. IE: EC_GROUP.

@KPrasch
Copy link
Member Author

KPrasch commented Jul 8, 2018

We dont have 100% coverage or accuracy - but mypy errors have been vastly reduced.

I'd like to take this PR off WIP while we work on annotating the remaining parts of the codebase in a future PR.

@KPrasch KPrasch changed the title [WIP] PEP 484 Type Hints for pyUmbral PEP 484 Type Hints for pyUmbral Jul 8, 2018
Copy link

@michwill michwill left a comment

Choose a reason for hiding this comment

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

Looks great!

Copy link
Member

@cygnusv cygnusv 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, @KPrasch!! Just some minor comments here and there.

delegating_pubkey: UmbralPublicKey,
signing_pubkey,
signing_pubkey: UmbralPublicKey,
Copy link
Member

Choose a reason for hiding this comment

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

This was deliberately left without type annotation, since strictly speaking, it shouldn't be an UmbralPublicKey. Umbral keys should only be used for encryption & delegation. The problem is that our current implementation of Signature uses, temporarily, UmbralPublicKey. AFAIK, that's something that will change after testnet, because it has a low priority.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, what shall we do in the meantime?

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree - a big part of the point was to make this swappable. It's not obvious to me what the "correct" type is here; situations like this make me questions the underlying wisdom of the type hint system, because what we're attempting to do here is, IMO, in the best spirit of the dynamic / duck-typed tradition of python.

Copy link
Member Author

@KPrasch KPrasch Jul 9, 2018

Choose a reason for hiding this comment

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

Yep - looks like we need to implement a custom subprotocol: https://mypy.readthedocs.io/en/latest/protocols.html#simple-user-defined-protocols

umbral/config.py Outdated
if not cls.__params:
cls.__set_curve_by_default()
return cls.__params

@classmethod
def curve(cls):
def curve(cls) -> Union[Type[SECP256R1], Type[SECP256K1]]:
Copy link
Member

Choose a reason for hiding this comment

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

Also, SECP384R1. And I know this is commutative, but how about putting SECP256K1 first?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah - Sounds like a good Idea - we need a single sourced alias for curves, IMO

umbral/config.py Outdated
return _CONFIG.set_curve(curve)


def default_curve():
def default_curve() -> Union[Type[SECP256R1], Type[SECP256K1]]:
return _CONFIG.curve()
Copy link
Member

Choose a reason for hiding this comment

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

Same here.

@@ -69,19 +69,19 @@ def to_bytes(self):
return self._id + key + ni + commitment + xcoord + signature

def verify(self,
signing_pubkey,
signing_pubkey: UmbralPublicKey,
Copy link
Member

Choose a reason for hiding this comment

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

Same as above. Now thinking that creating an issue and adding a related TODO can be the best way forward.

Copy link
Member Author

Choose a reason for hiding this comment

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

Perhaps a type alias, skip, or Any will suffice

bn_sig: Optional[Union[int, CurveBN]] = None,
point_e_prime: Optional[Point] = None,
point_v_prime: Optional[Union[int, Point]] = None,
point_noninteractive: Optional[Union[int, Point]] = None,
Copy link
Member

Choose a reason for hiding this comment

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

All Points above are just Optional[Point], not Optional[Union[int, Point]]. Same for bn_sig, but with CurveBN.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah - @jMyles and were are a bit stumped on how int is passed here during test-runtime.

@@ -177,7 +180,8 @@ def verify(self) -> bool:
s = self._bn_sig
h = CurveBN.hash(e, v, params=self._umbral_params)

return s * g == v + (h * e)
result = s * g == v + (h * e) # type: bool
Copy link
Member

Choose a reason for hiding this comment

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

Isn't this redundant? We already said above that the result is bool.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah - perhaps redundant - Looking for precision on the charts, the return value type and the return type of the arithmetic operators are different.

Copy link
Member

Choose a reason for hiding this comment

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

Different? I don't see why they're different.

@@ -260,15 +264,16 @@ def __eq__(self, other):
# Again, it's hard to imagine why.
return False

def __hash__(self):
@typing.no_type_check
Copy link
Member

Choose a reason for hiding this comment

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

Just curious, why?

Copy link
Member Author

Choose a reason for hiding this comment

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

there is a tricky check inside the genexp here.

@@ -81,22 +82,22 @@ def __len__(self):
def __add__(self, other):
Copy link
Member

@cygnusv cygnusv Jul 8, 2018

Choose a reason for hiding this comment

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

Why __add__ and __len__ don't have type hints, but __bytes__, __radd__, and __eq__ do?

Copy link
Member Author

Choose a reason for hiding this comment

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

other than __eq__, They just haven't been covered yet. As for __eq__ an implementation change may be needed as __eq__ needs to be able to take any object.

umbral/utils.py Outdated
from umbral import openssl

def lambda_coeff(id_i, selected_ids):
CurveTypes = Union[Type[SECP256K1], Type[SECP192R1], Type[SECP384R1], Type[SECP256R1]]
Copy link
Member

Choose a reason for hiding this comment

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

We can get rid of SECP192R1.

Copy link
Member Author

Choose a reason for hiding this comment

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

Well, it's a type that is passed in during test runtime, an it needs to be included in the annotation for it to pass type checks. Perhaps we need curves type-aliases

Copy link
Contributor

@tuxxy tuxxy left a comment

Choose a reason for hiding this comment

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

Looks great! I agree with @cygnusv's review. Those changes and I'll approve.

@KPrasch
Copy link
Member Author

KPrasch commented Jul 8, 2018

Cool - Ill peck away at the changes.

Feel free to add more comments - I combed through the changeset - but much of the annotations were auto-generated with monkeytype so more eyes on the code is a good thing.

@KPrasch
Copy link
Member Author

KPrasch commented Jul 9, 2018

What do you all think about addressing the request for changes in a future PR?

Copy link
Contributor

@tuxxy tuxxy left a comment

Choose a reason for hiding this comment

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

🐧

@tuxxy tuxxy merged commit 23bc511 into nucypher:master Jul 9, 2018
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.

5 participants