-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Increase precision of g1 and g2. #822
Increase precision of g1 and g2. #822
Conversation
This allows us to shift by 256+128 = 384 bits, which is a multiple of the limb size of the scalar representation. This also happens to be the most precision possible for g2 that still fits into a 256-bit value.
Historically speaking the values of Instead there is a very slight advantage of shifting by a multiple of the limb size. |
a582c3f
to
d6cc066
Compare
I've updated the proof. Please note that |
I've added a Be aware that the verification fails with GCC 9.3 and GCC 10.2 because these compilers are badly broken. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95189. |
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.
Nice. I can create a follow up PR to add a sage script that computes all the constants here.
One could write optimized multiplication routines for the current shorter g1
, g2
. But that's a lot of work for a tiny bit of performance so unless we have this, I agree that the new constants are an improvement.
Yeah, I don't think we want "expected failures". But tbh, I don't know what to do. We could disable the tests for these GCC versions but this is not a good idea either. We could also write our own memcmp for the tests but this is strange, too. |
What would you do if we already had such a test in place before GCC released their broken compilers? Keep in mind these broken compilers are already compromising our existing tests @ Lines 3458 to 3460 in 770b3dc
|
@roconnor-blockstream That's different. If the test succeeds incorrectly, then that's a problem because that single test does not work. And yes, maybe we should fix this. If the tests fail incorrectly, it's much worse. Then the test binary aborts early and a lot of the tests are simply skipped. Moreover, people will be trained to ignore failing tests / Travis, which is bad. |
What about the other memcmp's we have in actual production code? (bip340 tag, tweak add check, scratch impl, sha256 selftest) does this bug affect those too? |
The fix for the tests that succeed incorrectly is the same as for fixing these tests. Stop using GCC 9.3 and 10.2 or find some flags to disable the use of intrinsics for memcmp for those particular compiler versions that are broken. Making code accommodations for compilers with such egregious errors doesn't seem reasonable to me. |
I agree.
We're not in control. We control our code, not the compiler. We can blacklist these compilers but that's ugly and people would override it.
|
I propose we argue about |
Concept ACK, but the test cannot be included as is-- not even in a couple weeks because the broken compilers have been massively shipped and some users will still be running them for a couple of years (e.g. imagine you setup an offline signer using install media...). At a minimum the tests should add an explicit memcmp bug test so that the error the user gets is a useful report that tells them that their compiler is faulty and not all other tests are bypassed in case the user wants to continue with the broken compiler. But I think the library should probably ship a workaround (see my comments in #823). And congrats on finding a compiler bug (though you weren't the first in the case)-- good testing (sadly) finds compiler bugs. The fact that none of the other tests find this suggest to me that there isn't enough mutation testing going on here (or we just got really unlucky, and none of the mutation hittable differences with constant comparisons have an early null). |
We can for sure have better mutation testing but in our defense, we use secp256k1/src/modules/extrakeys/tests_impl.h Line 432 in d7838ba
But in this case, GCC emits a memcmp call, and I can't convince it to emit wrong code. It's not that easy to hit this bug, it seems to depend on specific contexts and optimizations.
|
d6cc066
to
a765e35
Compare
Tests now pass. 😠 |
a765e35
to
d91408e
Compare
utACK d91408e |
If we want to add unit tests for lambda splitting that result in numbers very close to the bound:
I found these by randomly generating r1 values (within range 0..k1_bound) and r2 values (very close to k2_bound) such that split(r1+lambda*r2)=(r1,r2), and observing that valid r1 values were within a very small range. As I brought r2 closer and closer to k2_bound, the range became narrowing, making it easy to see where it converges. Turns out that it works all the way up to k2_bound-1. The same approach works for r1 very close to k1_bound, except it needs r2 values in range (-k2_bound...0). There it actually lets us go to k1_bound itself. |
That scalar that creates maximal values might be a useful scalar for ecmult tests and as a private key for ECDH too bad you don't achieve the k2_bound. |
Here is a commit to add tests for splitting and EC multiplications with those scalars: https://github.com/sipa/secp256k1/commits/202009_pr822. The endomorphism test fails when I introduce small deviations in g1/g2 (though only when the error is around ~2^128 at least). Feel free to cherry pick, or I can open as a separate PR later. |
As it appears that all these large-output values follow a simple pattern ( |
Should I add
? |
I don't have strong opinions (and I assume noone has). If you add it, I'll remove it in #825 . :P |
If we expect to merge #825 afterwards, no need. |
d91408e
to
341196c
Compare
I added the include of I expect the k2_bound is unachievable. With some effort could probably enumerate the few possible candidate points that could possibly achieve the k2_bound and inspect them to eliminate them as possibilities. |
looks good to me |
ACK 57d4b0d Reviewed the diff with the earlier version, created a merge of this with #826 and built/tested it (40000 runs of the unit tests with it). @roconnor-blockstream It's my belief that the k2_bound is indeed unreachable; if it was, one of the inputs in the |
For your consideration, I've made some test improvements: https://github.com/gmaxwell/secp256k1/commit/6c3e1fab91766aa0c424b678371a0c8099726655 |
The bounds check in secp256k1_scalar_split_lambda_verify now doesn't avoid triggering the GCC bug, it just falsely passes in the presence of it (e.g. set the two bounds to all zeros and it keeps passing). Not ideal considering essentially all developers are using impacted compilers. I didn't realize this at first and burnt a few cpu years running tests that could not fail. It appears to be right with the code in #825. |
Is it expected to see any meaningful difference in performance here? because I can't see any in the benchmakrs |
No, this just saves a few instructions and we run this only once per ecmult. |
c582aba Consistency improvements to the comments (Pieter Wuille) 63c6b71 Reorder comments/function around scalar_split_lambda (Pieter Wuille) 2edc514 WNAF of lambda_split output has max size 129 (Pieter Wuille) 4232e5b Rip out non-endomorphism code (Pieter Wuille) ebad841 Check correctness of lambda split without -DVERIFY (Gregory Maxwell) fe7fc1f Make lambda constant accessible (Pieter Wuille) 9d2f2b4 Add tests to exercise lambda split near bounds (Pieter Wuille) 9aca2f7 Add secp256k1_split_lambda_verify (Russell O'Connor) acab934 Detailed comments for secp256k1_scalar_split_lambda (Russell O'Connor) 76ed922 Increase precision of g1 and g2 (Russell O'Connor) 6173839 Switch to our own memcmp function (Tim Ruffing) Pull request description: This is a rebased/combined version of the following pull requests/commits with minor changes: * #825 Switch to our own memcmp function * Modification: `secp256k1_memcmp_var` is marked static inline * Modification: also replace `memcmp` with `secp256k1_memcmp_var` in exhaustive tests * Modification: add reference to GCC bug 95189 * #822 Increase precision of g1 and g2 * Modification: use the new `secp256k1_memcmp_var` function instead of `memcmp` (see #822 (comment)) * Modification: drop the " Allow secp256k1_split_lambda_verify to pass even in the presence of GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95189." commit, as it's dealt with using `secp256k1_memcmp_var`. * Modification: rename secp256k1_gej_mul_lambda -> secp256k1_ge_mul_lambda * A new commit that moves the `lambda` constant out of `secp256k1_scalar_split_lambda` and (`_verify`). * The test commit suggested here: #822 (comment) * Modification: use the new accessible `secp256k1_const_lambda` instead of duplicating it. * #826 Rip out non-endomorphism code * A new commit that reduces the size of the WNAF output to 129, as we now have proof that the split output is always 128 bits or less. * A new commit to more consistently use input:`k`, integer outputs:`k1`,`k2`, modulo n outputs:`r1`,`r2` ACKs for top commit: real-or-random: ACK c582aba code inspection, some tests, verified the new g1/g2 constants jonasnick: ACK c582aba didn't verify the proof Tree-SHA512: 323a3ee3884b7ac4fa85c8e7b785111b5c0638d718bc1c805a38963c87411e81a746c98e9a42a3e2197ab34a874544de5cc51326955d1c4d0ea45afd418e819f
Merged as part of #830. |
This allows us to shift by 256+128 = 384 bits, which is a multiple of the limb size of the scalar representation.
This also happens to be the most precision possible for g2 that still fits into a 256-bit value.