add secp256k1_ec_pubkey_cmp method#850
Conversation
|
Concept ACK I would be easier to simply have a Implementation is then just a call to |
|
I did think about this possibility, and if |
|
I don't feel strongly about it, I'm happy to implement the memcmp API if that's what people want. |
Oh it does. |
|
I also think that exposing a memcmp-like single API is somewhat nicer (but this is also ok) |
|
Oh, neat, I misread the memcmp_var code. Ok, I'll just expose a single function then. |
0831038 to
edcc076
Compare
secp256k1_ec_pubkey_equal and secp256k1_ec_pubkey_leq methodssecp256k1_ec_pubkey_cmp method
|
Replaced with a single _cmp method. |
|
@apoelstra may I ask what you intend to use this for? |
|
@jonasnick it's needed for the |
|
@apoelstra The |
|
sigh, ok, I guess we cannot support comparisons in this library |
I'm not sure that A sad thing is that this ordering won't be compatible with the lexicographical ordering on x-only keys... |
|
Ironically, sorting by uncompressed encoding would be compatible with x-only keys. |
|
actually, what about adding these to xonly_pubkey too? |
|
sure |
|
A week ago I argued that this is helpful but I'm not so sure anymore. If these functions are just serializing and memcmp'ing, they're not essential, so we could leave this to the user. Pro: The user has to make a deliberate choice on an ordering, which may be good a thing here as things are complicated. |
|
As a user I find it extremely irritating to need to serialize in order to compare keys for equality, so I think we should expose that....and then it's only epsilon more work to expose a total order. |
Agreed, equality is a no-brainer.
Indeed. But I think in common cases when you want an order, you need it because you're going to serialize anyway, so the user probably won't be extremely irritated in that case. @sipa @jonasnick @elichai What do you think? Should we expose a total order? (And if yes, which one? :P) |
|
@apoelstra Would it be useful to just have an equality test function? That avoids the rathole of trying to predict what ordering the user needs. |
|
Is there any actual opposition to merging this? Or just uncertainty about what ordering hypothetical users might want? We could definitely use the xonly stuff (which is unambiguous) downstream now for MuSig so it would be cool to merge this. |
|
If it would be easier, I can remove the legacy stuff and only add the xonly comparison? |
|
utACK 48ac53b This ordering is sufficiently natural that we can just merge it, I think. |
src/modules/extrakeys/main_impl.h
Outdated
|
|
||
| VERIFY_CHECK(ctx != NULL); | ||
| ARG_CHECK(pk1 != NULL); | ||
| ARG_CHECK(pk2 != NULL); |
There was a problem hiding this comment.
ARG_CHECK returns 0 for failure here, which isn't an appropriate return condition for a cmp function. You can use ARG_CHECK_NO_RETURN, but you won't have a post-condition that the pointer is non-NULL, and you will still need to handle that case. This can be done by zeroing the out1 and out2 buffers and only calling secp256k1_xonly_pubkey_serialize when pk is non NULL.
src/modules/extrakeys/main_impl.h
Outdated
| ARG_CHECK(pk1 != NULL); | ||
| ARG_CHECK(pk2 != NULL); | ||
|
|
||
| CHECK(secp256k1_xonly_pubkey_serialize(ctx, out1, pk1)); |
There was a problem hiding this comment.
Not sure why these are CHECK instead of VERIFY_CHECK.
There was a problem hiding this comment.
CHECK and VERIFY_CHECK are both not right here because they abort if the check fails, making it impossible to test the function with illegal keys. I'd suggest to remove the CHECK and instead make sure that out1 is all 0 if pubkey_serialize fails.
|
@apoelstra I wrote a fixup for this PR that makes the cmp functions define a consistent order even when dealing with NULL or illegal pubkeys by treating them as 0. It's used in libsecp-zkp's musig aggregation PR to add a sorting function for public keys. |
|
Oh CI fails again because this PR is too old and we switched to Cirrus CI. @apoelstra Can you quickly rebase this? This should solve it. |
c0eaa2a to
f86f026
Compare
| * Args: ctx: a secp256k1 context object. | ||
| * In: pubkey1: first public key to compare | ||
| * pubkey2: second public key to compare |
There was a problem hiding this comment.
We should add "(cannot be NULL)" here (and nit: full stops), same below
| * Args: ctx: a secp256k1 context object. | |
| * In: pubkey1: first public key to compare | |
| * pubkey2: second public key to compare | |
| * Args: ctx: a secp256k1 context object (cannot be NULL). | |
| * In: pubkey1: first public key to compare (cannot be NULL). | |
| * pubkey2: second public key to compare (cannot be NULL). |
There was a problem hiding this comment.
This is implicit as per the discussion in #783 (comment)
There was a problem hiding this comment.
Okay, yes. Strictly speaking, we first need to add the line Unless explicitly stated all pointer arguments must not be NULL. in the header file (as done in #783) because currently we promise that the illegal_callback is only called for violations explicitly mentioned in the header.
|
Tim and I noticed that the comparison functions can be simplified because pubkey_serialize already ARG_CHECKs pk != NULL. We can rely on that because we check it in the API tests. I pushed fixups that also add comments on the rationale and fix the nits mentioned in this thread. @apoelstra if you think that makes sense, feel free to cherry-pick and squash. |
|
@jonasnick Your branch looks good to me, I suggest we merge that one. |
f86f026 to
6eceec6
Compare
|
Squashed in jonas' commits. |
|
Code review ACK 6eceec6 |
| * Returns: <0 if the first public key is less than the second | ||
| * >0 if the first public key is greater than the second | ||
| * 0 if the two public keys are equal | ||
| * Args: ctx: a secp256k1 context object. |
There was a problem hiding this comment.
non-null comments here too?
There was a problem hiding this comment.
unnecessary if #926 gets merged (needs more ACKs :] )
…_cmp` Summary: Allows comparing `secp256k1_pubkey` and `secp256k1_xonly_pubkey` respectively, to establish an order between them. This is a backport of [[ bitcoin-core/secp256k1#850 | secp256k1#850 ]] and [[ bitcoin-core/secp256k1#926 | secp256k1#926 ]]. We need this for porting `rust-secp256k1` to the secp256k1 library of this repo. Test Plan: `ninja check-secp256k1` Reviewers: #bitcoin_abc, Fabien Reviewed By: #bitcoin_abc, Fabien Differential Revision: https://reviews.bitcoinabc.org/D16957
…_cmp` Summary: Allows comparing `secp256k1_pubkey` and `secp256k1_xonly_pubkey` respectively, to establish an order between them. This is a backport of [[ bitcoin-core/secp256k1#850 | secp256k1#850 ]] and [[ bitcoin-core/secp256k1#926 | secp256k1#926 ]]. We need this for porting `rust-secp256k1` to the secp256k1 library of this repo. Test Plan: `ninja check-secp256k1` Reviewers: #bitcoin_abc, Fabien Reviewed By: #bitcoin_abc, Fabien Differential Revision: https://reviews.bitcoinabc.org/D16957
…_cmp` Summary: Allows comparing `secp256k1_pubkey` and `secp256k1_xonly_pubkey` respectively, to establish an order between them. This is a backport of [[ bitcoin-core/secp256k1#850 | secp256k1#850 ]] and [[ bitcoin-core/secp256k1#926 | secp256k1#926 ]]. We need this for porting `rust-secp256k1` to the secp256k1 library of this repo. Test Plan: `ninja check-secp256k1` Reviewers: #bitcoin_abc, Fabien Reviewed By: #bitcoin_abc, Fabien Differential Revision: https://reviews.bitcoinabc.org/D16957
No description provided.