Skip to content
This repository has been archived by the owner on Mar 8, 2024. It is now read-only.

Add musig tests #106

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions core/types/external_tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
)

func TestPendingEtxsValidity(t *testing.T) {
pendingEtxs := &PendingEtxs{EmptyHeader(), []Transactions{Transactions{}, Transactions{}, Transactions{}}}
pendingEtxs := &PendingEtxs{EmptyHeader(), make(Transactions, 0)}

t.Log("Len of pendingEtxs", len(pendingEtxs.Etxs))

pendingEtxs.IsValid(nil, 2)
pendingEtxs.IsValid(nil)
}
2 changes: 1 addition & 1 deletion core/types/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func TestUTXOTransactionEncode(t *testing.T) {
Address: to.Bytes(),
}

utxo := &UtxoTx{
utxo := &QiTx{
ChainID: big.NewInt(1337),
TxIn: TxIns{in},
TxOut: TxOuts{newOut},
Expand Down
184 changes: 156 additions & 28 deletions core/types/utxo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"crypto/sha256"
"encoding/hex"
"fmt"
"strings"
"sync"
"testing"

Expand All @@ -20,27 +21,17 @@ func TestSingleSigner(t *testing.T) {
// ECDSA key
key, err := crypto.HexToECDSA("345debf66bc68724062b236d3b0a6eb30f051e725ebb770f1dc367f2c569f003")
if err != nil {
fmt.Println(err)
t.Fatal(err)
}
addr := crypto.PubkeyToAddress(key.PublicKey, location)
fmt.Println(addr.Hex())

b, err := hex.DecodeString("345debf66bc68724062b236d3b0a6eb30f051e725ebb770f1dc367f2c569f003")
if err != nil {
fmt.Println(err)
t.Fatal(err)
}

// btcec key for schnorr use
btcecKey, _ := btcec.PrivKeyFromBytes(b)

// Spendable out, could come from anywhere
coinbaseOutput := &TxOut{
Denomination: uint8(1),
Address: addr.Bytes(),
}

fmt.Println(coinbaseOutput)

coinbaseBlockHash := common.HexToHash("000000000000000000000000000000000000000000000000000012")
coinbaseIndex := uint32(0)

Expand Down Expand Up @@ -80,45 +71,33 @@ func TestSingleSigner(t *testing.T) {
}
Copy link
Member

Choose a reason for hiding this comment

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

single signer should use musig, not schnorr


func TestMultiSigners(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

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

please build these into test vectors, like you do for the test below.

e.g. provide a list of pubkeys with different corner cases (generator, off the curve, etc), and provide expected results.

What you have right now doesn't exercise failures due to combining invalid keys, etc


location := common.Location{0, 0}
// ECDSA key
key1, err := crypto.HexToECDSA("345debf66bc68724062b236d3b0a6eb30f051e725ebb770f1dc367f2c569f003")
if err != nil {
fmt.Println(err)
t.Fatal(err)
}
addr1 := crypto.PubkeyToAddress(key1.PublicKey, location)

b1, err := hex.DecodeString("345debf66bc68724062b236d3b0a6eb30f051e725ebb770f1dc367f2c569f003")
if err != nil {
fmt.Println(err)
t.Fatal(err)
}

// btcec key for schnorr use
btcecKey1, _ := btcec.PrivKeyFromBytes(b1)

key2, err := crypto.HexToECDSA("000000f66bc68724062b236d3b0a6eb30f051e725ebb770f1dc367f2c569f003")
if err != nil {
fmt.Println(err)
t.Fatal(err)
}
addr2 := crypto.PubkeyToAddress(key2.PublicKey, location)
fmt.Println(addr2.Hex())

b2, err := hex.DecodeString("000000f66bc68724062b236d3b0a6eb30f051e725ebb770f1dc367f2c569f003")
if err != nil {
fmt.Println(err)
t.Fatal(err)
}

btcecKey2, _ := btcec.PrivKeyFromBytes(b2)

// Spendable out, could come from anywhere
coinbaseOutput := &TxOut{
Denomination: uint8(1),
Address: addr1.Bytes(),
}

fmt.Println(coinbaseOutput)

coinbaseIndex := uint32(0)

coinbaseBlockHash1 := common.HexToHash("00000000000000000000000000000000000000000000000000000")
Expand Down Expand Up @@ -264,3 +243,152 @@ func TestMultiSigners(t *testing.T) {
t.Fatalf("final sig is invalid!")
}
}

func TestVerify(t *testing.T) {
// Test that we mark a signature as valid when it is and invalid when it is not valid
testCases := []struct {
name string
privateKey string
publicKey string
messageDigest string
signature string
expectedResult bool
}{
{ // TEST CASE #1:
name: "Confirms a Valid Signature",
privateKey: "c90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b14e5c7",
publicKey: "04fac2114c2fbb091527eb7c64ecb11f8021cb45e8e7809d3c0938e4b8c0e5f84bc655c2105c3c5c380f2c8b8ce2c0c25b0d57062d2d28187254f0deb802b8891f",
messageDigest: "4df3c3f68fcc83b27e9d42c90431a72499f17875c81a599b566c9889b9696703",
signature: "5364b58801791a30ee9f2dfb16bdfb543800eccddb514c56c7b8d75e30d25149ba273d4e61d2bb29f6e9e8a29bc7a31f6653a53bd81cf6994df07e58b1cb768b",
expectedResult: true,
},
{ // TEST CASE #2:
name: "Confirms a Valid Signature",
privateKey: "c90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b14e5c7",
publicKey: "04fac2114c2fbb091527eb7c64ecb11f8021cb45e8e7809d3c0938e4b8c0e5f84bc655c2105c3c5c380f2c8b8ce2c0c25b0d57062d2d28187254f0deb802b8891f",
messageDigest: "0000000000000000000000000000000000000000000000000000000000000000",
signature: "f6b70ab3159a32120c3af5ada42625c08f5f3d412179d8763347a3b3a133b73389b5163772dd8f8c02ea513e81eb244508a81dc4a11495c1ee458a226e178a1a",
expectedResult: true,
},
{ // TEST CASE #3:
name: "Fails signature with public key not on the curve",
publicKey: "03eefdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34",
messageDigest: "4df3c3f68fcc83b27e9d42c90431a72499f17875c81a599b566c9889b9696703",
signature: "00000000000000000000003b78ce563f89a0ed9414f5aa28ad0d96d6795f9c6302a8dc32e64e86a333f20ef56eac9ba30b7246d6d25e22adb8c6be1aeb08d49d",
expectedResult: false,
},
{ // TEST CASE #4: FAILING
name: "Fails signature with incorrect R residuosity",
privateKey: "c90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b14e5c7",
publicKey: "04fac2114c2fbb091527eb7c64ecb11f8021cb45e8e7809d3c0938e4b8c0e5f84bc655c2105c3c5c380f2c8b8ce2c0c25b0d57062d2d28187254f0deb802b8891f",
messageDigest: "243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89",
signature: "48a215e87777e4fa800d5d2a3d7b858414401727063f2c189355853b9d0f9a87f468606087da7f2373befefa1259e71cccbdc9bd75eadd1a73e346420fa75cf7",
expectedResult: false,
},
{ // TEST CASE #5:
name: "Fails signature with negated message",
privateKey: "c90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b14e5c7",
publicKey: "04fac2114c2fbb091527eb7c64ecb11f8021cb45e8e7809d3c0938e4b8c0e5f84bc655c2105c3c5c380f2c8b8ce2c0c25b0d57062d2d28187254f0deb802b8891f",
messageDigest: "5e2d58d8b3bcdf1abadec7829054f90dda9805aab56c77333024b9d0a508b75c",
signature: "00da9b08172a9b6f0466a2defd817f2d7ab437e0d253cb5395a963866b3574bed092f9d860f1776a1f7412ad8a1eb50daccc222bc8c0e26b2056df2f273efdec",
expectedResult: false,
},
{ // TEST CASE #6:
name: "Fails signature with negated s value",
privateKey: "c90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b14e5c7",
publicKey: "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
messageDigest: "0000000000000000000000000000000000000000000000000000000000000000",
signature: "b75dea1788881b057ff2a2d5c2847a7bebbfe8d8f9c0d3e76caa7ac462f065780b979f9f782580dc8c410105eda618e3334236428a1522e58c1cb9bdf058a308",
expectedResult: false,
},
Copy link
Member

Choose a reason for hiding this comment

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

I believe the verifier should reject pubkey==generator, right? Need a test for that

}

var signature [64]byte
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
publicBytes, _ := hex.DecodeString(testCase.publicKey)
msgBytes, _ := hex.DecodeString(testCase.messageDigest)
sig, _ := hex.DecodeString(testCase.signature)
copy(signature[:], sig)
public, err := btcec.ParsePubKey(publicBytes)
if err != nil {
errorMessage := err.Error()
if strings.Contains(errorMessage, "invalid public key") && testCase.expectedResult == false {
return
}
t.Fatal(err)
}

sigFormatted, _ := schnorr.ParseSignature(signature[:])
result := sigFormatted.Verify(msgBytes, public)

if result != testCase.expectedResult { // || err != nil
t.Fatalf("Did not confirm/deny validity of signature as expected: Want: %t Got: %t Error: %s", testCase.expectedResult, result, err)
} else {
t.Logf("SUCCESS: Expected verify result. Schnorr Signature is valid: %t Error: %s", result, err)
}
})
}
}

// ModifyRSig takes a Schnorr signature and modifies its R component.
// signatureHex is the original signature in hexadecimal format.
// It returns the modified signature also in hexadecimal format.
func TestModifyRSig(t *testing.T) {
signatureHex := "b75dea1788881b057ff2a2d5c2847a7bebbfe8d8f9c0d3e76caa7ac462f06578f468606087da7f2373befefa1259e71cccbdc9bd75eadd1a73e346420fa75cf7"
// Decode the signature from hex format
signatureBytes, err := hex.DecodeString(signatureHex)
if err != nil {
t.Fatalf("Failed to parse signature: %s", err)
}

// Check if the signature length is even
if len(signatureBytes)%2 != 0 {
t.Fatalf("Failed to parse signature: %s", err)
}

// Calculate the length of R and S components
halfLength := len(signatureBytes) / 2

// Modify the R component
// Here, we simply invert the bytes of the R component
// You can replace this logic with any other modification you need
for i := 0; i < halfLength; i++ {
signatureBytes[i] = ^signatureBytes[i]
}

// Encode the modified signature back to hex format
modifiedSigHex := hex.EncodeToString(signatureBytes)
t.Log("Modified Signature: ", modifiedSigHex)
Copy link
Member

Choose a reason for hiding this comment

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

You build the modified sig, but then you don't check it against expected result

Copy link
Author

Choose a reason for hiding this comment

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

Used this to generate it for the test case above, likely should be considered dead code.

}

// ModifySSig takes a Schnorr signature and modifies its S component.
// signatureHex is the original signature in hexadecimal format.
// It returns the modified signature also in hexadecimal format.
func TestModifySSig(t *testing.T) {
signatureHex := "b75dea1788881b057ff2a2d5c2847a7bebbfe8d8f9c0d3e76caa7ac462f06578f468606087da7f2373befefa1259e71cccbdc9bd75eadd1a73e346420fa75cf7"
// Decode the signature from hex format
signatureBytes, err := hex.DecodeString(signatureHex)
if err != nil {
t.Fatalf("Failed to parse signature: %s", err)
}

// Check if the signature length is even
if len(signatureBytes)%2 != 0 {
t.Fatalf("Signature length is not even: %s", err)
}

// Calculate the length of R and S components
halfLength := len(signatureBytes) / 2

// Modify the S component
// Here, we simply invert the bytes of the S component
// You can replace this logic with any other modification you need
for i := halfLength; i < len(signatureBytes); i++ {
signatureBytes[i] = ^signatureBytes[i]
}

// Encode the modified signature back to hex format
modifiedSigHex := hex.EncodeToString(signatureBytes)
t.Log("Modified Signature: ", modifiedSigHex)
Copy link
Member

Choose a reason for hiding this comment

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

again, computed sig is not verified

Copy link
Author

Choose a reason for hiding this comment

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

Same as above

}
Copy link
Member

Choose a reason for hiding this comment

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

There are no tests here for pubkey/signature aggregation

Loading