Skip to content

Commit

Permalink
Merge pull request #1865 from sputn1ck/musig2_0.3.0
Browse files Browse the repository at this point in the history
MuSig2: Catch up to 0.4.0
  • Loading branch information
Roasbeef committed Aug 11, 2022
2 parents 04aac1e + 06ce960 commit da4b534
Show file tree
Hide file tree
Showing 7 changed files with 1,355 additions and 197 deletions.
15 changes: 15 additions & 0 deletions btcec/btcec.go
Expand Up @@ -39,3 +39,18 @@ type CurveParams = secp.CurveParams
func Params() *CurveParams {
return secp.Params()
}

// Generator returns the public key at the Generator Point.
func Generator() *PublicKey {
var (
result JacobianPoint
k secp.ModNScalar
)

k.SetInt(1)
ScalarBaseMultNonConst(&k, &result)

result.ToAffine()

return NewPublicKey(&result.X, &result.Y)
}
52 changes: 52 additions & 0 deletions btcec/curve.go
Expand Up @@ -4,13 +4,18 @@
package btcec

import (
"fmt"

secp "github.com/decred/dcrd/dcrec/secp256k1/v4"
)

// JacobianPoint is an element of the group formed by the secp256k1 curve in
// Jacobian projective coordinates and thus represents a point on the curve.
type JacobianPoint = secp.JacobianPoint

// infinityPoint is the jacobian representation of the point at infinity.
var infinityPoint JacobianPoint

// MakeJacobianPoint returns a Jacobian point with the provided X, Y, and Z
// coordinates.
func MakeJacobianPoint(x, y, z *FieldVal) JacobianPoint {
Expand Down Expand Up @@ -61,3 +66,50 @@ func ScalarBaseMultNonConst(k *ModNScalar, result *JacobianPoint) {
func ScalarMultNonConst(k *ModNScalar, point, result *JacobianPoint) {
secp.ScalarMultNonConst(k, point, result)
}

// ParseJacobian parses a byte slice point as a secp.Publickey and returns the
// pubkey as a JacobianPoint. If the nonce is a zero slice, the infinityPoint
// is returned.
func ParseJacobian(point []byte) (JacobianPoint, error) {
var result JacobianPoint

if len(point) != 33 {
str := fmt.Sprintf("invalid nonce: invalid length: %v",
len(point))
return JacobianPoint{}, makeError(secp.ErrPubKeyInvalidLen, str)
}

if point[0] == 0x00 {
return infinityPoint, nil
}

noncePk, err := secp.ParsePubKey(point)
if err != nil {
return JacobianPoint{}, err
}
noncePk.AsJacobian(&result)

return result, nil
}

// JacobianToByteSlice converts the passed JacobianPoint to a Pubkey
// and serializes that to a byte slice. If the JacobianPoint is the infinity
// point, a zero slice is returned.
func JacobianToByteSlice(point JacobianPoint) []byte {
if point.X == infinityPoint.X && point.Y == infinityPoint.Y {
return make([]byte, 33)
}

point.ToAffine()

return NewPublicKey(
&point.X, &point.Y,
).SerializeCompressed()
}

// GeneratorJacobian sets the passed JacobianPoint to the Generator Point.
func GeneratorJacobian(jacobian *JacobianPoint) {
var k ModNScalar
k.SetInt(1)
ScalarBaseMultNonConst(&k, jacobian)
}
5 changes: 5 additions & 0 deletions btcec/error.go
Expand Up @@ -17,3 +17,8 @@ type Error = secp.Error
// errors.As, so the caller can directly check against an error kind when
// determining the reason for an error.
type ErrorKind = secp.ErrorKind

// makeError creates an secp.Error given a set of arguments.
func makeError(kind ErrorKind, desc string) Error {
return Error{Err: kind, Description: desc}
}
9 changes: 8 additions & 1 deletion btcec/schnorr/musig2/keys.go
Expand Up @@ -26,6 +26,10 @@ var (
// ErrTweakedKeyIsInfinity is returned if while tweaking a key, we end
// up with the point at infinity.
ErrTweakedKeyIsInfinity = fmt.Errorf("tweaked key is infinity point")

// ErrTweakedKeyOverflows is returned if a tweaking key is larger than
// 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141.
ErrTweakedKeyOverflows = fmt.Errorf("tweaked key is to large")
)

// sortableKeys defines a type of slice of public keys that implements the sort
Expand Down Expand Up @@ -286,7 +290,10 @@ func tweakKey(keyJ btcec.JacobianPoint, parityAcc btcec.ModNScalar, tweak [32]by
// Next, map the tweak into a mod n integer so we can use it for
// manipulations below.
tweakInt := new(btcec.ModNScalar)
tweakInt.SetBytes(&tweak)
overflows := tweakInt.SetBytes(&tweak)
if overflows == 1 {
return keyJ, parityAcc, tweakAcc, ErrTweakedKeyOverflows
}

// Next, we'll compute: Q_i = g*Q + t*G, where g is our parityFactor and t
// is the tweakInt above. We'll space things out a bit to make it easier to
Expand Down

0 comments on commit da4b534

Please sign in to comment.