RFC: Add exhaustive test for 2-of-2 musig [WIP] #1615
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR attempts to add an exhaustive test for 2-of-2 signature aggregation via MuSig2. Currently, only the combinations of each participant's possible signing keys are fully iterated, and other involved cryptographic elements (generated nonces, signing challenge etc.) are either derived from a counter or statically set. Some invalid conditions that are practically unreachable on the full group order for secp256k1 (due to negligible probablity) can obviously hit for the exhaustive group test orders, so some special treatment is needed here to avoid a crash in the test. Those three conditions are:
secp256k1_musig_pubkey_agg
):secp256k1/src/modules/musig/keyagg_impl.h
Lines 216 to 217 in a88aa93
→ the PR copes with that by letting the function return 0 instead if the condition hits and we compile for exhaustive tests, and skip the current iteration at the call-site in that case
secp256k1_musig_nonce_gen{,_counter}
):secp256k1/src/modules/musig/session_impl.h
Lines 442 to 443 in a88aa93
→ the PR copes with that by letting the function return 0 instead if the condition hits and we compile for exhaustive tests, and try to generate a nonce another time with different input (increased counter), until it succeeds
secp256k1_musig_nonce_process
):secp256k1/src/modules/musig/session_impl.h
Lines 601 to 603 in a88aa93
This one was a bit tricky. On the full group order, this condition can only be true if both of the aggregated nonce group elements (which are supplied externally) are the point at infinity (encoded as 66 zero-bytes), caused by either a dishonest nonce aggregator or dishonest signer, see https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki#user-content-Dealing_with_Infinity_in_Nonce_Aggregation. On the reduced group orders, this can hit frequently, making the aggregated signature verification fail in the end.
→ the PR copes with that by checking if the final nonce is G (when possibly a reduction has happened) and skip signing/verification then. that's a bit hacky and skips also legit cases (i.e. we arrive at G for the final nonce without the reduction being involved), but works for now :-)
I'm asking for general comments at this point what would make the most sense in an exhaustive musig test, or if it is even worth it to have one at all. If yes, is it a good idea to change function behaviour depending on exhaustive tests being compiled? Are there other solutions that I haven't thought of? It's also a bit strange that some iterations are skipped, so there should probably an extra check at the end (right now if all iterations are skipped, we wouldn't even notice it, apart from the WIP-printf output). I guess the basic idea of the PR is still slightly better than having nothing, but still far away from what we would want ideally.
Number of full iterations (i.e. nothing is skipped due to any condition described above) depending on the exhaustive test order: