From 93e069f3bd4cdb2198a0ff158b6f8f43a649e476 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 27 Apr 2022 22:20:39 +0200 Subject: [PATCH] docs: add MuSig2 doc and release notes --- docs/musig2.md | 117 +++++++++++++++++++++ docs/release-notes/release-notes-0.15.0.md | 10 ++ 2 files changed, 127 insertions(+) create mode 100644 docs/musig2.md diff --git a/docs/musig2.md b/docs/musig2.md new file mode 100644 index 000000000..6a445bbef --- /dev/null +++ b/docs/musig2.md @@ -0,0 +1,117 @@ +# MuSig2 + +With `lnd v0.15.0-beta` a new, experimental MuSig2 API was added to the +`signrpc` subserver RPC. With MuSig2 it is possible to combine the public keys +of multiple signing participants into a single, combined key. The signers can +then later come together and cooperatively produce a single signature that is +valid for that combined public key. MuSig2 therefore is an interactive `n-of-n` +signature scheme that produces a final/complete Schnorr signature out of `n` +partial signatures. + +**NOTE**: At the time the MuSig2 code in `btcd`/`lnd` was written, there was no +"official" MuSig2 support merged to either `bitcoind` or `secp256k1`. Therefore, +some smaller details in the signing protocol could change in the future that +might not be backward compatible. So this API must be seen as highly +experimental and backward compatibility can't be guaranteed at this point. + +## References + * [MuSig2 paper](https://eprint.iacr.org/2020/1261.pdf) + * [Draft MuSig + BIP](https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki) + * [MuSig2 implementation discussion in + `bitcoind`](https://github.com/bitcoin/bitcoin/issues/23326) + +## A note on security + +The MuSig2 signing protocol is secure from leaking private key information of +the signers **as long as the same secret nonce is never used multiple times**. +If the same nonce is used for signing multiple times then the private key can +leak. To avoid this security risk, the `signrpc.MuSig2Sign` RPC can only be +called a single time for the same session ID. This has the implication that if a +signing session fails or is aborted (for example because a participant isn't +responsive or the message changes after some participants have already started +signing), a completely new signing session needs to be initialized, which +internally creates fresh nonces. + +## Examples + +An API is sometimes easiest explained by showing concrete usage examples. Here +we take a look at the MuSig2 integration tests in `lnd`, since they both serve +to test the RPCs and to showcase the different use cases. + +### 3-of-3 Taproot key spend path (BIP-0086) + +See `testTaprootMuSig2KeySpendBip86` in +[`lntest/itest/lnd_taproot_test.go`](../lntest/itest/lnd_taproot_test.go) to see +the full code. + +This example uses combines the public keys of 3 participants into a shared +MuSig2 public key that is then tweaked with the +[BIP-0086](https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki#address-derivation) +TapTweak to be turned into a Taproot public key that can be used directly as the +`pkScript` of a p2tr output on chain. + +The most notable parameter for this to work is the `TaprootTweak` parameter in +the `MuSig2CreateSession` RPC call: + +```go + taprootTweak := &signrpc.TaprootTweakDesc{ + KeySpendOnly: true, + } + + sessResp1, err := node.SignerClient.MuSig2CreateSession( + ctx, &signrpc.MuSig2SessionRequest{ + KeyLoc: keyDesc1.KeyLoc, + AllSignerPubkeys: allPubKeys, + TaprootTweak: taprootTweak, + }, + ) +``` + +### 3-of-3 Taproot key spend path with root hash commitment + +See `testTaprootMuSig2KeySpendRootHash` in +[`lntest/itest/lnd_taproot_test.go`](../lntest/itest/lnd_taproot_test.go) to see +the full code. + +This is very similar to the above example but with the main difference that the +p2tr output on chain not only commits to a key spend path but also a script +path. The MuSig2 combined key becomes the Taproot internal key and the TapTweak +commits to both the internal key and the Taproot script merkle root hash. + +The most notable parameter for this to work is the `TaprootTweak` parameter in +the `MuSig2CreateSession` RPC call: + +```go + taprootTweak := &signrpc.TaprootTweakDesc{ + ScriptRoot: rootHash[:], + } + + sessResp1, err := node.SignerClient.MuSig2CreateSession( + ctx, &signrpc.MuSig2SessionRequest{ + KeyLoc: keyDesc1.KeyLoc, + AllSignerPubkeys: allPubKeys, + TaprootTweak: taprootTweak, + }, + ) +``` + +### 3-of-3 `OP_CHECKSIG` in Taproot script spend path + +See `testTaprootMuSig2CombinedLeafKeySpend` in +[`lntest/itest/lnd_taproot_test.go`](../lntest/itest/lnd_taproot_test.go) to see +the full code. + +This example is definitely the most involved one. To be able to use a MuSig2 +combined key and then spend it through a Taproot script spend with an +`OP_CHECKSIG` script, the following steps need to be performed: + +1. Derive signing keys on signers, combine them through `MuSig2CombineKeys`. +2. Create a Taproot script tree with a script leaf ` OP_CHECKSIG`. +3. Create the Taproot key by committing to the script tree root hash. +4. When spending the output, the message being signed needs to be the sighash of + a Taproot script spend that also commits to the leaf hash. +5. The final witness stack needs to contain the combined signature, the leaf + script and the control block (which contains the internal public key and the + inclusion proof if there were any other script leaves). + diff --git a/docs/release-notes/release-notes-0.15.0.md b/docs/release-notes/release-notes-0.15.0.md index f64945a84..ca56fb58a 100644 --- a/docs/release-notes/release-notes-0.15.0.md +++ b/docs/release-notes/release-notes-0.15.0.md @@ -25,6 +25,16 @@ addresses](https://github.com/lightningnetwork/lnd/pull/6263). Using then watch it on chain. Taproot script spends are also supported through the `signrpc.SignOutputRaw` RPC (`/v2/signer/signraw` in REST). +## MuSig2 + +The [`signrpc.Signer` RPC service now supports EXPERIMENTAL MuSig2 +signing](https://github.com/lightningnetwork/lnd/pull/6361). + +More information can be found in the [MuSig2 documentation](../musig2.md). +Note that the MuSig2 BIP is not final yet and therefore the MuSig2 API must be +considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming +releases. Backward compatibility is not guaranteed! + ## `lncli` * Add [auto-generated command-line completions](https://github.com/lightningnetwork/lnd/pull/4177)