-
Notifications
You must be signed in to change notification settings - Fork 71
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
Conversation
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. |
Yes, I think it's just |
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
There was a problem hiding this 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, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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]]: |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious, why?
There was a problem hiding this comment.
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): |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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]] |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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
There was a problem hiding this 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.
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. |
What do you all think about addressing the request for changes in a future PR? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐧
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
- Skippedparams.py
point.py
pre.py
signing.py
utils.py
See: #183