-
Notifications
You must be signed in to change notification settings - Fork 59
/
Copy pathschnorr.js
161 lines (148 loc) · 4.36 KB
/
schnorr.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import test from "tape";
import { fromHex, toHex } from "./util.js";
import fschnorr from "./fixtures/schnorr.json" assert { type: "json" };
export function parseBip340Vector(f) {
return {
...(f.d ? { d: fromHex(f.d), e: fromHex(f.e) } : {}),
...(f.exception ? { exception: f.exception } : { v: f.v }),
Q: fromHex(f.Q),
m: fromHex(f.m),
s: fromHex(f.s),
comment: f.comment,
};
}
export function parseTweakAddVector(f) {
return {
pubkey: fromHex(f.pubkey),
tweak: fromHex(f.tweak),
parity: f.parity,
result: f.result ? fromHex(f.result) : f.result,
};
}
export default function (secp256k1, type) {
const rand = () => Math.floor(Math.random() * 254) + 1; // [1..254];
const randPubKey = () =>
secp256k1.xOnlyPointFromScalar(new Uint8Array(32).fill(rand()));
test(`sign schnorr (${type})`, (t) => {
for (const fHex of fschnorr.bip340testvectors) {
if (fHex.d) {
const f = parseBip340Vector(fHex);
t.same(
secp256k1.signSchnorr(f.m, f.d, f.e),
f.s,
`signSchnorr(${fHex.m}, ...) == ${fHex.s}`
);
}
}
t.end();
});
test(`verify schnorr (${type})`, (t) => {
for (const fHex of fschnorr.bip340testvectors) {
const f = parseBip340Vector(fHex);
if (f.exception) {
t.throws(
() => {
secp256k1.verifySchnorr(f.m, f.Q, f.s);
},
new RegExp(f.exception),
`${f.comment} throws ${f.exception}`
);
} else {
const resultVerify = secp256k1.verifySchnorr(f.m, f.Q, f.s);
t.same(resultVerify, f.v, `verifySchnorr(${fHex.m}, ...) == ${fHex.v}`);
}
}
t.end();
});
test(`scalar to xOnlyPubkey (${type})`, (t) => {
for (const fHex of fschnorr.bip340testvectors) {
if (fHex.d) {
const f = parseBip340Vector(fHex);
t.same(
secp256k1.xOnlyPointFromScalar(f.d),
f.Q,
`xOnlyPointFromScalar(${fHex.d}) == ${fHex.Q}`
);
}
}
t.end();
});
test(`pubkey to xOnlyPubkey (${type})`, (t) => {
for (const fHex of fschnorr.bip340testvectors) {
if (fHex.d) {
const f = parseBip340Vector(fHex);
const pubkey1 = secp256k1.pointFromScalar(f.d, true);
const pubkey2 = secp256k1.pointFromScalar(f.d, false);
t.same(
secp256k1.xOnlyPointFromPoint(pubkey1),
f.Q,
`xOnlyPointFromPoint(${toHex(pubkey1)}) == ${fHex.Q}`
);
t.same(
secp256k1.xOnlyPointFromPoint(pubkey2),
f.Q,
`xOnlyPointFromPoint(${toHex(pubkey2)}) == ${fHex.Q}`
);
}
}
t.end();
});
test(`xonly pubkey tweak add schnorr (${type})`, (t) => {
for (const fHex of fschnorr.tweakaddvectors) {
const f = parseTweakAddVector(fHex);
const res = secp256k1.xOnlyPointAddTweak(f.pubkey, f.tweak);
if (f.result === null) {
t.same(
res,
f.result,
`xOnlyPointAddTweak returns null when G pubkey and n - 1 tweak used`
);
continue;
}
const { parity, xOnlyPubkey: result } = res;
t.same(
result,
f.result,
`xOnlyPointAddTweak(${fHex.pubkey},${fHex.tweak}) == ${fHex.result} result`
);
t.same(
parity,
f.parity,
`xOnlyPointAddTweak(${fHex.pubkey},${fHex.tweak}) == ${fHex.parity} parity`
);
// test check method
t.ok(
secp256k1.xOnlyPointAddTweakCheck(
f.pubkey,
f.tweak,
f.result,
f.parity
),
`xOnlyPointAddTweakCheck(${fHex.pubkey},${fHex.tweak},${fHex.result},${fHex.parity}) == true`
);
t.ok(
secp256k1.xOnlyPointAddTweakCheck(f.pubkey, f.tweak, f.result),
`xOnlyPointAddTweakCheck(${fHex.pubkey},${fHex.tweak},${fHex.result}) == true`
);
const dummyKey = randPubKey();
t.notOk(
secp256k1.xOnlyPointAddTweakCheck(
f.pubkey,
f.tweak,
dummyKey,
f.parity
),
`xOnlyPointAddTweakCheck(${fHex.pubkey},${fHex.tweak},${toHex(
dummyKey
)},${fHex.parity}) == false`
);
t.notOk(
secp256k1.xOnlyPointAddTweakCheck(f.pubkey, f.tweak, dummyKey),
`xOnlyPointAddTweakCheck(${fHex.pubkey},${fHex.tweak},${toHex(
dummyKey
)}) == false`
);
}
t.end();
});
}