Skip to content
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

Add module "musig" that implements MuSig2 multi-signatures (BIP 327) #1479

Merged
merged 5 commits into from
Oct 7, 2024

Conversation

jonasnick
Copy link
Contributor

@jonasnick jonasnick commented Jan 6, 2024

EDIT: based on #1518. Closes #1452. Most of the code is a copy from libsecp256k1-zkp. The API added in this PR is identical with the exception of two modifications:

  1. I removed the unused scratch_space argument from secp256k1_musig_pubkey_agg. This argument was intended to allow using ecmult_multi algorithms for key aggregation in the future. But at this point it's unclear whether the scratch_space object will remain in its current form (see Rework or get rid of scratch space  #1302).
  2. Support for adaptor signatures was removed and therefore the adaptor argument of musig_nonce_process was also removed.

In contrast to the module in libsecp256k1-zkp, the module is non-experimental. I slightly cleaned up parts of the module, adjusted the code to the new definition of the VERIFY_CHECK macro and applied some simplifications that were possible because the module is now in the upstream repo (ge_from_bytes, ge_to_bytes). You can follow the changes I made to the libsecp256k1-zkp module at https://github.com/jonasnick/secp256k1-zkp/commits/musig2-upstream/.

src/secp256k1.c Outdated Show resolved Hide resolved
@jonasnick
Copy link
Contributor Author

Rebased on top of master to get #1480 which allowed dropping a commit. Old state is preserved at https://github.com/jonasnick/secp256k1/tree/musig2-module-backup.

Copy link
Contributor

@real-or-random real-or-random left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs rebase :)

include/secp256k1_extrakeys.h Outdated Show resolved Hide resolved
src/modules/musig/keyagg.h Outdated Show resolved Hide resolved
@t-bast
Copy link

t-bast commented Jan 23, 2024

FWIW, we have JVM bindings on top of this branch in ACINQ/secp256k1-kmp#93 and an implementation of swap-in-potentiam (musig2 key-path with alternative delayed script path) in ACINQ/bitcoin-kmp#107 and everything is working fine, and the API is easy enough to use!

@jonasnick
Copy link
Contributor Author

Rebased.

Thanks @t-bast, that's good to hear.

@siv2r
Copy link
Contributor

siv2r commented Feb 1, 2024

Attaching a visualization for the API flow.

musig2-api-flowchart

Edit: The above visualization is incorrect. I will update it with the correct one soon.

pubkeys_ptr[i] = &signers[i].pubkey;
}
printf("ok\n");
printf("Combining public keys...");
Copy link
Contributor

@siv2r siv2r Feb 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we recommend that users sort their pubkeys before aggregating them? The musig_pubkey_agg API documentation simply says the user "can" do it.

If we recommend the sorting step, including it in the example file would be helpful.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's no catch-all recommendation. BIP327 says "The aggregate public key produced by KeyAgg (regardless of the type) depends on the order of the individual public keys. If the application does not have a canonical order of the signers, the individual public keys can be sorted with the KeySort algorithm to ensure that the aggregate public key is independent of the order of signers."

In other words: If in your application, the collection of pubkeys (or signers represented by them) is conceptually an (ordered) list, then don't bother with sorting. If in your application, the collection of pubkeys is conceptually an (unordered) set, i.e., the application doesn't want to care about the order of pubkeys, then sort to make sure the set has a canonical serialization.

Perhaps we can explain this somewhere in more detail, either in the API docs or in the example.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think it would be nice to including sorting in the example for the following reasons:

  • It provides a practical example on how to use the sorting API
  • It's a good hook for adding a comment explaining what @real-or-random just explained above. Feels a bit nicer to have that comment in the example, vs the API docs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added sorting and a comment.

include/secp256k1_musig.h Outdated Show resolved Hide resolved
include/secp256k1_musig.h Outdated Show resolved Hide resolved
include/secp256k1_musig.h Outdated Show resolved Hide resolved
Copy link
Member

@josibake josibake left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also using the heapsort commits in #1471. What do you think about splitting out the sort commits into their own PR? Also fine with cherry-picking for now, but figured I'd mention it since it might simplify both of our PRs.

Comment on lines 305 to 309
/* Suppress wrong warning (fixed in MSVC 19.33) */
#if defined(_MSC_VER) && (_MSC_VER < 1933)
#pragma warning(push)
#pragma warning(disable: 4090)
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in 26dde29 ("extrakeys: add secp256k1_pubkey_sort"):

Does it make sense to move this block into the secp256k1_sort function? I ended up copying these lines while writing a secp256k1_silentpayments_recipient_sort function, which made me realize anyone else would also need to copy these lines when writing a sort function for heapsort.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean into secp256k1_hsort? I'd guess the wrong warning is emitted when secp256k1_hsort is called and therefore it would be to late when the warning was disabled in secp256k1_hsort.

Copy link
Contributor

@theStack theStack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re-ACK 5e55f09

(as per $ git diff fdc09608036822afc1cebbe0c5b56cebf8ba508d 5e55f093118c2517f068841f5414f767fb35c7fe)

As far as I can tell, none of the unadressed questions/comments are critical.

@jonasnick
Copy link
Contributor Author

@theStack

are there any musig API functions where the SECP256K1_WARN_UNUSED_RESULT attribute should be added?

That's a good point. I couldn't discover a consistent pattern we're currently following (e.g, secp256k1_ec_pubkey_parse has the warning, secp256k1_tagged_sha256 has the warning even though it always returns 1, and signature_parse_der, signature_parse_compact don't). I think this should be made more consistent treewide with a note to CONTRIBUTING.md.

There are different rules we could follow:

  1. Just add the warning basically everywhere. Maybe that could be annoying sometimes if the user has data from a trusted source.
  2. Add it to functions returning a boolean result that would be pointless to call without checking for the result (e.g., verify).
  3. Add to all functions that can fail without calling a callback (e.g. they can fail because they are receiving data from untrusted sources -- at least in normal scenarios).
  4. Add it to all functions you need to call before verify to make sure that verify doesn't succeed due to invalid values. However, this would be defense-in-depth because it shouldn't happen anyway.
  5. Add it to all functions that operate on a seckey and produce a public output (e.g. sign) and all the functions the user needs to call before. This prevents that an invalid output (e.g., signature) accidentally leaks information about the seckey. However, users should already be protected from this because we zeroize the outputs if these functions fail.
  6. Add it to functions which sound particularly scary (nonce generation).

I added it to a few more functions (following basically rules 2, 3, 4, 6), because removing the warning is backwards compatible.

Copy link
Contributor

@real-or-random real-or-random left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reACK 352cd3b
nit: musig_example needs to be added to .gitignore

src/group_impl.h Outdated
}

static void secp256k1_ge_from_bytes_ext(secp256k1_ge *ge, const unsigned char *data) {
unsigned char zeros[64] = { 0 };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you did this, but in the "wrong" commit

@jonasnick
Copy link
Contributor Author

nit: musig_example needs to be added to .gitignore

fixed

@sipa
Copy link
Contributor

sipa commented Oct 7, 2024

reACK 168c920

Copy link
Contributor

@real-or-random real-or-random left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reACK 168c920

@real-or-random
Copy link
Contributor

We have an open issue for SECP256K1_WARN_UNUSED_RESULT, I copied @jonasnick's comment there.

Copy link
Contributor

@theStack theStack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re-ACK 168c920

@real-or-random real-or-random merged commit 3660fe5 into bitcoin-core:master Oct 7, 2024
116 checks passed
theStack added a commit to theStack/secp256k1 that referenced this pull request Oct 11, 2024
Quoting sipa (see bitcoin-core#1479 (comment)):
"When performing an EC multiplication A = aG for secret a, the resulting
 _affine_ coordinates of A are presumed to not leak information about a (ECDLP),
  but the same is not necessarily true for the Jacobian coordinates that come
  out of our multiplication algorithm."

For the ECDH point multiplication result, the result in Jacobi coordinates should be
cleared not only to avoid leaking the scalar, but even more so as it's a representation
of the resulting shared secret.
achow101 added a commit to achow101/bitcoin that referenced this pull request Oct 12, 2024
a88aa935063 Merge bitcoin-core/secp256k1#1603: f can never equal -m
3660fe5e2a9 Merge bitcoin-core/secp256k1#1479: Add module "musig" that implements MuSig2 multi-signatures (BIP 327)
168c92011f5 build: allow enabling the musig module in cmake
f411841a46b Add module "musig" that implements MuSig2 multi-signatures (BIP 327)
0be79660f38 util: add constant-time is_zero_array function
c8fbdb1b972 group: add ge_to_bytes_ext and ge_from_bytes_ext
ef7ff03407f f can never equal -m
4c57c7a5a95 Merge bitcoin-core/secp256k1#1554: cmake: Clean up testing code
472faaa8ee6 Merge bitcoin-core/secp256k1#1604: doc: fix typos in `secp256k1_ecdsa_{recoverable_,}signature` API description
292310fbb24 doc: fix typos in `secp256k1_ecdsa_{recoverable_,}signature` API description
85e224dd97f group: add ge_to_bytes and ge_from_bytes
7c987ec89e6 cmake: Call `enable_testing()` unconditionally
6aa576515ef cmake: Delete `CTest` module

git-subtree-dir: src/secp256k1
git-subtree-split: a88aa9350633c2d2472bace5c290aa291c7f12c9
hebasto added a commit to hebasto/bitcoin that referenced this pull request Oct 16, 2024
4f64b9f4cd build: Drop no longer needed  `-fvisibility=hidden` compiler option
5d978f1899 ci: Run `tools/symbol-check.py`
258dba9e11 test: Add `tools/symbol-check.py`
3144ba99f3 Introduce `SECP256K1_LOCAL_VAR` macro
e2571385e0 Do not export `secp256k1_musig_nonce_gen_internal`
e59158b6eb Merge bitcoin-core/secp256k1#1553: cmake: Set top-level target output locations
18f9b967c2 Merge bitcoin-core/secp256k1#1616: examples: do not retry generating seckey randomness in musig
5bab8f6d3c examples: make key generation doc consistent
e8908221a4 examples: do not retry generating seckey randomness in musig
70b6be1834 extrakeys: improve doc of keypair_create (don't suggest retry)
01b5893389 Merge bitcoin-core/secp256k1#1599: bitcoin#1570 improve examples: remove key generation loop
cd4f84f3ba Improve examples/documentation: remove key generation loops
a88aa93506 Merge bitcoin-core/secp256k1#1603: f can never equal -m
3660fe5e2a Merge bitcoin-core/secp256k1#1479: Add module "musig" that implements MuSig2 multi-signatures (BIP 327)
168c92011f build: allow enabling the musig module in cmake
f411841a46 Add module "musig" that implements MuSig2 multi-signatures (BIP 327)
0be79660f3 util: add constant-time is_zero_array function
c8fbdb1b97 group: add ge_to_bytes_ext and ge_from_bytes_ext
ef7ff03407 f can never equal -m
c232486d84 Revert "cmake: Set `ENVIRONMENT` property for examples on Windows"
26e4a7c214 cmake: Set top-level target output locations
4c57c7a5a9 Merge bitcoin-core/secp256k1#1554: cmake: Clean up testing code
472faaa8ee Merge bitcoin-core/secp256k1#1604: doc: fix typos in `secp256k1_ecdsa_{recoverable_,}signature` API description
292310fbb2 doc: fix typos in `secp256k1_ecdsa_{recoverable_,}signature` API description
85e224dd97 group: add ge_to_bytes and ge_from_bytes
7c987ec89e cmake: Call `enable_testing()` unconditionally
6aa576515e cmake: Delete `CTest` module

git-subtree-dir: src/secp256k1
git-subtree-split: 4f64b9f4cdf130d2c6d6b7bd855a04faf6f88e08
theStack added a commit to theStack/secp256k1 that referenced this pull request Oct 22, 2024
Quoting sipa (see bitcoin-core#1479 (comment)):
"When performing an EC multiplication A = aG for secret a, the resulting
 _affine_ coordinates of A are presumed to not leak information about a (ECDLP),
  but the same is not necessarily true for the Jacobian coordinates that come
  out of our multiplication algorithm."

For the ECDH point multiplication result, the result in Jacobi coordinates should be
cleared not only to avoid leaking the scalar, but even more so as it's a representation
of the resulting shared secret.
achow101 added a commit to achow101/bitcoin that referenced this pull request Oct 24, 2024
68b55209f1b Merge bitcoin-core/secp256k1#1619: musig: ctimetests: fix _declassify range for generated nonce points
f0868a9b3d8 Merge bitcoin-core/secp256k1#1595: build: 45839th attempt to fix symbol visibility on Windows
1fae76f50c0 Merge bitcoin-core/secp256k1#1620: Remove unused scratch space from API
8be3839fb2e Remove unused scratch space from API
57eda3ba300 musig: ctimetests: fix _declassify range for generated nonce points
e59158b6eb7 Merge bitcoin-core/secp256k1#1553: cmake: Set top-level target output locations
18f9b967c25 Merge bitcoin-core/secp256k1#1616: examples: do not retry generating seckey randomness in musig
5bab8f6d3c4 examples: make key generation doc consistent
e8908221a45 examples: do not retry generating seckey randomness in musig
70b6be1834e extrakeys: improve doc of keypair_create (don't suggest retry)
01b5893389e Merge bitcoin-core/secp256k1#1599: bitcoin#1570 improve examples: remove key generation loop
cd4f84f3ba8 Improve examples/documentation: remove key generation loops
a88aa935063 Merge bitcoin-core/secp256k1#1603: f can never equal -m
3660fe5e2a9 Merge bitcoin-core/secp256k1#1479: Add module "musig" that implements MuSig2 multi-signatures (BIP 327)
168c92011f5 build: allow enabling the musig module in cmake
f411841a46b Add module "musig" that implements MuSig2 multi-signatures (BIP 327)
0be79660f38 util: add constant-time is_zero_array function
c8fbdb1b972 group: add ge_to_bytes_ext and ge_from_bytes_ext
ef7ff03407f f can never equal -m
c232486d84e Revert "cmake: Set `ENVIRONMENT` property for examples on Windows"
26e4a7c2146 cmake: Set top-level target output locations
4c57c7a5a95 Merge bitcoin-core/secp256k1#1554: cmake: Clean up testing code
447334cb06d include: Avoid visibility("default") on Windows
472faaa8ee6 Merge bitcoin-core/secp256k1#1604: doc: fix typos in `secp256k1_ecdsa_{recoverable_,}signature` API description
292310fbb24 doc: fix typos in `secp256k1_ecdsa_{recoverable_,}signature` API description
85e224dd97f group: add ge_to_bytes and ge_from_bytes
7c987ec89e6 cmake: Call `enable_testing()` unconditionally
6aa576515ef cmake: Delete `CTest` module

git-subtree-dir: src/secp256k1
git-subtree-split: 68b55209f1ba3e6c0417789598f5f75649e9c14c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add MuSig2 module