Improve handling of parity integer#344
Conversation
|
I agree that Even/Odd would be nicer in general but:
Parity should mean 0 is even. But yeah, I believe this is the problem with this change. rust-secp256k1 should be compatible with rust-secp256k1, and if upstream uses a parity bit, then we should do the same. Because only then users can be sure that if the bit is the same, they get the same result on rust-secp256k1 and on secp256k1. Maybe we can convince upstream to rename parity to |
|
Thanks for the review @real-or-random. I get your intention, users of Would you be happy with something like this: |
nit, boolean values don't exist in C89, so this int actually is equivalent to a bool in rust as it is documented to be used as a bool (only 1/0) I personally wouldn't be against adding an enum, but I'd prefer if we can somehow not expose "even/odd" terminology to the user at all and somehow create an abstraction above this, as users IMO shouldn't know what even/odd means |
|
concept ACK using an enum for this. @tcharding is right that we already change the type from an Edit: oh, I misunderstood. I thought this was talking about key compressedness rather than parity. For parity I also think we should have an enum, but it needs to have explicit conversion functions between the numeric value (which is encoded in some places) and the enum. |
The import statements can be simplified by using an import wildcard (`super::*`). While we are at it put them in std, external crate, this crate order.
There are currently two unit tests in the `schnorr` module that are testing keys from the `key` module. This is possible because the tests are only testing the public interface, none the less they are better placed in the `key` module.
We have two `tweak_add_assign` methods (one for keypair and one for x-only pubkey). Both check the return value from a FFI function call. We can make both sites uniform to _slightly_ reduce cognitive load when reading the code. Use C style code to make it obvious to readers that this is basically C code.
@apoelstra can you please confirm that I've got all the encodings you refer to. I grepped for the function names involved and I believe I've got them all. |
Two functions in the FFI secp code return and accept a parity int. Currently we are manually converting this to a bool. Doing so forces readers of the code to think what the bool means even though understanding this bool is not needed since in is just passed back down to the FFI code. We can abstract this away by using an opaque type to hold the original int and not converting it to a boolean value. Add 'Return' and 'Error' sections to `tweak_add_assign` while fixing the docs to describe the new opaque parity type.
It is not immediately apparent what 'err == 1' means, one must determine that the FFI function call returns 1 for success. We can help readers of the code by adding a 'Return' section to the method documentation. Add trailing full stop to method docs initial line also.
apoelstra
left a comment
There was a problem hiding this comment.
ACK ede114f
This looks good to me. I haven't been involved with this API upstream so I'm probably not the best person to ask about having gotten all the conversion sites, but I think you did. (I grepped for some variations of {1} or {true} which would indicate an int->boolean conversion, and didn't find any.)
|
I actually liked that it was a single byte and that we didn't expose that |
|
I wouldn't mind changing the conversion function to go to/from a |
In rust-bitcoin, i32::from(self.output_key_parity) as u8 | self.leaf_version.as_u8() This is not the end of the world. Maybe in the next release, we can have a custom enum |
|
I think a u8 would be more conceptually clear. |
|
Why not a custom enum? |
|
post merge review: I'm not entirely convinced that a opaque type is useful here. You can't even XOR two parities which seems to be no so uncommon in advanced signing constructions. (If more is added to tweaking, e.g., musig). Not sure if really the user needs to access the value but on the other hand, I don't see how this opaque value is any safer than a bool. |
|
We could implement xor on this type. That's a pretty good idea. @real-or-random 'because a bool has no intrinsic meaning and does not "naturally" map to the two parity classes of elliptic curve points. |
In which case, we should update the constructors From to be fallible ones. |
|
So I think, for now we can simply
And we can do all this in a minor release. Later we can replace the underlying type with an enum so users can directly see "even" or "odd". |
|
So shell we have a point release addressing this together with #364? |
|
Yep |
…eger
ede114fb1a82206824dc678c3ea1a19df718f41d Improve docs on tweak_add_check method (Tobin Harding)
fbc64c77252e86100a657fa3d381b36c22eeb48e Add opaque parity type (Tobin Harding)
1b768b2749f2b3508f44ad875e99968a7a1eb268 Make tweak_add_assign return statements uniform (Tobin Harding)
edafb88f8c6b9f8f21b253621cd5ecbf1e2bffd1 Move key unit tests to key module (Tobin Harding)
e3d21a3d87614980f840bd50ed3cb387d06381c4 Clean up test imports with key module (Tobin Harding)
Pull request description:
Two functions in the FFI secp code return and accept a parity integer.
Currently we are manually converting this to a bool. Doing so forces readers of the code to think what the bool means even though understanding this value is not needed since in is just passed back down to the FFI code.
We initially tried to solve this issue by adding an enum, discussion below refers to that version. Instead of an enum we can solve this issue by adding an opaque type that holds the parity value returned by the FFI function call and then just pass it back down to FFI code without devs needing to know what the value should be. This fully abstracts the value away and removes the boolean conversion code which must otherwise be read by each dev.
- Patch 1 and 2 improve unit tests that test the code path modified by this PR
- Patch 3 trivially changes code to be uniform between two similar methods (`tweak_add_assign`)
- Patch 4 is the meat and potatoes (main part of PR :)
- Patch 5 is docs improvements to code in the area of this PR
ACKs for top commit:
apoelstra:
ACK ede114fb1a82206824dc678c3ea1a19df718f41d
Tree-SHA512: 37843e066d9006c5daa30dece9f7eb7a802864b85606e43ed2651c6d55938c4f884cc4abab81eccb69685f6eda918a9b9ba57bf1a4efec41e89239b99ae2b726
…eger
ede114fb1a82206824dc678c3ea1a19df718f41d Improve docs on tweak_add_check method (Tobin Harding)
fbc64c77252e86100a657fa3d381b36c22eeb48e Add opaque parity type (Tobin Harding)
1b768b2749f2b3508f44ad875e99968a7a1eb268 Make tweak_add_assign return statements uniform (Tobin Harding)
edafb88f8c6b9f8f21b253621cd5ecbf1e2bffd1 Move key unit tests to key module (Tobin Harding)
e3d21a3d87614980f840bd50ed3cb387d06381c4 Clean up test imports with key module (Tobin Harding)
Pull request description:
Two functions in the FFI secp code return and accept a parity integer.
Currently we are manually converting this to a bool. Doing so forces readers of the code to think what the bool means even though understanding this value is not needed since in is just passed back down to the FFI code.
We initially tried to solve this issue by adding an enum, discussion below refers to that version. Instead of an enum we can solve this issue by adding an opaque type that holds the parity value returned by the FFI function call and then just pass it back down to FFI code without devs needing to know what the value should be. This fully abstracts the value away and removes the boolean conversion code which must otherwise be read by each dev.
- Patch 1 and 2 improve unit tests that test the code path modified by this PR
- Patch 3 trivially changes code to be uniform between two similar methods (`tweak_add_assign`)
- Patch 4 is the meat and potatoes (main part of PR :)
- Patch 5 is docs improvements to code in the area of this PR
ACKs for top commit:
apoelstra:
ACK ede114fb1a82206824dc678c3ea1a19df718f41d
Tree-SHA512: 37843e066d9006c5daa30dece9f7eb7a802864b85606e43ed2651c6d55938c4f884cc4abab81eccb69685f6eda918a9b9ba57bf1a4efec41e89239b99ae2b726
Two functions in the FFI secp code return and accept a parity integer.
Currently we are manually converting this to a bool. Doing so forces readers of the code to think what the bool means even though understanding this value is not needed since in is just passed back down to the FFI code.
We initially tried to solve this issue by adding an enum, discussion below refers to that version. Instead of an enum we can solve this issue by adding an opaque type that holds the parity value returned by the FFI function call and then just pass it back down to FFI code without devs needing to know what the value should be. This fully abstracts the value away and removes the boolean conversion code which must otherwise be read by each dev.
tweak_add_assign)