mirror of
https://github.com/btcsuite/btcd.git
synced 2024-11-19 01:40:07 +01:00
btcec/schnorr/musig: update nonce test vectors to musig2 1.0.0
This commit is contained in:
parent
1567f20055
commit
3d9f4484df
@ -6,6 +6,11 @@ require (
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1
|
||||
github.com/stretchr/testify v1.8.0
|
||||
)
|
||||
|
||||
require github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect
|
||||
require (
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
13
btcec/go.sum
13
btcec/go.sum
@ -1,8 +1,21 @@
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
54
btcec/schnorr/musig2/data/nonce_agg_vectors.json
Normal file
54
btcec/schnorr/musig2/data/nonce_agg_vectors.json
Normal file
@ -0,0 +1,54 @@
|
||||
{
|
||||
"pnonces": [
|
||||
"020151C80F435648DF67A22B749CD798CE54E0321D034B92B709B567D60A42E66603BA47FBC1834437B3212E89A84D8425E7BF12E0245D98262268EBDCB385D50641",
|
||||
"03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B833",
|
||||
"020151C80F435648DF67A22B749CD798CE54E0321D034B92B709B567D60A42E6660279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
|
||||
"03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60379BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
|
||||
"04FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B833",
|
||||
"03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B831",
|
||||
"03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A602FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30"
|
||||
],
|
||||
"valid_test_cases": [
|
||||
{
|
||||
"pnonce_indices": [0, 1],
|
||||
"expected": "035FE1873B4F2967F52FEA4A06AD5A8ECCBE9D0FD73068012C894E2E87CCB5804B024725377345BDE0E9C33AF3C43C0A29A9249F2F2956FA8CFEB55C8573D0262DC8"
|
||||
},
|
||||
{
|
||||
"pnonce_indices": [2, 3],
|
||||
"expected": "035FE1873B4F2967F52FEA4A06AD5A8ECCBE9D0FD73068012C894E2E87CCB5804B000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"comment": "Sum of second points encoded in the nonces is point at infinity which is serialized as 33 zero bytes"
|
||||
}
|
||||
],
|
||||
"error_test_cases": [
|
||||
{
|
||||
"pnonce_indices": [0, 4],
|
||||
"error": {
|
||||
"type": "invalid_contribution",
|
||||
"signer": 1,
|
||||
"contrib": "pubnonce"
|
||||
},
|
||||
"comment": "Public nonce from signer 1 is invalid due wrong tag, 0x04, in the first half",
|
||||
"btcec_err": "invalid public key: unsupported format: 4"
|
||||
},
|
||||
{
|
||||
"pnonce_indices": [5, 1],
|
||||
"error": {
|
||||
"type": "invalid_contribution",
|
||||
"signer": 0,
|
||||
"contrib": "pubnonce"
|
||||
},
|
||||
"comment": "Public nonce from signer 0 is invalid because the second half does not correspond to an X coordinate",
|
||||
"btcec_err": "invalid public key: x coordinate 48c264cdd57d3c24d79990b0f865674eb62a0f9018277a95011b41bfc193b831 is not on the secp256k1 curve"
|
||||
},
|
||||
{
|
||||
"pnonce_indices": [6, 1],
|
||||
"error": {
|
||||
"type": "invalid_contribution",
|
||||
"signer": 0,
|
||||
"contrib": "pubnonce"
|
||||
},
|
||||
"comment": "Public nonce from signer 0 is invalid because second half exceeds field size",
|
||||
"btcec_err": "invalid public key: x >= field prime"
|
||||
}
|
||||
]
|
||||
}
|
36
btcec/schnorr/musig2/data/nonce_gen_vectors.json
Normal file
36
btcec/schnorr/musig2/data/nonce_gen_vectors.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"test_cases": [
|
||||
{
|
||||
"rand_": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"sk": "0202020202020202020202020202020202020202020202020202020202020202",
|
||||
"aggpk": "0707070707070707070707070707070707070707070707070707070707070707",
|
||||
"msg": "0101010101010101010101010101010101010101010101010101010101010101",
|
||||
"extra_in": "0808080808080808080808080808080808080808080808080808080808080808",
|
||||
"expected": "BC6C683EBBCC39DCB3C29B3D010D2AAA7C86CFB562FC41ED9A460EE061013E75FB4AD2F0B816713269800D018803906D5481E00A940EAB4F4AC49B4A372EB0F4"
|
||||
},
|
||||
{
|
||||
"rand_": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"sk": "0202020202020202020202020202020202020202020202020202020202020202",
|
||||
"aggpk": "0707070707070707070707070707070707070707070707070707070707070707",
|
||||
"msg": "",
|
||||
"extra_in": "0808080808080808080808080808080808080808080808080808080808080808",
|
||||
"expected": "AAC4BFD707F4953B4063851D7E4AAD5C59D5D0BFB0E71012788A85698B5ACF8F11834D5051928424BA501C8CD064F3F942F8D4A07D8A2ED79F153E4ABD9EBBE9"
|
||||
},
|
||||
{
|
||||
"rand_": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"sk": "0202020202020202020202020202020202020202020202020202020202020202",
|
||||
"aggpk": "0707070707070707070707070707070707070707070707070707070707070707",
|
||||
"msg": "2626262626262626262626262626262626262626262626262626262626262626262626262626",
|
||||
"extra_in": "0808080808080808080808080808080808080808080808080808080808080808",
|
||||
"expected": "DF54500DD2B503DBA3753C48A9D6B67E6C11EC4325EDD1DC256C7F75D6A85DBECA6D9857A6F3F292FB3B50DBCBF69FADB67B1CDDB0EA6EB693F6455C4C9088E1"
|
||||
},
|
||||
{
|
||||
"rand_": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"sk": null,
|
||||
"aggpk": null,
|
||||
"msg": null,
|
||||
"extra_in": null,
|
||||
"expected": "7B3B5A002356471AF0E961DE2549C121BD0D48ABCEEDC6E034BDDF86AD3E0A187ECEE674CEF7364B0BC4BEEFB8B66CAD89F98DE2F8C5A5EAD5D1D1E4BD7D04CD"
|
||||
}
|
||||
]
|
||||
}
|
@ -46,6 +46,8 @@ var (
|
||||
"B65481B6BAAFB3C5810106717BEB")
|
||||
keyCombo4, _ = hex.DecodeString("2EB18851887E7BDC5E830E89B19DDBC28078" +
|
||||
"F1FA88AAD0AD01CA06FE4F80210B")
|
||||
|
||||
testVectorBaseDir = "data"
|
||||
)
|
||||
|
||||
// getInfinityTweak returns a tweak that, when tweaking the Generator, triggers
|
||||
@ -1340,210 +1342,6 @@ func TestMuSigEarlyNonce(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestMusig2NonceGenTestVectors tests the nonce generation function with
|
||||
// the testvectors defined in the Musig2 BIP.
|
||||
func TestMusig2NonceGenTestVectors(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
msg := bytes.Repeat([]byte{0x01}, 32)
|
||||
sk := bytes.Repeat([]byte{0x02}, 32)
|
||||
aggpk := bytes.Repeat([]byte{0x07}, 32)
|
||||
extra_in := bytes.Repeat([]byte{0x08}, 32)
|
||||
|
||||
testCases := []struct {
|
||||
opts nonceGenOpts
|
||||
expectedNonce string
|
||||
}{
|
||||
{
|
||||
opts: nonceGenOpts{
|
||||
randReader: &memsetRandReader{i: 0},
|
||||
secretKey: sk[:],
|
||||
combinedKey: aggpk[:],
|
||||
auxInput: extra_in[:],
|
||||
msg: msg[:],
|
||||
},
|
||||
expectedNonce: "BC6C683EBBCC39DCB3C29B3D010D2AAA7C86C" +
|
||||
"FB562FC41ED9A460EE061013E75FB4AD2F0B81671326" +
|
||||
"9800D018803906D5481E00A940EAB4F4AC49B4A372EB0F4",
|
||||
},
|
||||
{
|
||||
opts: nonceGenOpts{
|
||||
randReader: &memsetRandReader{i: 0},
|
||||
secretKey: sk[:],
|
||||
combinedKey: aggpk[:],
|
||||
auxInput: extra_in[:],
|
||||
msg: nil,
|
||||
},
|
||||
expectedNonce: "8A633F5EECBDB690A6BE4921426F41BE78D50" +
|
||||
"9DC1CE894C1215844C0E4C6DE7ABC9A5BE0A3BF3FE31" +
|
||||
"2CCB7E4817D2CB17A7CEA8382B73A99A583E323387B3C32",
|
||||
},
|
||||
{
|
||||
opts: nonceGenOpts{
|
||||
randReader: &memsetRandReader{i: 0},
|
||||
secretKey: nil,
|
||||
combinedKey: nil,
|
||||
auxInput: nil,
|
||||
msg: nil,
|
||||
},
|
||||
expectedNonce: "7B3B5A002356471AF0E961DE2549C121BD0D4" +
|
||||
"8ABCEEDC6E034BDDF86AD3E0A187ECEE674CEF7364B0" +
|
||||
"BC4BEEFB8B66CAD89F98DE2F8C5A5EAD5D1D1E4BD7D04CD",
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
nonce, err := GenNonces(withCustomOptions(testCase.opts))
|
||||
if err != nil {
|
||||
t.Fatalf("err gen nonce aux bytes %v", err)
|
||||
}
|
||||
|
||||
expectedBytes, _ := hex.DecodeString(testCase.expectedNonce)
|
||||
if !bytes.Equal(nonce.SecNonce[:], expectedBytes) {
|
||||
|
||||
t.Fatalf("nonces don't match: expected %x, got %x",
|
||||
expectedBytes, nonce.SecNonce[:])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
pNonce1, _ = hex.DecodeString("020151C80F435648DF67A22B749CD798CE54E0321D034B92B709B567D60A42E666" +
|
||||
"03BA47FBC1834437B3212E89A84D8425E7BF12E0245D98262268EBDCB385D50641")
|
||||
pNonce2, _ = hex.DecodeString("03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A6" +
|
||||
"0248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B833")
|
||||
|
||||
expectedNonce, _ = hex.DecodeString("035FE1873B4F2967F52FEA4A06AD5A8ECCBE9D0FD73068012C894E2E87CCB5804B" +
|
||||
"024725377345BDE0E9C33AF3C43C0A29A9249F2F2956FA8CFEB55C8573D0262DC8")
|
||||
|
||||
invalidNonce1, _ = hex.DecodeString("04FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A6" + "0248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B833")
|
||||
invalidNonce2, _ = hex.DecodeString("03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A6" + "0248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B831")
|
||||
invalidNonce3, _ = hex.DecodeString("03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A6" + "02FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30")
|
||||
)
|
||||
|
||||
type jsonNonceAggTestCase struct {
|
||||
Nonces []string `json:"nonces"`
|
||||
ExpectedNonce string `json:"expected_key"`
|
||||
ExpectedError string `json:"expected_error"`
|
||||
}
|
||||
|
||||
func TestMusig2AggregateNoncesTestVectors(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var jsonCases []jsonNonceAggTestCase
|
||||
|
||||
testCases := []struct {
|
||||
nonces [][]byte
|
||||
expectedNonce []byte
|
||||
expectedError error
|
||||
}{
|
||||
// Vector 1: Valid.
|
||||
{
|
||||
nonces: [][]byte{pNonce1, pNonce2},
|
||||
expectedNonce: expectedNonce,
|
||||
},
|
||||
|
||||
// Vector 2: Public nonce from signer 1 is invalid due wrong
|
||||
// tag, 0x04, inthe first half.
|
||||
{
|
||||
nonces: [][]byte{pNonce1, invalidNonce1},
|
||||
expectedError: secp256k1.ErrPubKeyInvalidFormat,
|
||||
},
|
||||
|
||||
// Vector 3: Public nonce from signer 0 is invalid because the
|
||||
// second half does not correspond to an X coordinate.
|
||||
{
|
||||
nonces: [][]byte{invalidNonce2, pNonce2},
|
||||
expectedError: secp256k1.ErrPubKeyNotOnCurve,
|
||||
},
|
||||
|
||||
// Vector 4: Public nonce from signer 0 is invalid because
|
||||
// second half exceeds field size.
|
||||
{
|
||||
nonces: [][]byte{invalidNonce3, pNonce2},
|
||||
expectedError: secp256k1.ErrPubKeyXTooBig,
|
||||
},
|
||||
|
||||
// Vector 5: Sum of second points encoded in the nonces would
|
||||
// be point at infinity, therefore set sum to base point G.
|
||||
{
|
||||
nonces: [][]byte{
|
||||
append(
|
||||
append([]byte{}, pNonce1[0:33]...),
|
||||
getGBytes()...,
|
||||
),
|
||||
append(
|
||||
append([]byte{}, pNonce2[0:33]...),
|
||||
getNegGBytes()...,
|
||||
),
|
||||
},
|
||||
expectedNonce: append(
|
||||
append([]byte{}, expectedNonce[0:33]...),
|
||||
getInfinityBytes()...,
|
||||
),
|
||||
},
|
||||
}
|
||||
for i, testCase := range testCases {
|
||||
testName := fmt.Sprintf("Vector %v", i+1)
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
var (
|
||||
nonces [][66]byte
|
||||
strNonces []string
|
||||
jsonError string
|
||||
)
|
||||
for _, nonce := range testCase.nonces {
|
||||
nonces = append(nonces, toPubNonceSlice(nonce))
|
||||
strNonces = append(strNonces, hex.EncodeToString(nonce))
|
||||
}
|
||||
|
||||
if testCase.expectedError != nil {
|
||||
jsonError = testCase.expectedError.Error()
|
||||
}
|
||||
|
||||
jsonCases = append(jsonCases, jsonNonceAggTestCase{
|
||||
Nonces: strNonces,
|
||||
ExpectedNonce: hex.EncodeToString(expectedNonce),
|
||||
ExpectedError: jsonError,
|
||||
})
|
||||
|
||||
aggregatedNonce, err := AggregateNonces(nonces)
|
||||
|
||||
switch {
|
||||
case testCase.expectedError != nil &&
|
||||
errors.Is(err, testCase.expectedError):
|
||||
|
||||
return
|
||||
case err != nil:
|
||||
t.Fatalf("aggregating nonce error: %v", err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(testCase.expectedNonce, aggregatedNonce[:]) {
|
||||
t.Fatalf("case: #%v, invalid nonce aggregation: "+
|
||||
"expected %x, got %x", i, testCase.expectedNonce,
|
||||
aggregatedNonce)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
if *dumpJson {
|
||||
jsonBytes, err := json.Marshal(jsonCases)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to encode json: %v", err)
|
||||
}
|
||||
|
||||
var formattedJson bytes.Buffer
|
||||
json.Indent(&formattedJson, jsonBytes, "", "\t")
|
||||
err = ioutil.WriteFile(
|
||||
nonceAggTestVectorName, formattedJson.Bytes(), 0644,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to write file: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type memsetRandReader struct {
|
||||
i int
|
||||
}
|
||||
|
@ -255,10 +255,10 @@ func genNonceAuxBytes(rand []byte, i int,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch len(opts.msg) {
|
||||
switch {
|
||||
// If the message isn't present, then we'll just write out a single
|
||||
// uint8 of a zero byte: m_prefixed = bytes(1, 0).
|
||||
case 0:
|
||||
case opts.msg == nil:
|
||||
if _, err := w.Write([]byte{0x00}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -266,6 +266,8 @@ func genNonceAuxBytes(rand []byte, i int,
|
||||
// Otherwise, we'll write a single byte of 0x01 with a 1 byte length
|
||||
// prefix, followed by the message itself with an 8 byte length prefix:
|
||||
// m_prefixed = bytes(1, 1) || bytes(8, len(m)) || m.
|
||||
case len(opts.msg) == 0:
|
||||
fallthrough
|
||||
default:
|
||||
if _, err := w.Write([]byte{0x01}); err != nil {
|
||||
return nil, err
|
||||
|
164
btcec/schnorr/musig2/nonces_test.go
Normal file
164
btcec/schnorr/musig2/nonces_test.go
Normal file
@ -0,0 +1,164 @@
|
||||
// Copyright 2013-2022 The btcsuite developers
|
||||
|
||||
package musig2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type nonceGenTestCase struct {
|
||||
Rand string `json:"rand_"`
|
||||
Sk string `json:"sk"`
|
||||
AggPk string `json:"aggpk"`
|
||||
Msg *string `json:"msg"`
|
||||
ExtraIn string `json:"extra_in"`
|
||||
|
||||
Expected string `json:"expected"`
|
||||
}
|
||||
|
||||
type nonceGenTestCases struct {
|
||||
TestCases []nonceGenTestCase `json:"test_cases"`
|
||||
}
|
||||
|
||||
const (
|
||||
nonceGenTestVectorsFileName = "nonce_gen_vectors.json"
|
||||
nonceAggTestVectorsFileName = "nonce_agg_vectors.json"
|
||||
)
|
||||
|
||||
// TestMusig2NonceGenTestVectors tests the nonce generation function with the
|
||||
// testvectors defined in the Musig2 BIP.
|
||||
func TestMusig2NonceGenTestVectors(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testVectorPath := path.Join(
|
||||
testVectorBaseDir, nonceGenTestVectorsFileName,
|
||||
)
|
||||
testVectorBytes, err := os.ReadFile(testVectorPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
var testCases nonceGenTestCases
|
||||
require.NoError(t, json.Unmarshal(testVectorBytes, &testCases))
|
||||
|
||||
for i, testCase := range testCases.TestCases {
|
||||
testCase := testCase
|
||||
|
||||
customOpts := nonceGenOpts{
|
||||
randReader: &memsetRandReader{i: 0},
|
||||
secretKey: mustParseHex(testCase.Sk),
|
||||
combinedKey: mustParseHex(testCase.AggPk),
|
||||
auxInput: mustParseHex(testCase.ExtraIn),
|
||||
}
|
||||
if testCase.Msg != nil {
|
||||
customOpts.msg = mustParseHex(*testCase.Msg)
|
||||
}
|
||||
|
||||
t.Run(fmt.Sprintf("test_case=%v", i), func(t *testing.T) {
|
||||
nonce, err := GenNonces(withCustomOptions(customOpts))
|
||||
if err != nil {
|
||||
t.Fatalf("err gen nonce aux bytes %v", err)
|
||||
}
|
||||
|
||||
expectedBytes, _ := hex.DecodeString(testCase.Expected)
|
||||
if !bytes.Equal(nonce.SecNonce[:], expectedBytes) {
|
||||
|
||||
t.Fatalf("nonces don't match: expected %x, got %x",
|
||||
expectedBytes, nonce.SecNonce[:])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type nonceAggError struct {
|
||||
Type string `json:"type"`
|
||||
Signer int `json:"signer"`
|
||||
Contrib string `json:"contrib"`
|
||||
}
|
||||
|
||||
type nonceAggValidCase struct {
|
||||
Indices []int `json:"pnonce_indices"`
|
||||
|
||||
Expected string `json:"expected"`
|
||||
|
||||
Comment string `json:"comment"`
|
||||
}
|
||||
|
||||
type nonceAggInvalidCase struct {
|
||||
Indices []int `json:"pnonce_indices"`
|
||||
|
||||
Error nonceAggError `json:"error"`
|
||||
|
||||
Comment string `json:"comment"`
|
||||
|
||||
ExpectedErr string `json:"btcec_err"`
|
||||
}
|
||||
|
||||
type nonceAggTestCases struct {
|
||||
Nonces []string `json:"pnonces"`
|
||||
|
||||
ValidCases []nonceAggValidCase `json:"valid_test_cases"`
|
||||
|
||||
InvalidCases []nonceAggInvalidCase `json:"error_test_cases"`
|
||||
}
|
||||
|
||||
// TestMusig2AggregateNoncesTestVectors tests that the musig2 implementation
|
||||
// passes the nonce aggregration test vectors for musig2 1.0.
|
||||
func TestMusig2AggregateNoncesTestVectors(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testVectorPath := path.Join(
|
||||
testVectorBaseDir, nonceAggTestVectorsFileName,
|
||||
)
|
||||
testVectorBytes, err := os.ReadFile(testVectorPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
var testCases nonceAggTestCases
|
||||
require.NoError(t, json.Unmarshal(testVectorBytes, &testCases))
|
||||
|
||||
nonces := make([][PubNonceSize]byte, len(testCases.Nonces))
|
||||
for i := range testCases.Nonces {
|
||||
var nonce [PubNonceSize]byte
|
||||
copy(nonce[:], mustParseHex(testCases.Nonces[i]))
|
||||
|
||||
nonces[i] = nonce
|
||||
}
|
||||
|
||||
for i, testCase := range testCases.ValidCases {
|
||||
testCase := testCase
|
||||
|
||||
var testNonces [][PubNonceSize]byte
|
||||
for _, idx := range testCase.Indices {
|
||||
testNonces = append(testNonces, nonces[idx])
|
||||
}
|
||||
|
||||
t.Run(fmt.Sprintf("valid_case=%v", i), func(t *testing.T) {
|
||||
aggregatedNonce, err := AggregateNonces(testNonces)
|
||||
require.NoError(t, err)
|
||||
|
||||
var expectedNonce [PubNonceSize]byte
|
||||
copy(expectedNonce[:], mustParseHex(testCase.Expected))
|
||||
|
||||
require.Equal(t, aggregatedNonce[:], expectedNonce[:])
|
||||
})
|
||||
}
|
||||
|
||||
for i, testCase := range testCases.InvalidCases {
|
||||
var testNonces [][PubNonceSize]byte
|
||||
for _, idx := range testCase.Indices {
|
||||
testNonces = append(testNonces, nonces[idx])
|
||||
}
|
||||
|
||||
t.Run(fmt.Sprintf("invalid_case=%v", i), func(t *testing.T) {
|
||||
_, err := AggregateNonces(testNonces)
|
||||
require.True(t, err != nil)
|
||||
require.Equal(t, testCase.ExpectedErr, err.Error())
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user