Skip to content

Commit de6e154

Browse files
committed
utils: accept raw keys in MuSig2Sign
1 parent f006cbd commit de6e154

File tree

3 files changed

+75
-31
lines changed

3 files changed

+75
-31
lines changed

staticaddr/script/script_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"fmt"
77
"testing"
88

9-
"github.com/btcsuite/btcd/btcec/v2"
109
"github.com/btcsuite/btcd/txscript"
1110
"github.com/btcsuite/btcd/wire"
1211
"github.com/lightninglabs/loop/test"
@@ -28,9 +27,12 @@ func TestStaticAddressScript(t *testing.T) {
2827
clientPrivKey, clientPubKey := test.CreateKey(1)
2928
serverPrivKey, serverPubKey := test.CreateKey(2)
3029

30+
var clientKey, serverKey [32]byte
31+
copy(clientKey[:], clientPrivKey.Serialize())
32+
copy(serverKey[:], serverPrivKey.Serialize())
33+
3134
// Keys used for the Musig2 session.
32-
privKeys := []*btcec.PrivateKey{clientPrivKey, serverPrivKey}
33-
pubKeys := []*btcec.PublicKey{clientPubKey, serverPubKey}
35+
privKeys := [][32]byte{clientKey, serverKey}
3436

3537
// Create a new static address.
3638
staticAddress, err := NewStaticAddress(
@@ -91,7 +93,7 @@ func TestStaticAddressScript(t *testing.T) {
9193
}
9294

9395
sig, err := utils.MuSig2Sign(
94-
version, privKeys, pubKeys, tweak, msg,
96+
version, privKeys, tweak, msg,
9597
)
9698
require.NoError(t, err)
9799

utils/musig.go

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,37 @@ import (
44
"fmt"
55

66
"github.com/btcsuite/btcd/btcec/v2"
7+
"github.com/btcsuite/btcd/btcec/v2/schnorr"
78
"github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
89
"github.com/lightningnetwork/lnd/input"
910
)
1011

1112
// MuSig2Sign will create a MuSig2 signature for the passed message using the
12-
// passed private keys. It expects at least two signing keys, and the number of
13-
// private keys and public keys must match.
14-
func MuSig2Sign(version input.MuSig2Version, privKeys []*btcec.PrivateKey,
15-
pubKeys []*btcec.PublicKey, tweaks *input.MuSig2Tweaks,
16-
msg [32]byte) ([]byte, error) {
17-
18-
if len(privKeys) != len(pubKeys) {
19-
return nil, fmt.Errorf("number of private keys (%d) must "+
20-
"match number of public keys (%d)",
21-
len(privKeys), len(pubKeys))
13+
// passed raw private keys. It expects at least two signing keys.
14+
func MuSig2Sign(version input.MuSig2Version, keys [][32]byte,
15+
tweaks *input.MuSig2Tweaks, msg [32]byte) ([]byte, error) {
16+
17+
privKeys := make([]*btcec.PrivateKey, len(keys))
18+
pubKeys := make([]*btcec.PublicKey, len(keys))
19+
20+
// First parse the raw private keys and also create the corresponding
21+
// public keys.
22+
for i, key := range keys {
23+
privKeys[i], pubKeys[i] = btcec.PrivKeyFromBytes(key[:])
24+
25+
// MuSig2 v0.4 expects x-only public keys.
26+
if version == input.MuSig2Version040 {
27+
pubKey := pubKeys[i].SerializeCompressed()
28+
xOnlyPubKey, err := schnorr.ParsePubKey(pubKey[1:])
29+
if err != nil {
30+
return nil, fmt.Errorf("error parsing x-only "+
31+
"pubkey: %v", err)
32+
}
33+
34+
pubKeys[i] = xOnlyPubKey
35+
}
2236
}
37+
2338
if len(privKeys) < 2 {
2439
return nil, fmt.Errorf("need at least two signing keys")
2540
}

utils/musig_test.go

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,66 @@ package utils
33
import (
44
"testing"
55

6-
"github.com/btcsuite/btcd/btcec/v2"
76
"github.com/lightninglabs/loop/test"
87
"github.com/lightningnetwork/lnd/input"
98
"github.com/stretchr/testify/require"
109
)
1110

11+
// rawKeys returns serialized private keys for the given test seeds.
12+
func rawKeys(seeds ...int32) [][32]byte {
13+
keys := make([][32]byte, len(seeds))
14+
for i, seed := range seeds {
15+
privKey, _ := test.CreateKey(seed)
16+
copy(keys[i][:], privKey.Serialize())
17+
}
18+
19+
return keys
20+
}
21+
1222
// TestMuSig2SignRejectsSingleSigner ensures the helper fails fast with a clear
1323
// error instead of entering an invalid one-party MuSig2 flow.
1424
func TestMuSig2SignRejectsSingleSigner(t *testing.T) {
15-
privKey, pubKey := test.CreateKey(1)
16-
1725
_, err := MuSig2Sign(
1826
input.MuSig2Version100RC2,
19-
[]*btcec.PrivateKey{privKey},
20-
[]*btcec.PublicKey{pubKey},
27+
rawKeys(1),
2128
&input.MuSig2Tweaks{},
2229
[32]byte{},
2330
)
2431
require.ErrorContains(t, err, "need at least two signing keys")
2532
}
2633

27-
// TestMuSig2SignRejectsMismatchedKeyCounts ensures we fail before creating any
28-
// MuSig2 sessions when the signer sets are inconsistent.
29-
func TestMuSig2SignRejectsMismatchedKeyCounts(t *testing.T) {
30-
privKey, pubKey1 := test.CreateKey(1)
31-
_, pubKey2 := test.CreateKey(2)
34+
// TestMuSig2SignSupportsVersions verifies the helper works with the supported
35+
// MuSig2 versions used in Loop.
36+
func TestMuSig2SignSupportsVersions(t *testing.T) {
37+
t.Parallel()
3238

33-
_, err := MuSig2Sign(
39+
for _, version := range []input.MuSig2Version{
40+
input.MuSig2Version040,
3441
input.MuSig2Version100RC2,
35-
[]*btcec.PrivateKey{privKey},
36-
[]*btcec.PublicKey{pubKey1, pubKey2},
37-
&input.MuSig2Tweaks{},
38-
[32]byte{},
39-
)
40-
require.ErrorContains(t, err, "must match number of public keys")
42+
} {
43+
t.Run(testVersionName(version), func(t *testing.T) {
44+
t.Parallel()
45+
46+
sig, err := MuSig2Sign(
47+
version, rawKeys(1, 2), &input.MuSig2Tweaks{},
48+
[32]byte{},
49+
)
50+
require.NoError(t, err)
51+
require.Len(t, sig, 64)
52+
})
53+
}
54+
}
55+
56+
// testVersionName returns a stable subtest name for a MuSig2 version.
57+
func testVersionName(version input.MuSig2Version) string {
58+
switch version {
59+
case input.MuSig2Version040:
60+
return "MuSig2 0.4"
61+
62+
case input.MuSig2Version100RC2:
63+
return "MuSig2 1.0RC2"
64+
65+
default:
66+
return "unknown"
67+
}
4168
}

0 commit comments

Comments
 (0)