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

MuSig2 support #208

Open
14 of 21 tasks
bigspider opened this issue Nov 20, 2023 · 1 comment · May be fixed by #294
Open
14 of 21 tasks

MuSig2 support #208

bigspider opened this issue Nov 20, 2023 · 1 comment · May be fixed by #294
Labels
enhancement New feature or request
Milestone

Comments

@bigspider
Copy link
Collaborator

bigspider commented Nov 20, 2023

Extend wallet policies with musig support, as tentatively specified here.

For wallet policies, expressions of the form:

musig(KEY, ..., KEY)/<M,N>/*
musig(KEY, ..., KEY)/**

will suffice; KEY can be restricted to xpubs (although it's possible to generalize to other key expressions if there are use cases). It is unclear if there is any benefit in supporting things like musig(KEY/**, ..., KEY/**), which seems inherently inefficient.

References

Tasks:

  • Bitcoin app
    • Wallet policy parsing of musig descriptors
    • Update specs for PSBT fields (aggregate key is now a plain key and not x-only)
    • Aggregate xpub derivation for musig descriptor
    • Address generation for policies with musig descriptor.
    • Update to sorted musig() (per this)
    • Review sanity rules (e.g.: repeated xpubs in wallet policy) in the presence of musig
    • Transaction-level signing session logic
    • Pubnonce generation
    • Partial signature in signing logic.
    • Compute the aggregate key only once for the placeholder
    • Sign the second round silently if both rounds are executed back-to-back.
  • Client libraries:
    • Extend processing of YIELD to understand pubnonces and partial signatures (all clients)
    • Add musig() xpub generation to python client
    • Update to sorted musig() (per this)
    • Add musig() xpub generation to Rust client
    • Add musig() xpub generation to JS client
  • UX
    • Figure out what to show when no signature is produced, and only pubnonces (instead of Transaction Signed)
  • Tests:
    • Address generation
    • Implement cosigner logic and psbt partial signature aggregation in the python test suite
    • Extensive tests
    • Figure out how to optimize the CI to not recompile bitcoin every time
@bigspider bigspider added the enhancement New feature or request label Nov 20, 2023
@bigspider bigspider added this to the 2.3.0 milestone Nov 20, 2023
@bigspider
Copy link
Collaborator Author

bigspider commented Feb 13, 2024

Edit: a more precise version of these specs was posted on Delving Bitcoin.

BIP-0327 discusses the necessity to keep some state during a signing session. However, a "signing session" in BIP-0327 only refers to the production of a single signature.

In the typical signing flow of a wallet, it's more logical to consider a session at the level of an entire transaction. All of the inputs of the transactions are likely to be obtained from the same descriptor, and the signer would produce the pubnonce/signature for all of them at the same time.

Therefore, in the flow of BIP-0327, you would expect one MuSig2 signing session per input to be active at the same time. That's problematic as it would require to persist state for an unbounded number of signing sessions.

Instead, we want a psbt-level session with a small state persisted on the device, that allows to complete a full signing flow for the entire PSBT; the necessary state for the each actual session for each internal input (possibly, one session per-input and per-placeholder of the wallet policy) can be synthetically generated.

Signing flow

For now, we assume that the app can handle a single psbt-level session; this could be generalized to multiple parallel psbt-level sessions in the future.

In the following, a session always refers to the psbt-level signing session.

Phase 1: pubnonce generation: A PSBT is sent to the bitcoin app, and it does not contain any pubnonce.

  • If a session already exists, it is deleted from the persistent memory.
  • A new session is created in volatile memory.
  • The app produces a fresh random number $rand\_root$, and saves it in the current session.
  • The app generates the randomness for the $i$-th placeholder and for the $j$-th input as: $rand_{i,j} = SHA256(rand\_root || i || j)$ (with a fixed-length encoding of $i$ and $j$). That is used as the rand' value in NonceGen for that input/placeholder pair.
  • At completion (after all the pubnonces are returned), the session is copied into the persistent memory.

Phase 2: partial signature generation: A PSBT is sent to the bitcoin app, and contains the pubnonces. **

  • A copy of the session is stored in the volatile memory, and the session is deleted from the persistent memory.
  • For each input/placeholder pair $(i, j)$:
    • Recompute the synthetic pubnonce/secnonce pair with the syntetic randomness $rand_{i,j}$
    • Verify that the pubnonce the PSBT matches the recomputed one
    • Continue the signing flow as per BIP-0327, generating the partial signature.

Security considerations

State reuse avoidance

Storing the session in persistent memory only at the end of Phase 1, and deleting it before beginning Phase 2 simplifies auditing and making sure that there is no reuse of state across signing sessions.

Security of synthetic randomness

Generating $rand_{i, j}$ syntetically is not a problem, as the $rand\_root$ value is kept secret, making all the values produced for different $i$ and $j$ not predictable for an attacker.

Malleability of the PSBT

If the optional parameters are passed to the NonceGen function, they will depend on the transaction data present in the PSBT. Therefore, there is no guarantee that they will be unchanged the next time the PSBT is provided.

However, that does not constitute a security risk, as those parameters are only used as additional sources of entropy in NonceGen. A malicious client can't affect the secnonce/pubnonce pairs in any predictable way, since the $rand\_root$ never leaves the device.

@bigspider bigspider linked a pull request Oct 9, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
1 participant