@bsv/sdk 1.6.18 → 1.6.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/dist/cjs/package.json +5 -9
- package/dist/cjs/src/auth/transports/SimplifiedFetchTransport.js +39 -39
- package/dist/cjs/src/auth/transports/SimplifiedFetchTransport.js.map +1 -1
- package/dist/cjs/src/primitives/ECDSA.js +69 -167
- package/dist/cjs/src/primitives/ECDSA.js.map +1 -1
- package/dist/cjs/src/primitives/Hash.js +660 -436
- package/dist/cjs/src/primitives/Hash.js.map +1 -1
- package/dist/cjs/src/primitives/Point.js +285 -293
- package/dist/cjs/src/primitives/Point.js.map +1 -1
- package/dist/cjs/src/script/ScriptEvaluationError.js +27 -0
- package/dist/cjs/src/script/ScriptEvaluationError.js.map +1 -0
- package/dist/cjs/src/script/Spend.js +13 -7
- package/dist/cjs/src/script/Spend.js.map +1 -1
- package/dist/cjs/src/script/index.js +3 -1
- package/dist/cjs/src/script/index.js.map +1 -1
- package/dist/cjs/src/transaction/Beef.js +4 -4
- package/dist/cjs/src/transaction/Transaction.js +3 -3
- package/dist/cjs/src/transaction/Transaction.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/auth/transports/SimplifiedFetchTransport.js +39 -39
- package/dist/esm/src/auth/transports/SimplifiedFetchTransport.js.map +1 -1
- package/dist/esm/src/primitives/ECDSA.js +69 -167
- package/dist/esm/src/primitives/ECDSA.js.map +1 -1
- package/dist/esm/src/primitives/Hash.js +672 -444
- package/dist/esm/src/primitives/Hash.js.map +1 -1
- package/dist/esm/src/primitives/Point.js +268 -293
- package/dist/esm/src/primitives/Point.js.map +1 -1
- package/dist/esm/src/script/ScriptEvaluationError.js +33 -0
- package/dist/esm/src/script/ScriptEvaluationError.js.map +1 -0
- package/dist/esm/src/script/Spend.js +14 -8
- package/dist/esm/src/script/Spend.js.map +1 -1
- package/dist/esm/src/script/index.js +1 -0
- package/dist/esm/src/script/index.js.map +1 -1
- package/dist/esm/src/transaction/Beef.js +4 -4
- package/dist/esm/src/transaction/Transaction.js +3 -3
- package/dist/esm/src/transaction/Transaction.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/auth/transports/SimplifiedFetchTransport.d.ts +1 -1
- package/dist/types/src/auth/transports/SimplifiedFetchTransport.d.ts.map +1 -1
- package/dist/types/src/primitives/ECDSA.d.ts.map +1 -1
- package/dist/types/src/primitives/Hash.d.ts +12 -19
- package/dist/types/src/primitives/Hash.d.ts.map +1 -1
- package/dist/types/src/primitives/Point.d.ts +37 -5
- package/dist/types/src/primitives/Point.d.ts.map +1 -1
- package/dist/types/src/script/ScriptEvaluationError.d.ts +24 -0
- package/dist/types/src/script/ScriptEvaluationError.d.ts.map +1 -0
- package/dist/types/src/script/Spend.d.ts.map +1 -1
- package/dist/types/src/script/index.d.ts +1 -0
- package/dist/types/src/script/index.d.ts.map +1 -1
- package/dist/types/src/transaction/Transaction.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +20 -1
- package/dist/umd/bundle.js.map +1 -0
- package/package.json +5 -9
- package/src/auth/transports/SimplifiedFetchTransport.ts +64 -67
- package/src/primitives/ECDSA.ts +80 -222
- package/src/primitives/Hash.ts +752 -589
- package/src/primitives/Point.ts +277 -336
- package/src/script/ScriptEvaluationError.ts +44 -0
- package/src/script/Spend.ts +14 -12
- package/src/script/index.ts +1 -0
- package/src/transaction/Beef.ts +4 -4
- package/src/transaction/Transaction.ts +11 -3
|
@@ -2,7 +2,195 @@ import BasePoint from './BasePoint.js';
|
|
|
2
2
|
import JPoint from './JacobianPoint.js';
|
|
3
3
|
import BigNumber from './BigNumber.js';
|
|
4
4
|
import { toArray, toHex } from './utils.js';
|
|
5
|
-
|
|
5
|
+
// -----------------------------------------------------------------------------
|
|
6
|
+
// BigInt helpers & constants (secp256k1) – hoisted so we don't recreate them on
|
|
7
|
+
// every Point.mul() call.
|
|
8
|
+
// -----------------------------------------------------------------------------
|
|
9
|
+
export const BI_ZERO = 0n;
|
|
10
|
+
export const BI_ONE = 1n;
|
|
11
|
+
export const BI_TWO = 2n;
|
|
12
|
+
export const BI_THREE = 3n;
|
|
13
|
+
export const BI_FOUR = 4n;
|
|
14
|
+
export const BI_EIGHT = 8n;
|
|
15
|
+
export const P_BIGINT = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn;
|
|
16
|
+
export const N_BIGINT = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n;
|
|
17
|
+
export const MASK_256 = (1n << 256n) - 1n; // 0xffff…ffff (256 sones)
|
|
18
|
+
export function red(x) {
|
|
19
|
+
// first fold
|
|
20
|
+
let hi = x >> 256n;
|
|
21
|
+
x = (x & MASK_256) + (hi << 32n) + hi * 977n;
|
|
22
|
+
// second fold (hi ≤ 2³² + 977 here, so one more pass is enough)
|
|
23
|
+
hi = x >> 256n;
|
|
24
|
+
x = (x & MASK_256) + (hi << 32n) + hi * 977n;
|
|
25
|
+
// final conditional subtraction
|
|
26
|
+
if (x >= P_BIGINT)
|
|
27
|
+
x -= P_BIGINT;
|
|
28
|
+
return x;
|
|
29
|
+
}
|
|
30
|
+
export const biMod = (a) => red((a % P_BIGINT + P_BIGINT) % P_BIGINT);
|
|
31
|
+
export const biModSub = (a, b) => (a >= b ? a - b : P_BIGINT - (b - a));
|
|
32
|
+
export const biModMul = (a, b) => red(a * b);
|
|
33
|
+
export const biModAdd = (a, b) => red(a + b);
|
|
34
|
+
export const biModInv = (a) => {
|
|
35
|
+
let lm = BI_ONE;
|
|
36
|
+
let hm = BI_ZERO;
|
|
37
|
+
let low = biMod(a);
|
|
38
|
+
let high = P_BIGINT;
|
|
39
|
+
while (low > BI_ONE) {
|
|
40
|
+
const r = high / low;
|
|
41
|
+
[lm, hm] = [hm - lm * r, lm];
|
|
42
|
+
[low, high] = [high - low * r, low];
|
|
43
|
+
}
|
|
44
|
+
return biMod(lm);
|
|
45
|
+
};
|
|
46
|
+
export const biModSqr = (a) => biModMul(a, a);
|
|
47
|
+
export const biModPow = (base, exp) => {
|
|
48
|
+
let result = BI_ONE;
|
|
49
|
+
base = biMod(base);
|
|
50
|
+
let e = exp;
|
|
51
|
+
while (e > BI_ZERO) {
|
|
52
|
+
if ((e & BI_ONE) === BI_ONE)
|
|
53
|
+
result = biModMul(result, base);
|
|
54
|
+
base = biModMul(base, base);
|
|
55
|
+
e >>= BI_ONE;
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
};
|
|
59
|
+
export const P_PLUS1_DIV4 = (P_BIGINT + 1n) >> 2n;
|
|
60
|
+
export const biModSqrt = (a) => {
|
|
61
|
+
const r = biModPow(a, P_PLUS1_DIV4);
|
|
62
|
+
return biModMul(r, r) === biMod(a) ? r : null;
|
|
63
|
+
};
|
|
64
|
+
const toBigInt = (x) => {
|
|
65
|
+
if (BigNumber.isBN(x))
|
|
66
|
+
return BigInt('0x' + x.toString(16));
|
|
67
|
+
if (typeof x === 'string')
|
|
68
|
+
return BigInt('0x' + x);
|
|
69
|
+
if (Array.isArray(x))
|
|
70
|
+
return BigInt('0x' + toHex(x));
|
|
71
|
+
return BigInt(x);
|
|
72
|
+
};
|
|
73
|
+
// Generator point coordinates as bigint constants
|
|
74
|
+
export const GX_BIGINT = BigInt('0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798');
|
|
75
|
+
export const GY_BIGINT = BigInt('0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8');
|
|
76
|
+
// Cache for precomputed windowed tables keyed by 'window:x:y'
|
|
77
|
+
const WNAF_TABLE_CACHE = new Map();
|
|
78
|
+
export const jpDouble = (P) => {
|
|
79
|
+
const { X: X1, Y: Y1, Z: Z1 } = P;
|
|
80
|
+
if (Y1 === BI_ZERO)
|
|
81
|
+
return { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO };
|
|
82
|
+
const Y1sq = biModMul(Y1, Y1);
|
|
83
|
+
const S = biModMul(BI_FOUR, biModMul(X1, Y1sq));
|
|
84
|
+
const M = biModMul(BI_THREE, biModMul(X1, X1));
|
|
85
|
+
const X3 = biModSub(biModMul(M, M), biModMul(BI_TWO, S));
|
|
86
|
+
const Y3 = biModSub(biModMul(M, biModSub(S, X3)), biModMul(BI_EIGHT, biModMul(Y1sq, Y1sq)));
|
|
87
|
+
const Z3 = biModMul(BI_TWO, biModMul(Y1, Z1));
|
|
88
|
+
return { X: X3, Y: Y3, Z: Z3 };
|
|
89
|
+
};
|
|
90
|
+
export const jpAdd = (P, Q) => {
|
|
91
|
+
if (P.Z === BI_ZERO)
|
|
92
|
+
return Q;
|
|
93
|
+
if (Q.Z === BI_ZERO)
|
|
94
|
+
return P;
|
|
95
|
+
const Z1Z1 = biModMul(P.Z, P.Z);
|
|
96
|
+
const Z2Z2 = biModMul(Q.Z, Q.Z);
|
|
97
|
+
const U1 = biModMul(P.X, Z2Z2);
|
|
98
|
+
const U2 = biModMul(Q.X, Z1Z1);
|
|
99
|
+
const S1 = biModMul(P.Y, biModMul(Z2Z2, Q.Z));
|
|
100
|
+
const S2 = biModMul(Q.Y, biModMul(Z1Z1, P.Z));
|
|
101
|
+
const H = biModSub(U2, U1);
|
|
102
|
+
const r = biModSub(S2, S1);
|
|
103
|
+
if (H === BI_ZERO) {
|
|
104
|
+
if (r === BI_ZERO)
|
|
105
|
+
return jpDouble(P);
|
|
106
|
+
return { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO }; // Infinity
|
|
107
|
+
}
|
|
108
|
+
const HH = biModMul(H, H);
|
|
109
|
+
const HHH = biModMul(H, HH);
|
|
110
|
+
const V = biModMul(U1, HH);
|
|
111
|
+
const X3 = biModSub(biModSub(biModMul(r, r), HHH), biModMul(BI_TWO, V));
|
|
112
|
+
const Y3 = biModSub(biModMul(r, biModSub(V, X3)), biModMul(S1, HHH));
|
|
113
|
+
const Z3 = biModMul(H, biModMul(P.Z, Q.Z));
|
|
114
|
+
return { X: X3, Y: Y3, Z: Z3 };
|
|
115
|
+
};
|
|
116
|
+
export const jpNeg = (P) => {
|
|
117
|
+
if (P.Z === BI_ZERO)
|
|
118
|
+
return P;
|
|
119
|
+
return { X: P.X, Y: P_BIGINT - P.Y, Z: P.Z };
|
|
120
|
+
};
|
|
121
|
+
// Fast windowed-NAF scalar multiplication (default window = 5) in Jacobian
|
|
122
|
+
// coordinates. Returns Q = k * P0 as a JacobianPoint.
|
|
123
|
+
export const scalarMultiplyWNAF = (k, P0, window = 5) => {
|
|
124
|
+
const key = `${window}:${P0.x.toString(16)}:${P0.y.toString(16)}`;
|
|
125
|
+
let tbl = WNAF_TABLE_CACHE.get(key);
|
|
126
|
+
let P;
|
|
127
|
+
if (tbl === undefined) {
|
|
128
|
+
// Convert affine to Jacobian and pre-compute odd multiples
|
|
129
|
+
const tblSize = 1 << (window - 1); // e.g. w=5 → 16 entries
|
|
130
|
+
tbl = new Array(tblSize);
|
|
131
|
+
P = { X: P0.x, Y: P0.y, Z: BI_ONE };
|
|
132
|
+
tbl[0] = P;
|
|
133
|
+
const twoP = jpDouble(P);
|
|
134
|
+
for (let i = 1; i < tblSize; i++) {
|
|
135
|
+
tbl[i] = jpAdd(tbl[i - 1], twoP);
|
|
136
|
+
}
|
|
137
|
+
WNAF_TABLE_CACHE.set(key, tbl);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
P = tbl[0];
|
|
141
|
+
}
|
|
142
|
+
// Build wNAF representation of k
|
|
143
|
+
const wnaf = [];
|
|
144
|
+
const wBig = 1n << BigInt(window);
|
|
145
|
+
const wHalf = wBig >> 1n;
|
|
146
|
+
let kTmp = k;
|
|
147
|
+
while (kTmp > 0n) {
|
|
148
|
+
if ((kTmp & BI_ONE) === BI_ZERO) {
|
|
149
|
+
wnaf.push(0);
|
|
150
|
+
kTmp >>= BI_ONE;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
let z = kTmp & (wBig - 1n); // kTmp mod 2^w
|
|
154
|
+
if (z > wHalf)
|
|
155
|
+
z -= wBig; // make it odd & within (-2^{w-1}, 2^{w-1})
|
|
156
|
+
wnaf.push(Number(z));
|
|
157
|
+
kTmp -= z;
|
|
158
|
+
kTmp >>= BI_ONE;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Accumulate from MSB to LSB
|
|
162
|
+
let Q = { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO }; // infinity
|
|
163
|
+
for (let i = wnaf.length - 1; i >= 0; i--) {
|
|
164
|
+
Q = jpDouble(Q);
|
|
165
|
+
const di = wnaf[i];
|
|
166
|
+
if (di !== 0) {
|
|
167
|
+
const idx = Math.abs(di) >> 1; // (|di|-1)/2 because di is odd
|
|
168
|
+
const addend = di > 0 ? tbl[idx] : jpNeg(tbl[idx]);
|
|
169
|
+
Q = jpAdd(Q, addend);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return Q;
|
|
173
|
+
};
|
|
174
|
+
export const modN = (a) => {
|
|
175
|
+
let r = a % N_BIGINT;
|
|
176
|
+
if (r < 0n)
|
|
177
|
+
r += N_BIGINT;
|
|
178
|
+
return r;
|
|
179
|
+
};
|
|
180
|
+
export const modMulN = (a, b) => modN(a * b);
|
|
181
|
+
/** modular inverse modulo n with plain extended‑gcd (not constant‑time) */
|
|
182
|
+
export const modInvN = (a) => {
|
|
183
|
+
let lm = 1n;
|
|
184
|
+
let hm = 0n;
|
|
185
|
+
let low = modN(a);
|
|
186
|
+
let high = N_BIGINT;
|
|
187
|
+
while (low > 1n) {
|
|
188
|
+
const q = high / low;
|
|
189
|
+
[lm, hm] = [hm - lm * q, lm];
|
|
190
|
+
[low, high] = [high - low * q, low];
|
|
191
|
+
}
|
|
192
|
+
return modN(lm);
|
|
193
|
+
};
|
|
6
194
|
/**
|
|
7
195
|
* `Point` class is a representation of an elliptic curve point with affine coordinates.
|
|
8
196
|
* It extends the functionality of BasePoint and carries x, y coordinates of point on the curve.
|
|
@@ -16,10 +204,6 @@ import ReductionContext from './ReductionContext.js';
|
|
|
16
204
|
* @property inf - Flag to record if the point is at infinity in the Elliptic Curve.
|
|
17
205
|
*/
|
|
18
206
|
export default class Point extends BasePoint {
|
|
19
|
-
static red = new ReductionContext('k256');
|
|
20
|
-
static a = new BigNumber(0).toRed(Point.red);
|
|
21
|
-
static b = new BigNumber(7).toRed(Point.red);
|
|
22
|
-
static zero = new BigNumber(0).toRed(Point.red);
|
|
23
207
|
x;
|
|
24
208
|
y;
|
|
25
209
|
inf;
|
|
@@ -84,12 +268,6 @@ export default class Point extends BasePoint {
|
|
|
84
268
|
const bytes = toArray(str, 'hex');
|
|
85
269
|
return Point.fromDER(bytes);
|
|
86
270
|
}
|
|
87
|
-
static redSqrtOptimized(y2) {
|
|
88
|
-
const red = Point.red;
|
|
89
|
-
const p = red.m; // The modulus
|
|
90
|
-
const exponent = p.addn(1).iushrn(2); // (p + 1) / 4
|
|
91
|
-
return y2.redPow(exponent);
|
|
92
|
-
}
|
|
93
271
|
/**
|
|
94
272
|
* Generates a point from an x coordinate and a boolean indicating whether the corresponding
|
|
95
273
|
* y coordinate is odd.
|
|
@@ -106,62 +284,18 @@ export default class Point extends BasePoint {
|
|
|
106
284
|
* const point = Point.fromX(xCoordinate, true);
|
|
107
285
|
*/
|
|
108
286
|
static fromX(x, odd) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
base = mod(base, modulus);
|
|
115
|
-
while (exponent > BigInt(0)) {
|
|
116
|
-
if ((exponent & BigInt(1)) === BigInt(1)) {
|
|
117
|
-
result = mod(result * base, modulus);
|
|
118
|
-
}
|
|
119
|
-
exponent >>= BigInt(1);
|
|
120
|
-
base = mod(base * base, modulus);
|
|
121
|
-
}
|
|
122
|
-
return result;
|
|
123
|
-
}
|
|
124
|
-
function sqrtMod(a, p) {
|
|
125
|
-
const exponent = (p + BigInt(1)) >> BigInt(2);
|
|
126
|
-
const sqrtCandidate = modPow(a, exponent, p);
|
|
127
|
-
if (mod(sqrtCandidate * sqrtCandidate, p) === mod(a, p)) {
|
|
128
|
-
return sqrtCandidate;
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
// Curve parameters for secp256k1
|
|
135
|
-
const p = BigInt('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F');
|
|
136
|
-
const b = BigInt(7);
|
|
137
|
-
let xBigInt;
|
|
138
|
-
if (x instanceof BigNumber) {
|
|
139
|
-
xBigInt = BigInt('0x' + x.toString(16));
|
|
140
|
-
}
|
|
141
|
-
else if (typeof x === 'string') {
|
|
142
|
-
xBigInt = BigInt('0x' + x);
|
|
143
|
-
}
|
|
144
|
-
else if (Array.isArray(x)) {
|
|
145
|
-
xBigInt = BigInt('0x' + toHex(x).padStart(64, '0'));
|
|
146
|
-
}
|
|
147
|
-
else if (typeof x === 'number') {
|
|
148
|
-
xBigInt = BigInt(x);
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
throw new Error('Invalid x-coordinate type');
|
|
152
|
-
}
|
|
153
|
-
xBigInt = mod(xBigInt, p);
|
|
154
|
-
const y2 = mod(modPow(xBigInt, BigInt(3), p) + b, p);
|
|
155
|
-
let y = sqrtMod(y2, p);
|
|
156
|
-
if (y === null) {
|
|
287
|
+
let xBigInt = toBigInt(x);
|
|
288
|
+
xBigInt = biMod(xBigInt);
|
|
289
|
+
const y2 = biModAdd(biModMul(biModSqr(xBigInt), xBigInt), 7n);
|
|
290
|
+
const y = biModSqrt(y2);
|
|
291
|
+
if (y === null)
|
|
157
292
|
throw new Error('Invalid point');
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
y = p - y;
|
|
293
|
+
let yBig = y;
|
|
294
|
+
if ((yBig & BI_ONE) !== (odd ? BI_ONE : BI_ZERO)) {
|
|
295
|
+
yBig = biModSub(P_BIGINT, yBig);
|
|
162
296
|
}
|
|
163
297
|
const xBN = new BigNumber(xBigInt.toString(16), 16);
|
|
164
|
-
const yBN = new BigNumber(
|
|
298
|
+
const yBN = new BigNumber(yBig.toString(16), 16);
|
|
165
299
|
return new Point(xBN, yBN);
|
|
166
300
|
}
|
|
167
301
|
/**
|
|
@@ -403,21 +537,30 @@ export default class Point extends BasePoint {
|
|
|
403
537
|
}
|
|
404
538
|
// P + (-P) = O
|
|
405
539
|
if (this.neg().eq(p)) {
|
|
406
|
-
return new Point(
|
|
540
|
+
return new Point(null, null);
|
|
407
541
|
}
|
|
408
542
|
// P + Q = O
|
|
409
543
|
if (this.x?.cmp(p.x ?? new BigNumber(0)) === 0) {
|
|
410
|
-
return new Point(
|
|
411
|
-
}
|
|
412
|
-
let c = this.y?.redSub(p.y ?? new BigNumber(0)) ?? new BigNumber(0);
|
|
413
|
-
if (c.cmpn(0) !== 0) {
|
|
414
|
-
c = c.redMul(this.x?.redSub(p.x ?? new BigNumber(0)).redInvm() ?? new BigNumber(1));
|
|
544
|
+
return new Point(null, null);
|
|
415
545
|
}
|
|
416
|
-
const
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
546
|
+
const P1 = {
|
|
547
|
+
X: BigInt('0x' + this.x.fromRed().toString(16)),
|
|
548
|
+
Y: BigInt('0x' + this.y.fromRed().toString(16)),
|
|
549
|
+
Z: BI_ONE
|
|
550
|
+
};
|
|
551
|
+
const Q1 = {
|
|
552
|
+
X: BigInt('0x' + p.x.fromRed().toString(16)),
|
|
553
|
+
Y: BigInt('0x' + p.y.fromRed().toString(16)),
|
|
554
|
+
Z: BI_ONE
|
|
555
|
+
};
|
|
556
|
+
const R = jpAdd(P1, Q1);
|
|
557
|
+
if (R.Z === BI_ZERO)
|
|
558
|
+
return new Point(null, null);
|
|
559
|
+
const zInv = biModInv(R.Z);
|
|
560
|
+
const zInv2 = biModMul(zInv, zInv);
|
|
561
|
+
const xRes = biModMul(R.X, zInv2);
|
|
562
|
+
const yRes = biModMul(R.Y, biModMul(zInv2, zInv));
|
|
563
|
+
return new Point(xRes.toString(16), yRes.toString(16));
|
|
421
564
|
}
|
|
422
565
|
/**
|
|
423
566
|
* Doubles the current point.
|
|
@@ -429,21 +572,21 @@ export default class Point extends BasePoint {
|
|
|
429
572
|
* const result = P.dbl();
|
|
430
573
|
* */
|
|
431
574
|
dbl() {
|
|
432
|
-
if (this.inf)
|
|
575
|
+
if (this.inf)
|
|
433
576
|
return this;
|
|
577
|
+
if (this.x === null || this.y === null) {
|
|
578
|
+
throw new Error('Point coordinates cannot be null');
|
|
434
579
|
}
|
|
435
|
-
|
|
436
|
-
const
|
|
437
|
-
if (
|
|
438
|
-
return new Point(
|
|
439
|
-
}
|
|
440
|
-
const
|
|
441
|
-
const
|
|
442
|
-
const
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
const ny = c.redMul((this.x ?? new BigNumber(0)).redSub(nx)).redISub(this.y ?? new BigNumber(0));
|
|
446
|
-
return new Point(nx, ny);
|
|
580
|
+
const X = BigInt('0x' + this.x.fromRed().toString(16));
|
|
581
|
+
const Y = BigInt('0x' + this.y.fromRed().toString(16));
|
|
582
|
+
if (Y === BI_ZERO)
|
|
583
|
+
return new Point(null, null);
|
|
584
|
+
const R = jpDouble({ X, Y, Z: BI_ONE });
|
|
585
|
+
const zInv = biModInv(R.Z);
|
|
586
|
+
const zInv2 = biModMul(zInv, zInv);
|
|
587
|
+
const xRes = biModMul(R.X, zInv2);
|
|
588
|
+
const yRes = biModMul(R.Y, biModMul(zInv2, zInv));
|
|
589
|
+
return new Point(xRes.toString(16), yRes.toString(16));
|
|
447
590
|
}
|
|
448
591
|
/**
|
|
449
592
|
* Returns X coordinate of point
|
|
@@ -481,86 +624,45 @@ export default class Point extends BasePoint {
|
|
|
481
624
|
k = new BigNumber(k, 16);
|
|
482
625
|
}
|
|
483
626
|
k = k;
|
|
484
|
-
if (
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
let Px;
|
|
504
|
-
let Py;
|
|
505
|
-
if (this === this.curve.g) {
|
|
506
|
-
Px = GX_BIGINT;
|
|
507
|
-
Py = GY_BIGINT;
|
|
508
|
-
}
|
|
509
|
-
else {
|
|
510
|
-
Px = BigInt('0x' + this.x.fromRed().toString(16));
|
|
511
|
-
Py = BigInt('0x' + this.y.fromRed().toString(16));
|
|
512
|
-
}
|
|
513
|
-
const mod = (a, m) => ((a % m) + m) % m;
|
|
514
|
-
const modMul = (a, b, m) => mod(a * b, m);
|
|
515
|
-
const modInv = (a, m) => {
|
|
516
|
-
let lm = one;
|
|
517
|
-
let hm = zero;
|
|
518
|
-
let low = mod(a, m);
|
|
519
|
-
let high = m;
|
|
520
|
-
while (low > one) {
|
|
521
|
-
const r = high / low;
|
|
522
|
-
const nm = hm - lm * r;
|
|
523
|
-
const neww = high - low * r;
|
|
524
|
-
hm = lm;
|
|
525
|
-
lm = nm;
|
|
526
|
-
high = low;
|
|
527
|
-
low = neww;
|
|
528
|
-
}
|
|
529
|
-
return mod(lm, m);
|
|
530
|
-
};
|
|
531
|
-
const scalarMultiply = (kVal, P0) => {
|
|
532
|
-
// Delegate to the hoisted windowed-NAF implementation above. We
|
|
533
|
-
// keep the wrapper so that the rest of the mul() code remains
|
|
534
|
-
// untouched while providing a massive speed-up (≈4-6×).
|
|
535
|
-
return scalarMultiplyWNAF(kVal, P0);
|
|
536
|
-
};
|
|
537
|
-
const R = scalarMultiply(kBig, { x: Px, y: Py });
|
|
538
|
-
if (R.Z === zero) {
|
|
539
|
-
return new Point(null, null);
|
|
540
|
-
}
|
|
541
|
-
const zInv = modInv(R.Z, p);
|
|
542
|
-
const zInv2 = modMul(zInv, zInv, p);
|
|
543
|
-
const xRes = modMul(R.X, zInv2, p);
|
|
544
|
-
const yRes = modMul(R.Y, modMul(zInv2, zInv, p), p);
|
|
545
|
-
const xBN = new BigNumber(xRes.toString(16), 16);
|
|
546
|
-
const yBN = new BigNumber(yRes.toString(16), 16);
|
|
547
|
-
const result = new Point(xBN, yBN);
|
|
548
|
-
if (isNeg) {
|
|
549
|
-
return result.neg();
|
|
550
|
-
}
|
|
551
|
-
return result;
|
|
627
|
+
if (this.inf) {
|
|
628
|
+
return this;
|
|
629
|
+
}
|
|
630
|
+
let kBig = BigInt('0x' + k.toString(16));
|
|
631
|
+
const isNeg = kBig < BI_ZERO;
|
|
632
|
+
if (isNeg)
|
|
633
|
+
kBig = -kBig;
|
|
634
|
+
kBig = biMod(kBig);
|
|
635
|
+
if (kBig === BI_ZERO) {
|
|
636
|
+
return new Point(null, null);
|
|
637
|
+
}
|
|
638
|
+
if (this.x === null || this.y === null) {
|
|
639
|
+
throw new Error('Point coordinates cannot be null');
|
|
640
|
+
}
|
|
641
|
+
let Px;
|
|
642
|
+
let Py;
|
|
643
|
+
if (this === this.curve.g) {
|
|
644
|
+
Px = GX_BIGINT;
|
|
645
|
+
Py = GY_BIGINT;
|
|
552
646
|
}
|
|
553
647
|
else {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
648
|
+
Px = BigInt('0x' + this.x.fromRed().toString(16));
|
|
649
|
+
Py = BigInt('0x' + this.y.fromRed().toString(16));
|
|
650
|
+
}
|
|
651
|
+
const R = scalarMultiplyWNAF(kBig, { x: Px, y: Py });
|
|
652
|
+
if (R.Z === BI_ZERO) {
|
|
653
|
+
return new Point(null, null);
|
|
654
|
+
}
|
|
655
|
+
const zInv = biModInv(R.Z);
|
|
656
|
+
const zInv2 = biModMul(zInv, zInv);
|
|
657
|
+
const xRes = biModMul(R.X, zInv2);
|
|
658
|
+
const yRes = biModMul(R.Y, biModMul(zInv2, zInv));
|
|
659
|
+
const xBN = new BigNumber(xRes.toString(16), 16);
|
|
660
|
+
const yBN = new BigNumber(yRes.toString(16), 16);
|
|
661
|
+
const result = new Point(xBN, yBN);
|
|
662
|
+
if (isNeg) {
|
|
663
|
+
return result.neg();
|
|
563
664
|
}
|
|
665
|
+
return result;
|
|
564
666
|
}
|
|
565
667
|
/**
|
|
566
668
|
* Performs a multiplication and addition operation in a single step.
|
|
@@ -894,7 +996,7 @@ export default class Point extends BasePoint {
|
|
|
894
996
|
for (i = 0; i < points.length; i++) {
|
|
895
997
|
const split = this.curve._endoSplit(coeffs[i]);
|
|
896
998
|
let p = points[i];
|
|
897
|
-
let beta = p._getBeta() ?? new Point(
|
|
999
|
+
let beta = p._getBeta() ?? new Point(null, null);
|
|
898
1000
|
if (split.k1.negative !== 0) {
|
|
899
1001
|
split.k1.ineg();
|
|
900
1002
|
p = p.neg(true);
|
|
@@ -968,131 +1070,4 @@ export default class Point extends BasePoint {
|
|
|
968
1070
|
};
|
|
969
1071
|
}
|
|
970
1072
|
}
|
|
971
|
-
// -----------------------------------------------------------------------------
|
|
972
|
-
// BigInt helpers & constants (secp256k1) – hoisted so we don't recreate them on
|
|
973
|
-
// every Point.mul() call.
|
|
974
|
-
// -----------------------------------------------------------------------------
|
|
975
|
-
const BI_ZERO = 0n;
|
|
976
|
-
const BI_ONE = 1n;
|
|
977
|
-
const BI_TWO = 2n;
|
|
978
|
-
const BI_THREE = 3n;
|
|
979
|
-
const BI_FOUR = 4n;
|
|
980
|
-
const BI_EIGHT = 8n;
|
|
981
|
-
const P_BIGINT = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn;
|
|
982
|
-
const MASK_256 = (1n << 256n) - 1n; // 0xffff…ffff (256 sones)
|
|
983
|
-
function red(x) {
|
|
984
|
-
// first fold
|
|
985
|
-
let hi = x >> 256n;
|
|
986
|
-
x = (x & MASK_256) + (hi << 32n) + hi * 977n;
|
|
987
|
-
// second fold (hi ≤ 2³² + 977 here, so one more pass is enough)
|
|
988
|
-
hi = x >> 256n;
|
|
989
|
-
x = (x & MASK_256) + (hi << 32n) + hi * 977n;
|
|
990
|
-
// final conditional subtraction
|
|
991
|
-
if (x >= P_BIGINT)
|
|
992
|
-
x -= P_BIGINT;
|
|
993
|
-
return x;
|
|
994
|
-
}
|
|
995
|
-
const biModSub = (a, b) => (a >= b ? a - b : P_BIGINT - (b - a));
|
|
996
|
-
const biModMul = (a, b) => red(a * b);
|
|
997
|
-
// Generator point coordinates as bigint constants
|
|
998
|
-
const GX_BIGINT = BigInt('0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798');
|
|
999
|
-
const GY_BIGINT = BigInt('0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8');
|
|
1000
|
-
// Cache for precomputed windowed tables keyed by 'window:x:y'
|
|
1001
|
-
const WNAF_TABLE_CACHE = new Map();
|
|
1002
|
-
const jpDouble = (P) => {
|
|
1003
|
-
const { X: X1, Y: Y1, Z: Z1 } = P;
|
|
1004
|
-
if (Y1 === BI_ZERO)
|
|
1005
|
-
return { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO };
|
|
1006
|
-
const Y1sq = biModMul(Y1, Y1);
|
|
1007
|
-
const S = biModMul(BI_FOUR, biModMul(X1, Y1sq));
|
|
1008
|
-
const M = biModMul(BI_THREE, biModMul(X1, X1));
|
|
1009
|
-
const X3 = biModSub(biModMul(M, M), biModMul(BI_TWO, S));
|
|
1010
|
-
const Y3 = biModSub(biModMul(M, biModSub(S, X3)), biModMul(BI_EIGHT, biModMul(Y1sq, Y1sq)));
|
|
1011
|
-
const Z3 = biModMul(BI_TWO, biModMul(Y1, Z1));
|
|
1012
|
-
return { X: X3, Y: Y3, Z: Z3 };
|
|
1013
|
-
};
|
|
1014
|
-
const jpAdd = (P, Q) => {
|
|
1015
|
-
if (P.Z === BI_ZERO)
|
|
1016
|
-
return Q;
|
|
1017
|
-
if (Q.Z === BI_ZERO)
|
|
1018
|
-
return P;
|
|
1019
|
-
const Z1Z1 = biModMul(P.Z, P.Z);
|
|
1020
|
-
const Z2Z2 = biModMul(Q.Z, Q.Z);
|
|
1021
|
-
const U1 = biModMul(P.X, Z2Z2);
|
|
1022
|
-
const U2 = biModMul(Q.X, Z1Z1);
|
|
1023
|
-
const S1 = biModMul(P.Y, biModMul(Z2Z2, Q.Z));
|
|
1024
|
-
const S2 = biModMul(Q.Y, biModMul(Z1Z1, P.Z));
|
|
1025
|
-
const H = biModSub(U2, U1);
|
|
1026
|
-
const r = biModSub(S2, S1);
|
|
1027
|
-
if (H === BI_ZERO) {
|
|
1028
|
-
if (r === BI_ZERO)
|
|
1029
|
-
return jpDouble(P);
|
|
1030
|
-
return { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO }; // Infinity
|
|
1031
|
-
}
|
|
1032
|
-
const HH = biModMul(H, H);
|
|
1033
|
-
const HHH = biModMul(H, HH);
|
|
1034
|
-
const V = biModMul(U1, HH);
|
|
1035
|
-
const X3 = biModSub(biModSub(biModMul(r, r), HHH), biModMul(BI_TWO, V));
|
|
1036
|
-
const Y3 = biModSub(biModMul(r, biModSub(V, X3)), biModMul(S1, HHH));
|
|
1037
|
-
const Z3 = biModMul(H, biModMul(P.Z, Q.Z));
|
|
1038
|
-
return { X: X3, Y: Y3, Z: Z3 };
|
|
1039
|
-
};
|
|
1040
|
-
const jpNeg = (P) => {
|
|
1041
|
-
if (P.Z === BI_ZERO)
|
|
1042
|
-
return P;
|
|
1043
|
-
return { X: P.X, Y: P_BIGINT - P.Y, Z: P.Z };
|
|
1044
|
-
};
|
|
1045
|
-
// Fast windowed-NAF scalar multiplication (default window = 5) in Jacobian
|
|
1046
|
-
// coordinates. Returns Q = k * P0 as a JacobianPoint.
|
|
1047
|
-
const scalarMultiplyWNAF = (k, P0, window = 5) => {
|
|
1048
|
-
const key = `${window}:${P0.x.toString(16)}:${P0.y.toString(16)}`;
|
|
1049
|
-
let tbl = WNAF_TABLE_CACHE.get(key);
|
|
1050
|
-
let P;
|
|
1051
|
-
if (tbl === undefined) {
|
|
1052
|
-
// Convert affine to Jacobian and pre-compute odd multiples
|
|
1053
|
-
const tblSize = 1 << (window - 1); // e.g. w=5 → 16 entries
|
|
1054
|
-
tbl = new Array(tblSize);
|
|
1055
|
-
P = { X: P0.x, Y: P0.y, Z: BI_ONE };
|
|
1056
|
-
tbl[0] = P;
|
|
1057
|
-
const twoP = jpDouble(P);
|
|
1058
|
-
for (let i = 1; i < tblSize; i++) {
|
|
1059
|
-
tbl[i] = jpAdd(tbl[i - 1], twoP);
|
|
1060
|
-
}
|
|
1061
|
-
WNAF_TABLE_CACHE.set(key, tbl);
|
|
1062
|
-
}
|
|
1063
|
-
else {
|
|
1064
|
-
P = tbl[0];
|
|
1065
|
-
}
|
|
1066
|
-
// Build wNAF representation of k
|
|
1067
|
-
const wnaf = [];
|
|
1068
|
-
const wBig = 1n << BigInt(window);
|
|
1069
|
-
const wHalf = wBig >> 1n;
|
|
1070
|
-
let kTmp = k;
|
|
1071
|
-
while (kTmp > 0n) {
|
|
1072
|
-
if ((kTmp & BI_ONE) === BI_ZERO) {
|
|
1073
|
-
wnaf.push(0);
|
|
1074
|
-
kTmp >>= BI_ONE;
|
|
1075
|
-
}
|
|
1076
|
-
else {
|
|
1077
|
-
let z = kTmp & (wBig - 1n); // kTmp mod 2^w
|
|
1078
|
-
if (z > wHalf)
|
|
1079
|
-
z -= wBig; // make it odd & within (-2^{w-1}, 2^{w-1})
|
|
1080
|
-
wnaf.push(Number(z));
|
|
1081
|
-
kTmp -= z;
|
|
1082
|
-
kTmp >>= BI_ONE;
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
// Accumulate from MSB to LSB
|
|
1086
|
-
let Q = { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO }; // infinity
|
|
1087
|
-
for (let i = wnaf.length - 1; i >= 0; i--) {
|
|
1088
|
-
Q = jpDouble(Q);
|
|
1089
|
-
const di = wnaf[i];
|
|
1090
|
-
if (di !== 0) {
|
|
1091
|
-
const idx = Math.abs(di) >> 1; // (|di|-1)/2 because di is odd
|
|
1092
|
-
const addend = di > 0 ? tbl[idx] : jpNeg(tbl[idx]);
|
|
1093
|
-
Q = jpAdd(Q, addend);
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
return Q;
|
|
1097
|
-
};
|
|
1098
1073
|
//# sourceMappingURL=Point.js.map
|