Skip to content

musig2: Add adaptor signature support to MuSig2 protocol #2325

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

martonp
Copy link
Contributor

@martonp martonp commented Feb 24, 2025

This commit adds comprehensive support for adaptor signatures in the MuSig2 protocol, including:

  • New methods for generating and setting adaptor points
  • Support for creating partial adaptor signatures
  • Methods to adapt final signatures and recover adaptor secrets
  • Updated signature verification and combination logic
  • Added test cases for adaptor signature functionality across different signer configurations

This commit adds comprehensive support for adaptor signatures in the MuSig2 protocol, including:

- New methods for generating and setting adaptor points
- Support for creating partial adaptor signatures
- Methods to adapt final signatures and recover adaptor secrets
- Updated signature verification and combination logic
- Added test cases for adaptor signature functionality across different signer configurations
@guggero guggero self-requested a review February 24, 2025 07:39
Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

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

Thank you for the PR!
Did a first pass, mostly to load some context. Didn't do a deep dive into the cryptography part of it yet, need to refresh my mental model on that first.

}

// The adaptor point added to the combined nonce must be even.
// We keep generating random secrets until we find one that works.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we need to do this in a loop? Can't we just take the inverse of the secret to get an even y coordinate if the first draw produces an odd one?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A loop is needed because we want the adaptor point added to the combined nonce to be even, not just for the adaptor point to be even.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, I understand that. But the evenness should be deterministic. So wouldn't it be possible to just invert the secret if we find out that (after adding the adaptor point to the nonce) it's not even, we can invert it instead of drawing a new value?
It's just that a for loop with no defined exit condition feels suboptimal.

// the validity of the adaptor secret key depends on the combined nonce. It
// must also be called before any partial signatures are generated or provided,
// because the validation of the signatures depends on the adaptor point.
func (s *Session) GenerateAdaptor(msg [32]byte) (*btcec.ModNScalar, *btcec.JacobianPoint, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: doc was added after this PR was opened, but we try to wrap before 80 characters to help with review and readability in narrow/multi-column environments: https://github.com/btcsuite/btcd/blob/master/docs/code_formatting_rules.md#80-character-line-length

@@ -548,6 +573,129 @@ func (s *Session) RegisterPubNonce(nonce [PubNonceSize]byte) (bool, error) {
return haveAllNonces, nil
}

// GenerateAdaptorSecret generates an adaptor secret key. This must be called
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: Godoc comment/method name mismatch.

return nil, nil, err
}

var secret btcec.ModNScalar
Copy link
Collaborator

Choose a reason for hiding this comment

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

This seems duplicated with SetAdaptor. Couldn't we instead just call into that method until we don't get ErrInvalidAdaptorPoint? Should reduce the size of the diff quite a bit.

@@ -320,6 +332,19 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey,
return nil, err
}

nonce.ToAffine()

var adaptedNonce *btcec.JacobianPoint
Copy link
Collaborator

Choose a reason for hiding this comment

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

How about adaptedNonce := nonce to avoid else case? Same for verifyPartialSig.

@@ -389,3 +390,119 @@ func TestMusig2SignCombine(t *testing.T) {
})
}
}

func TestMusig2SignCombineAdaptor(t *testing.T) {
// Pre-generate 10 deterministic private keys
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: comments should always be full sentences, including punctuation.

@@ -606,6 +635,8 @@ type combineOptions struct {
combinedKey *btcec.PublicKey

tweakAcc *btcec.ModNScalar

adaptorPub *btcec.JacobianPoint
Copy link
Collaborator

Choose a reason for hiding this comment

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

Where is this actually used? It seems like you can set it with WithAdaptorCombine, but don't see it being read anywhere. Which indicates to me that we probably want a unit test case for this as well.

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're right this is unnecessary. I've removed it along with WithAdaptorCombine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants