sign.go raw

   1  // Copyright 2013-2022 The btcsuite developers
   2  
   3  package musig2
   4  
   5  import (
   6  	"bytes"
   7  	"fmt"
   8  	"io"
   9  
  10  	"next.orly.dev/pkg/nostr/crypto/ec"
  11  	"next.orly.dev/pkg/nostr/crypto/ec/chainhash"
  12  	"next.orly.dev/pkg/nostr/crypto/ec/schnorr"
  13  	"next.orly.dev/pkg/nostr/crypto/ec/secp256k1"
  14  	"next.orly.dev/pkg/nostr/utils"
  15  	"next.orly.dev/pkg/lol/chk"
  16  )
  17  
  18  var (
  19  	// NonceBlindTag is that tag used to construct the value b, which
  20  	// blinds the second public nonce of each party.
  21  	NonceBlindTag = []byte("MuSig/noncecoef")
  22  
  23  	// ChallengeHashTag is the tag used to construct the challenge hash
  24  	ChallengeHashTag = []byte("BIP0340/challenge")
  25  
  26  	// ErrNoncePointAtInfinity is returned if during signing, the fully
  27  	// combined public nonce is the point at infinity.
  28  	ErrNoncePointAtInfinity = fmt.Errorf(
  29  		"signing nonce is the infinity " +
  30  			"point",
  31  	)
  32  
  33  	// ErrSecKeyZero is returned when the secret key for signing is
  34  	// actually zero.
  35  	ErrSecKeyZero = fmt.Errorf("priv key is zero")
  36  
  37  	// ErrPartialSigInvalid is returned when a partial is found to be
  38  	// invalid.
  39  	ErrPartialSigInvalid = fmt.Errorf("partial signature is invalid")
  40  
  41  	// ErrSecretNonceZero is returned when a secret nonce is passed in a
  42  	// zero.
  43  	ErrSecretNonceZero = fmt.Errorf("secret nonce is blank")
  44  
  45  	// ErrSecNoncePubkey is returned when the signing key does not match the
  46  	// sec nonce pubkey
  47  	ErrSecNoncePubkey = fmt.Errorf("public key does not match secnonce")
  48  
  49  	// ErrPubkeyNotIncluded is returned when the signers pubkey is not included
  50  	// in the list of pubkeys.
  51  	ErrPubkeyNotIncluded = fmt.Errorf(
  52  		"signer's pubkey must be included" +
  53  			" in the list of pubkeys",
  54  	)
  55  )
  56  
  57  // infinityPoint is the jacobian representation of the point at infinity.
  58  var infinityPoint btcec.JacobianPoint
  59  
  60  // PartialSignature reprints a partial (s-only) musig2 multi-signature. This
  61  // isn't a valid schnorr signature by itself, as it needs to be aggregated
  62  // along with the other partial signatures to be completed.
  63  type PartialSignature struct {
  64  	S *btcec.ModNScalar
  65  
  66  	R *btcec.PublicKey
  67  }
  68  
  69  // NewPartialSignature returns a new instances of the partial sig struct.
  70  func NewPartialSignature(
  71  	s *btcec.ModNScalar,
  72  	r *btcec.PublicKey,
  73  ) PartialSignature {
  74  
  75  	return PartialSignature{
  76  		S: s,
  77  		R: r,
  78  	}
  79  }
  80  
  81  // Encode writes a serialized version of the partial signature to the passed
  82  // io.Writer
  83  func (p *PartialSignature) Encode(w io.Writer) error {
  84  	var sBytes [32]byte
  85  	p.S.PutBytes(&sBytes)
  86  
  87  	if _, err := w.Write(sBytes[:]); chk.T(err) {
  88  		return err
  89  	}
  90  
  91  	return nil
  92  }
  93  
  94  // Decode attempts to parse a serialized PartialSignature stored in the io reader.
  95  func (p *PartialSignature) Decode(r io.Reader) error {
  96  	p.S = new(btcec.ModNScalar)
  97  
  98  	var sBytes [32]byte
  99  	if _, err := io.ReadFull(r, sBytes[:]); chk.T(err) {
 100  		return nil
 101  	}
 102  
 103  	overflows := p.S.SetBytes(&sBytes)
 104  	if overflows == 1 {
 105  		return ErrPartialSigInvalid
 106  	}
 107  
 108  	return nil
 109  }
 110  
 111  // SignOption is a functional option argument that allows callers to modify the
 112  // way we generate musig2 schnorr signatures.
 113  type SignOption func(*signOptions)
 114  
 115  // signOptions houses the set of functional options that can be used to modify
 116  // the method used to generate the musig2 partial signature.
 117  type signOptions struct {
 118  	// fastSign determines if we'll skip the check at the end of the
 119  	// routine where we attempt to verify the produced signature.
 120  	fastSign bool
 121  
 122  	// sortKeys determines if the set of keys should be sorted before doing
 123  	// key aggregation.
 124  	sortKeys bool
 125  
 126  	// tweaks specifies a series of tweaks to be applied to the aggregated
 127  	// public key, which also partially carries over into the signing
 128  	// process.
 129  	tweaks []KeyTweakDesc
 130  
 131  	// taprootTweak specifies a taproot specific tweak.  of the tweaks
 132  	// specified above. Normally we'd just apply the raw 32 byte tweak, but
 133  	// for taproot, we first need to compute the aggregated key before
 134  	// tweaking, and then use it as the internal key. This is required as
 135  	// the taproot tweak also commits to the public key, which in this case
 136  	// is the aggregated key before the tweak.
 137  	taprootTweak []byte
 138  
 139  	// bip86Tweak specifies that the taproot tweak should be done in a BIP
 140  	// 86 style, where we don't expect an actual tweak and instead just
 141  	// commit to the public key itself.
 142  	bip86Tweak bool
 143  }
 144  
 145  // defaultSignOptions returns the default set of signing operations.
 146  func defaultSignOptions() *signOptions {
 147  	return &signOptions{}
 148  }
 149  
 150  // WithFastSign forces signing to skip the extra verification step at the end.
 151  // Performance sensitive applications may opt to use this option to speed up
 152  // the signing operation.
 153  func WithFastSign() SignOption {
 154  	return func(o *signOptions) {
 155  		o.fastSign = true
 156  	}
 157  }
 158  
 159  // WithSortedKeys determines if the set of signing public keys are to be sorted
 160  // or not before doing key aggregation.
 161  func WithSortedKeys() SignOption {
 162  	return func(o *signOptions) {
 163  		o.sortKeys = true
 164  	}
 165  }
 166  
 167  // WithTweaks determines if the aggregated public key used should apply a
 168  // series of tweaks before key aggregation.
 169  func WithTweaks(tweaks ...KeyTweakDesc) SignOption {
 170  	return func(o *signOptions) {
 171  		o.tweaks = tweaks
 172  	}
 173  }
 174  
 175  // WithTaprootSignTweak allows a caller to specify a tweak that should be used
 176  // in a bip 340 manner when signing. This differs from WithTweaks as the tweak
 177  // will be assumed to always be x-only and the intermediate aggregate key
 178  // before tweaking will be used to generate part of the tweak (as the taproot
 179  // tweak also commits to the internal key).
 180  //
 181  // This option should be used in the taproot context to create a valid
 182  // signature for the keypath spend for taproot, when the output key is actually
 183  // committing to a script path, or some other data.
 184  func WithTaprootSignTweak(scriptRoot []byte) SignOption {
 185  	return func(o *signOptions) {
 186  		o.taprootTweak = scriptRoot
 187  	}
 188  }
 189  
 190  // WithBip86SignTweak allows a caller to specify a tweak that should be used in
 191  // a bip 340 manner when signing, factoring in BIP 86 as well. This differs
 192  // from WithTaprootSignTweak as no true script root will be committed to,
 193  // instead we just commit to the internal key.
 194  //
 195  // This option should be used in the taproot context to create a valid
 196  // signature for the keypath spend for taproot, when the output key was
 197  // generated using BIP 86.
 198  func WithBip86SignTweak() SignOption {
 199  	return func(o *signOptions) {
 200  		o.bip86Tweak = true
 201  	}
 202  }
 203  
 204  // computeSigningNonce calculates the final nonce used for signing. This will
 205  // be the R value used in the final signature.
 206  func computeSigningNonce(
 207  	combinedNonce [PubNonceSize]byte,
 208  	combinedKey *btcec.PublicKey, msg [32]byte,
 209  ) (
 210  	*btcec.JacobianPoint, *btcec.ModNScalar, error,
 211  ) {
 212  
 213  	// Next we'll compute the value b, that blinds our second public
 214  	// nonce:
 215  	//  * b = h(tag=NonceBlindTag, combinedNonce || combinedKey || m).
 216  	var (
 217  		nonceMsgBuf  bytes.Buffer
 218  		nonceBlinder btcec.ModNScalar
 219  	)
 220  	nonceMsgBuf.Write(combinedNonce[:])
 221  	nonceMsgBuf.Write(schnorr.SerializePubKey(combinedKey))
 222  	nonceMsgBuf.Write(msg[:])
 223  	nonceBlindHash := chainhash.TaggedHash(
 224  		NonceBlindTag, nonceMsgBuf.Bytes(),
 225  	)
 226  	nonceBlinder.SetByteSlice(nonceBlindHash[:])
 227  
 228  	// Next, we'll parse the public nonces into R1 and R2.
 229  	r1J, err := btcec.ParseJacobian(
 230  		combinedNonce[:btcec.PubKeyBytesLenCompressed],
 231  	)
 232  	if err != nil {
 233  		return nil, nil, err
 234  	}
 235  	r2J, err := btcec.ParseJacobian(
 236  		combinedNonce[btcec.PubKeyBytesLenCompressed:],
 237  	)
 238  	if err != nil {
 239  		return nil, nil, err
 240  	}
 241  
 242  	// With our nonce blinding value, we'll now combine both the public
 243  	// nonces, using the blinding factor to tweak the second nonce:
 244  	//  * R = R_1 + b*R_2
 245  	var nonce btcec.JacobianPoint
 246  	btcec.ScalarMultNonConst(&nonceBlinder, &r2J, &r2J)
 247  	btcec.AddNonConst(&r1J, &r2J, &nonce)
 248  
 249  	// If the combined nonce is the point at infinity, we'll use the
 250  	// generator point instead.
 251  	if nonce == infinityPoint {
 252  		G := btcec.Generator()
 253  		G.AsJacobian(&nonce)
 254  	}
 255  
 256  	return &nonce, &nonceBlinder, nil
 257  }
 258  
 259  // Sign generates a musig2 partial signature given the passed key set, secret
 260  // nonce, public nonce, and secret keys. This method returns an error if the
 261  // generated nonces are either too large, or end up mapping to the point at
 262  // infinity.
 263  func Sign(
 264  	secNonce [SecNonceSize]byte, privKey *btcec.SecretKey,
 265  	combinedNonce [PubNonceSize]byte, pubKeys []*btcec.PublicKey,
 266  	msg [32]byte, signOpts ...SignOption,
 267  ) (*PartialSignature, error) {
 268  
 269  	// First, parse the set of optional signing options.
 270  	opts := defaultSignOptions()
 271  	for _, option := range signOpts {
 272  		option(opts)
 273  	}
 274  
 275  	// Check that our signing key belongs to the secNonce
 276  	if !utils.FastEqual(
 277  		secNonce[btcec.SecKeyBytesLen*2:],
 278  		privKey.PubKey().SerializeCompressed(),
 279  	) {
 280  
 281  		return nil, ErrSecNoncePubkey
 282  	}
 283  
 284  	// Check that the key set contains the public key to our secret key.
 285  	var containsSecKey bool
 286  	for _, pk := range pubKeys {
 287  		if privKey.PubKey().IsEqual(pk) {
 288  			containsSecKey = true
 289  		}
 290  	}
 291  
 292  	if !containsSecKey {
 293  		return nil, ErrPubkeyNotIncluded
 294  	}
 295  
 296  	// Compute the hash of all the keys here as we'll need it do aggregate
 297  	// the keys and also at the final step of signing.
 298  	keysHash := keyHashFingerprint(pubKeys, opts.sortKeys)
 299  	uniqueKeyIndex := secondUniqueKeyIndex(pubKeys, opts.sortKeys)
 300  
 301  	keyAggOpts := []KeyAggOption{
 302  		WithKeysHash(keysHash), WithUniqueKeyIndex(uniqueKeyIndex),
 303  	}
 304  	switch {
 305  	case opts.bip86Tweak:
 306  		keyAggOpts = append(
 307  			keyAggOpts, WithBIP86KeyTweak(),
 308  		)
 309  	case opts.taprootTweak != nil:
 310  		keyAggOpts = append(
 311  			keyAggOpts, WithTaprootKeyTweak(opts.taprootTweak),
 312  		)
 313  	case len(opts.tweaks) != 0:
 314  		keyAggOpts = append(keyAggOpts, WithKeyTweaks(opts.tweaks...))
 315  	}
 316  
 317  	// Next we'll construct the aggregated public key based on the set of
 318  	// signers.
 319  	combinedKey, parityAcc, _, err := AggregateKeys(
 320  		pubKeys, opts.sortKeys, keyAggOpts...,
 321  	)
 322  	if err != nil {
 323  		return nil, err
 324  	}
 325  
 326  	// We'll now combine both the public nonces, using the blinding factor
 327  	// to tweak the second nonce:
 328  	//  * R = R_1 + b*R_2
 329  	nonce, nonceBlinder, err := computeSigningNonce(
 330  		combinedNonce, combinedKey.FinalKey, msg,
 331  	)
 332  	if err != nil {
 333  		return nil, err
 334  	}
 335  
 336  	// Next we'll parse out our two secret nonces, which we'll be using in
 337  	// the core signing process below.
 338  	var k1, k2 btcec.ModNScalar
 339  	k1.SetByteSlice(secNonce[:btcec.SecKeyBytesLen])
 340  	k2.SetByteSlice(secNonce[btcec.SecKeyBytesLen:])
 341  
 342  	if k1.IsZero() || k2.IsZero() {
 343  		return nil, ErrSecretNonceZero
 344  	}
 345  
 346  	nonce.ToAffine()
 347  
 348  	nonceKey := btcec.NewPublicKey(&nonce.X, &nonce.Y)
 349  
 350  	// If the nonce R has an odd y coordinate, then we'll negate both our
 351  	// secret nonces.
 352  	if nonce.Y.IsOdd() {
 353  		k1.Negate()
 354  		k2.Negate()
 355  	}
 356  
 357  	privKeyScalar := privKey.Key
 358  	if privKeyScalar.IsZero() {
 359  		return nil, ErrSecKeyZero
 360  	}
 361  
 362  	pubKey := privKey.PubKey()
 363  	combinedKeyYIsOdd := func() bool {
 364  		combinedKeyBytes := combinedKey.FinalKey.SerializeCompressed()
 365  		return combinedKeyBytes[0] == secp256k1.PubKeyFormatCompressedOdd
 366  	}()
 367  
 368  	// Next we'll compute the two parity factors for Q, the combined key.
 369  	// If the key is odd, then we'll negate it.
 370  	parityCombinedKey := new(btcec.ModNScalar).SetInt(1)
 371  	if combinedKeyYIsOdd {
 372  		parityCombinedKey.Negate()
 373  	}
 374  
 375  	// Before we sign below, we'll multiply by our various parity factors
 376  	// to ensure that the signing key is properly negated (if necessary):
 377  	//  * d = g⋅gacc⋅d'
 378  	privKeyScalar.Mul(parityCombinedKey).Mul(parityAcc)
 379  
 380  	// Next we'll create the challenge hash that commits to the combined
 381  	// nonce, combined public key and also the message:
 382  	// * e = H(tag=ChallengeHashTag, R || Q || m) mod n
 383  	var challengeMsg bytes.Buffer
 384  	challengeMsg.Write(schnorr.SerializePubKey(nonceKey))
 385  	challengeMsg.Write(schnorr.SerializePubKey(combinedKey.FinalKey))
 386  	challengeMsg.Write(msg[:])
 387  	challengeBytes := chainhash.TaggedHash(
 388  		ChallengeHashTag, challengeMsg.Bytes(),
 389  	)
 390  	var e btcec.ModNScalar
 391  	e.SetByteSlice(challengeBytes[:])
 392  
 393  	// Next, we'll compute a, our aggregation coefficient for the key that
 394  	// we're signing with.
 395  	a := aggregationCoefficient(pubKeys, pubKey, keysHash, uniqueKeyIndex)
 396  
 397  	// With mu constructed, we can finally generate our partial signature
 398  	// as: s = (k1_1 + b*k_2 + e*a*d) mod n.
 399  	s := new(btcec.ModNScalar)
 400  	s.Add(&k1).Add(k2.Mul(nonceBlinder)).Add(e.Mul(a).Mul(&privKeyScalar))
 401  
 402  	sig := NewPartialSignature(s, nonceKey)
 403  
 404  	// If we're not in fast sign mode, then we'll also validate our partial
 405  	// signature.
 406  	if !opts.fastSign {
 407  		pubNonce := secNonceToPubNonce(secNonce)
 408  		sigValid := sig.Verify(
 409  			pubNonce, combinedNonce, pubKeys, pubKey, msg,
 410  			signOpts...,
 411  		)
 412  		if !sigValid {
 413  			return nil, fmt.Errorf("sig is invalid!")
 414  		}
 415  	}
 416  
 417  	return &sig, nil
 418  }
 419  
 420  // Verify implements partial signature verification given the public nonce for
 421  // the signer, aggregate nonce, signer set and finally the message being
 422  // signed.
 423  func (p *PartialSignature) Verify(
 424  	pubNonce [PubNonceSize]byte,
 425  	combinedNonce [PubNonceSize]byte, keySet []*btcec.PublicKey,
 426  	signingKey *btcec.PublicKey, msg [32]byte, signOpts ...SignOption,
 427  ) bool {
 428  
 429  	pubKey := signingKey.SerializeCompressed()
 430  
 431  	return verifyPartialSig(
 432  		p, pubNonce, combinedNonce, keySet, pubKey, msg, signOpts...,
 433  	) == nil
 434  }
 435  
 436  // verifyPartialSig attempts to verify a partial schnorr signature given the
 437  // necessary parameters. This is the internal version of Verify that returns
 438  // detailed errors.  signed.
 439  func verifyPartialSig(
 440  	partialSig *PartialSignature, pubNonce [PubNonceSize]byte,
 441  	combinedNonce [PubNonceSize]byte, keySet []*btcec.PublicKey,
 442  	pubKey []byte, msg [32]byte, signOpts ...SignOption,
 443  ) error {
 444  
 445  	opts := defaultSignOptions()
 446  	for _, option := range signOpts {
 447  		option(opts)
 448  	}
 449  
 450  	// First we'll map the internal partial signature back into something
 451  	// we can manipulate.
 452  	s := partialSig.S
 453  
 454  	// Next we'll parse out the two public nonces into something we can
 455  	// use.
 456  	//
 457  	// Compute the hash of all the keys here as we'll need it do aggregate
 458  	// the keys and also at the final step of verification.
 459  	keysHash := keyHashFingerprint(keySet, opts.sortKeys)
 460  	uniqueKeyIndex := secondUniqueKeyIndex(keySet, opts.sortKeys)
 461  
 462  	keyAggOpts := []KeyAggOption{
 463  		WithKeysHash(keysHash), WithUniqueKeyIndex(uniqueKeyIndex),
 464  	}
 465  	switch {
 466  	case opts.bip86Tweak:
 467  		keyAggOpts = append(
 468  			keyAggOpts, WithBIP86KeyTweak(),
 469  		)
 470  	case opts.taprootTweak != nil:
 471  		keyAggOpts = append(
 472  			keyAggOpts, WithTaprootKeyTweak(opts.taprootTweak),
 473  		)
 474  	case len(opts.tweaks) != 0:
 475  		keyAggOpts = append(keyAggOpts, WithKeyTweaks(opts.tweaks...))
 476  	}
 477  
 478  	// Next we'll construct the aggregated public key based on the set of
 479  	// signers.
 480  	combinedKey, parityAcc, _, err := AggregateKeys(
 481  		keySet, opts.sortKeys, keyAggOpts...,
 482  	)
 483  	if err != nil {
 484  		return err
 485  	}
 486  
 487  	// Next we'll compute the value b, that blinds our second public
 488  	// nonce:
 489  	//  * b = h(tag=NonceBlindTag, combinedNonce || combinedKey || m).
 490  	var (
 491  		nonceMsgBuf  bytes.Buffer
 492  		nonceBlinder btcec.ModNScalar
 493  	)
 494  	nonceMsgBuf.Write(combinedNonce[:])
 495  	nonceMsgBuf.Write(schnorr.SerializePubKey(combinedKey.FinalKey))
 496  	nonceMsgBuf.Write(msg[:])
 497  	nonceBlindHash := chainhash.TaggedHash(NonceBlindTag, nonceMsgBuf.Bytes())
 498  	nonceBlinder.SetByteSlice(nonceBlindHash[:])
 499  
 500  	r1J, err := btcec.ParseJacobian(
 501  		combinedNonce[:btcec.PubKeyBytesLenCompressed],
 502  	)
 503  	if err != nil {
 504  		return err
 505  	}
 506  	r2J, err := btcec.ParseJacobian(
 507  		combinedNonce[btcec.PubKeyBytesLenCompressed:],
 508  	)
 509  	if err != nil {
 510  		return err
 511  	}
 512  
 513  	// With our nonce blinding value, we'll now combine both the public
 514  	// nonces, using the blinding factor to tweak the second nonce:
 515  	//  * R = R_1 + b*R_2
 516  	var nonce btcec.JacobianPoint
 517  	btcec.ScalarMultNonConst(&nonceBlinder, &r2J, &r2J)
 518  	btcec.AddNonConst(&r1J, &r2J, &nonce)
 519  
 520  	// Next, we'll parse out the set of public nonces this signer used to
 521  	// generate the signature.
 522  	pubNonce1J, err := btcec.ParseJacobian(
 523  		pubNonce[:btcec.PubKeyBytesLenCompressed],
 524  	)
 525  	if err != nil {
 526  		return err
 527  	}
 528  	pubNonce2J, err := btcec.ParseJacobian(
 529  		pubNonce[btcec.PubKeyBytesLenCompressed:],
 530  	)
 531  	if err != nil {
 532  		return err
 533  	}
 534  
 535  	// If the nonce is the infinity point we set it to the Generator.
 536  	if nonce == infinityPoint {
 537  		btcec.GeneratorJacobian(&nonce)
 538  	} else {
 539  		nonce.ToAffine()
 540  	}
 541  
 542  	// We'll perform a similar aggregation and blinding operator as we did
 543  	// above for the combined nonces: R' = R_1' + b*R_2'.
 544  	var pubNonceJ btcec.JacobianPoint
 545  
 546  	btcec.ScalarMultNonConst(&nonceBlinder, &pubNonce2J, &pubNonce2J)
 547  	btcec.AddNonConst(&pubNonce1J, &pubNonce2J, &pubNonceJ)
 548  
 549  	pubNonceJ.ToAffine()
 550  
 551  	// If the combined nonce used in the challenge hash has an odd y
 552  	// coordinate, then we'll negate our final public nonce.
 553  	if nonce.Y.IsOdd() {
 554  		pubNonceJ.Y.Negate(1)
 555  		pubNonceJ.Y.Normalize()
 556  	}
 557  
 558  	// Next we'll create the challenge hash that commits to the combined
 559  	// nonce, combined public key and also the message:
 560  	//  * e = H(tag=ChallengeHashTag, R || Q || m) mod n
 561  	var challengeMsg bytes.Buffer
 562  	challengeMsg.Write(
 563  		schnorr.SerializePubKey(
 564  			btcec.NewPublicKey(
 565  				&nonce.X, &nonce.Y,
 566  			),
 567  		),
 568  	)
 569  	challengeMsg.Write(schnorr.SerializePubKey(combinedKey.FinalKey))
 570  	challengeMsg.Write(msg[:])
 571  	challengeBytes := chainhash.TaggedHash(
 572  		ChallengeHashTag, challengeMsg.Bytes(),
 573  	)
 574  	var e btcec.ModNScalar
 575  	e.SetByteSlice(challengeBytes[:])
 576  
 577  	signingKey, err := btcec.ParsePubKey(pubKey)
 578  	if err != nil {
 579  		return err
 580  	}
 581  
 582  	// Next, we'll compute a, our aggregation coefficient for the key that
 583  	// we're signing with.
 584  	a := aggregationCoefficient(keySet, signingKey, keysHash, uniqueKeyIndex)
 585  
 586  	// If the combined key has an odd y coordinate, then we'll negate
 587  	// parity factor for the signing key.
 588  	parityCombinedKey := new(btcec.ModNScalar).SetInt(1)
 589  	combinedKeyBytes := combinedKey.FinalKey.SerializeCompressed()
 590  	if combinedKeyBytes[0] == secp256k1.PubKeyFormatCompressedOdd {
 591  		parityCombinedKey.Negate()
 592  	}
 593  
 594  	// Next, we'll construct the final parity factor by multiplying the
 595  	// sign key parity factor with the accumulated parity factor for all
 596  	// the keys.
 597  	finalParityFactor := parityCombinedKey.Mul(parityAcc)
 598  
 599  	var signKeyJ btcec.JacobianPoint
 600  	signingKey.AsJacobian(&signKeyJ)
 601  
 602  	// In the final set, we'll check that: s*G == R' + e*a*g*P.
 603  	var sG, rP btcec.JacobianPoint
 604  	btcec.ScalarBaseMultNonConst(s, &sG)
 605  	btcec.ScalarMultNonConst(e.Mul(a).Mul(finalParityFactor), &signKeyJ, &rP)
 606  	btcec.AddNonConst(&rP, &pubNonceJ, &rP)
 607  
 608  	sG.ToAffine()
 609  	rP.ToAffine()
 610  
 611  	if sG != rP {
 612  		return ErrPartialSigInvalid
 613  	}
 614  
 615  	return nil
 616  }
 617  
 618  // CombineOption is a functional option argument that allows callers to modify the
 619  // way we combine musig2 schnorr signatures.
 620  type CombineOption func(*combineOptions)
 621  
 622  // combineOptions houses the set of functional options that can be used to
 623  // modify the method used to combine the musig2 partial signatures.
 624  type combineOptions struct {
 625  	msg [32]byte
 626  
 627  	combinedKey *btcec.PublicKey
 628  
 629  	tweakAcc *btcec.ModNScalar
 630  }
 631  
 632  // defaultCombineOptions returns the default set of signing operations.
 633  func defaultCombineOptions() *combineOptions {
 634  	return &combineOptions{}
 635  }
 636  
 637  // WithTweakedCombine is a functional option that allows callers to specify
 638  // that the signature was produced using a tweaked aggregated public key. In
 639  // order to properly aggregate the partial signatures, the caller must specify
 640  // enough information to reconstruct the challenge, and also the final
 641  // accumulated tweak value.
 642  func WithTweakedCombine(
 643  	msg [32]byte, keys []*btcec.PublicKey,
 644  	tweaks []KeyTweakDesc, sort bool,
 645  ) CombineOption {
 646  
 647  	return func(o *combineOptions) {
 648  		combinedKey, _, tweakAcc, _ := AggregateKeys(
 649  			keys, sort, WithKeyTweaks(tweaks...),
 650  		)
 651  
 652  		o.msg = msg
 653  		o.combinedKey = combinedKey.FinalKey
 654  		o.tweakAcc = tweakAcc
 655  	}
 656  }
 657  
 658  // WithTaprootTweakedCombine is similar to the WithTweakedCombine option, but
 659  // assumes a BIP 341 context where the final tweaked key is to be used as the
 660  // output key, where the internal key is the aggregated key pre-tweak.
 661  //
 662  // This option should be used over WithTweakedCombine when attempting to
 663  // aggregate signatures for a top-level taproot keyspend, where the output key
 664  // commits to a script root.
 665  func WithTaprootTweakedCombine(
 666  	msg [32]byte, keys []*btcec.PublicKey,
 667  	scriptRoot []byte, sort bool,
 668  ) CombineOption {
 669  
 670  	return func(o *combineOptions) {
 671  		combinedKey, _, tweakAcc, _ := AggregateKeys(
 672  			keys, sort, WithTaprootKeyTweak(scriptRoot),
 673  		)
 674  
 675  		o.msg = msg
 676  		o.combinedKey = combinedKey.FinalKey
 677  		o.tweakAcc = tweakAcc
 678  	}
 679  }
 680  
 681  // WithBip86TweakedCombine is similar to the WithTaprootTweakedCombine option,
 682  // but assumes a BIP 341 + BIP 86 context where the final tweaked key is to be
 683  // used as the output key, where the internal key is the aggregated key
 684  // pre-tweak.
 685  //
 686  // This option should be used over WithTaprootTweakedCombine when attempting to
 687  // aggregate signatures for a top-level taproot keyspend, where the output key
 688  // was generated using BIP 86.
 689  func WithBip86TweakedCombine(
 690  	msg [32]byte, keys []*btcec.PublicKey,
 691  	sort bool,
 692  ) CombineOption {
 693  
 694  	return func(o *combineOptions) {
 695  		combinedKey, _, tweakAcc, _ := AggregateKeys(
 696  			keys, sort, WithBIP86KeyTweak(),
 697  		)
 698  
 699  		o.msg = msg
 700  		o.combinedKey = combinedKey.FinalKey
 701  		o.tweakAcc = tweakAcc
 702  	}
 703  }
 704  
 705  // CombineSigs combines the set of public keys given the final aggregated
 706  // nonce, and the series of partial signatures for each nonce.
 707  func CombineSigs(
 708  	combinedNonce *btcec.PublicKey,
 709  	partialSigs []*PartialSignature,
 710  	combineOpts ...CombineOption,
 711  ) *schnorr.Signature {
 712  
 713  	// First, parse the set of optional combine options.
 714  	opts := defaultCombineOptions()
 715  	for _, option := range combineOpts {
 716  		option(opts)
 717  	}
 718  
 719  	// If signer keys and tweaks are specified, then we need to carry out
 720  	// some intermediate steps before we can combine the signature.
 721  	var tweakProduct *btcec.ModNScalar
 722  	if opts.combinedKey != nil && opts.tweakAcc != nil {
 723  		// Next, we'll construct the parity factor of the combined key,
 724  		// negating it if the combined key has an even y coordinate.
 725  		parityFactor := new(btcec.ModNScalar).SetInt(1)
 726  		combinedKeyBytes := opts.combinedKey.SerializeCompressed()
 727  		if combinedKeyBytes[0] == secp256k1.PubKeyFormatCompressedOdd {
 728  			parityFactor.Negate()
 729  		}
 730  
 731  		// Next we'll reconstruct e the challenge has based on the
 732  		// nonce and combined public key.
 733  		//  * e = H(tag=ChallengeHashTag, R || Q || m) mod n
 734  		var challengeMsg bytes.Buffer
 735  		challengeMsg.Write(schnorr.SerializePubKey(combinedNonce))
 736  		challengeMsg.Write(schnorr.SerializePubKey(opts.combinedKey))
 737  		challengeMsg.Write(opts.msg[:])
 738  		challengeBytes := chainhash.TaggedHash(
 739  			ChallengeHashTag, challengeMsg.Bytes(),
 740  		)
 741  		var e btcec.ModNScalar
 742  		e.SetByteSlice(challengeBytes[:])
 743  
 744  		tweakProduct = new(btcec.ModNScalar).Set(&e)
 745  		tweakProduct.Mul(opts.tweakAcc).Mul(parityFactor)
 746  	}
 747  
 748  	// Finally, the tweak factor also needs to be re-computed as well.
 749  	var combinedSig btcec.ModNScalar
 750  	for _, partialSig := range partialSigs {
 751  		combinedSig.Add(partialSig.S)
 752  	}
 753  
 754  	// If the tweak product was set above, then we'll need to add the value
 755  	// at the very end in order to produce a valid signature under the
 756  	// final tweaked key.
 757  	if tweakProduct != nil {
 758  		combinedSig.Add(tweakProduct)
 759  	}
 760  
 761  	// TODO(roasbeef): less verbose way to get the x coord...
 762  	var nonceJ btcec.JacobianPoint
 763  	combinedNonce.AsJacobian(&nonceJ)
 764  	nonceJ.ToAffine()
 765  
 766  	return schnorr.NewSignature(&nonceJ.X, &combinedSig)
 767  }
 768