@bsv/sdk 1.0.0 → 1.0.1

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.
Files changed (123) hide show
  1. package/README.md +25 -3
  2. package/package.json +9 -5
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
  4. package/.github/ISSUE_TEMPLATE/discussion.md +0 -24
  5. package/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -23
  6. package/CHANGELOG.md +0 -72
  7. package/CONTRIBUTING.md +0 -85
  8. package/ROADMAP.md +0 -3
  9. package/docs/getting-started/COMMONJS.md +0 -94
  10. package/docs/getting-started/REACT-TS.md +0 -131
  11. package/docs/getting-started/TS-NODE.md +0 -106
  12. package/docs/getting-started/VUE.md +0 -103
  13. package/jest.config.js +0 -6
  14. package/mod.ts +0 -8
  15. package/src/compat/BSM.ts +0 -51
  16. package/src/compat/ECIES.ts +0 -557
  17. package/src/compat/HD.ts +0 -348
  18. package/src/compat/Mnemonic.ts +0 -295
  19. package/src/compat/__tests/BSM.test.ts +0 -38
  20. package/src/compat/__tests/ECIES.test.ts +0 -90
  21. package/src/compat/__tests/HD.test.ts +0 -405
  22. package/src/compat/__tests/Mnemonic.test.ts +0 -177
  23. package/src/compat/__tests/Mnemonic.vectors.ts +0 -172
  24. package/src/compat/bip-39-wordlist-en.ts +0 -2053
  25. package/src/compat/index.ts +0 -4
  26. package/src/messages/EncryptedMessage.ts +0 -70
  27. package/src/messages/SignedMessage.ts +0 -87
  28. package/src/messages/__tests/EncryptedMessage.test.ts +0 -36
  29. package/src/messages/__tests/SignedMessage.test.ts +0 -53
  30. package/src/messages/index.ts +0 -2
  31. package/src/primitives/AESGCM.ts +0 -479
  32. package/src/primitives/BasePoint.ts +0 -21
  33. package/src/primitives/BigNumber.ts +0 -4619
  34. package/src/primitives/Curve.ts +0 -1163
  35. package/src/primitives/DRBG.ts +0 -102
  36. package/src/primitives/ECDSA.ts +0 -164
  37. package/src/primitives/Hash.ts +0 -1420
  38. package/src/primitives/JacobianPoint.ts +0 -410
  39. package/src/primitives/K256.ts +0 -116
  40. package/src/primitives/Mersenne.ts +0 -123
  41. package/src/primitives/MontgomoryMethod.ts +0 -160
  42. package/src/primitives/Point.ts +0 -852
  43. package/src/primitives/PrivateKey.ts +0 -195
  44. package/src/primitives/PublicKey.ts +0 -154
  45. package/src/primitives/Random.ts +0 -55
  46. package/src/primitives/ReductionContext.ts +0 -528
  47. package/src/primitives/Signature.ts +0 -235
  48. package/src/primitives/SymmetricKey.ts +0 -75
  49. package/src/primitives/TransactionSignature.ts +0 -189
  50. package/src/primitives/__tests/AESGCM.test.ts +0 -338
  51. package/src/primitives/__tests/BRC42.private.vectors.ts +0 -33
  52. package/src/primitives/__tests/BRC42.public.vectors.ts +0 -33
  53. package/src/primitives/__tests/BigNumber.arithmatic.test.ts +0 -572
  54. package/src/primitives/__tests/BigNumber.binary.test.ts +0 -203
  55. package/src/primitives/__tests/BigNumber.constructor.test.ts +0 -176
  56. package/src/primitives/__tests/BigNumber.dhGroup.test.ts +0 -18
  57. package/src/primitives/__tests/BigNumber.fixtures.ts +0 -264
  58. package/src/primitives/__tests/BigNumber.serializers.test.ts +0 -157
  59. package/src/primitives/__tests/BigNumber.utils.test.ts +0 -347
  60. package/src/primitives/__tests/Curve.unit.test.ts +0 -192
  61. package/src/primitives/__tests/DRBG.test.ts +0 -18
  62. package/src/primitives/__tests/DRBG.vectors.ts +0 -167
  63. package/src/primitives/__tests/ECDH.test.ts +0 -31
  64. package/src/primitives/__tests/ECDSA.test.ts +0 -58
  65. package/src/primitives/__tests/HMAC.test.ts +0 -59
  66. package/src/primitives/__tests/Hash.test.ts +0 -121
  67. package/src/primitives/__tests/PBKDF2.vectors.ts +0 -119
  68. package/src/primitives/__tests/PrivateKey.test.ts +0 -17
  69. package/src/primitives/__tests/PublicKey.test.ts +0 -66
  70. package/src/primitives/__tests/Random.test.ts +0 -14
  71. package/src/primitives/__tests/Reader.test.ts +0 -296
  72. package/src/primitives/__tests/ReductionContext.test.ts +0 -279
  73. package/src/primitives/__tests/SymmetricKey.test.ts +0 -58
  74. package/src/primitives/__tests/SymmetricKey.vectors.ts +0 -40
  75. package/src/primitives/__tests/Writer.test.ts +0 -198
  76. package/src/primitives/__tests/sighash.vectors.ts +0 -3503
  77. package/src/primitives/__tests/utils.test.ts +0 -108
  78. package/src/primitives/index.ts +0 -8
  79. package/src/primitives/utils.ts +0 -665
  80. package/src/script/LockingScript.ts +0 -30
  81. package/src/script/OP.ts +0 -219
  82. package/src/script/Script.ts +0 -426
  83. package/src/script/ScriptChunk.ts +0 -7
  84. package/src/script/ScriptTemplate.ts +0 -36
  85. package/src/script/Spend.ts +0 -1379
  86. package/src/script/UnlockingScript.ts +0 -30
  87. package/src/script/__tests/Script.test.ts +0 -369
  88. package/src/script/__tests/Spend.test.ts +0 -248
  89. package/src/script/__tests/script.invalid.vectors.ts +0 -925
  90. package/src/script/__tests/script.valid.vectors.ts +0 -1120
  91. package/src/script/__tests/scriptFromVector.ts +0 -42
  92. package/src/script/__tests/spend.valid.vectors.ts +0 -2288
  93. package/src/script/index.ts +0 -7
  94. package/src/script/templates/P2PKH.ts +0 -109
  95. package/src/script/templates/RPuzzle.ts +0 -140
  96. package/src/script/templates/index.ts +0 -2
  97. package/src/transaction/Broadcaster.ts +0 -42
  98. package/src/transaction/ChainTracker.ts +0 -22
  99. package/src/transaction/FeeModel.ts +0 -13
  100. package/src/transaction/MerklePath.ts +0 -259
  101. package/src/transaction/Transaction.ts +0 -602
  102. package/src/transaction/TransactionInput.ts +0 -63
  103. package/src/transaction/TransactionOutput.ts +0 -37
  104. package/src/transaction/__tests/MerklePath.test.ts +0 -181
  105. package/src/transaction/__tests/Transaction.test.ts +0 -413
  106. package/src/transaction/__tests/bigtx.vectors.ts +0 -4
  107. package/src/transaction/__tests/bump.invalid.vectors.ts +0 -8
  108. package/src/transaction/__tests/bump.valid.vectors.ts +0 -4
  109. package/src/transaction/__tests/tx.invalid.vectors.ts +0 -281
  110. package/src/transaction/__tests/tx.valid.vectors.ts +0 -364
  111. package/src/transaction/broadcasters/ARC.ts +0 -106
  112. package/src/transaction/broadcasters/__tests/ARC.test.ts +0 -115
  113. package/src/transaction/broadcasters/index.ts +0 -1
  114. package/src/transaction/fee-models/SatoshisPerKilobyte.ts +0 -71
  115. package/src/transaction/fee-models/index.ts +0 -1
  116. package/src/transaction/index.ts +0 -6
  117. package/ts2md.json +0 -5
  118. package/tsconfig.base.json +0 -26
  119. package/tsconfig.cjs.json +0 -11
  120. package/tsconfig.eslint.json +0 -12
  121. package/tsconfig.esm.json +0 -9
  122. package/tsconfig.json +0 -17
  123. package/tsconfig.types.json +0 -11
@@ -1,852 +0,0 @@
1
- import BasePoint from './BasePoint.js'
2
- import JPoint from './JacobianPoint.js'
3
- import BigNumber from './BigNumber.js'
4
- import { toArray, toHex } from './utils.js'
5
- import ReductionContext from './ReductionContext.js'
6
-
7
- /**
8
- * `Point` class is a representation of an elliptic curve point with affine coordinates.
9
- * It extends the functionality of BasePoint and carries x, y coordinates of point on the curve.
10
- * It also introduces new methods for handling Point operations in elliptic curve.
11
- *
12
- * @class Point
13
- * @extends {BasePoint}
14
- *
15
- * @property x - The x-coordinate of the point.
16
- * @property y - The y-coordinate of the point.
17
- * @property inf - Flag to record if the point is at infinity in the Elliptic Curve.
18
- */
19
- export default class Point extends BasePoint {
20
- x: BigNumber | null
21
- y: BigNumber | null
22
- inf: boolean
23
-
24
- /**
25
- * Creates a point object from a given string. This string can represent coordinates in hex format, or points
26
- * in multiple established formats.
27
- * The function verifies the integrity of the provided data and throws errors if inconsistencies are found.
28
- *
29
- * @method fromString
30
- * @static
31
- * @param str - The point representation string.
32
- * @returns Returns a new point representing the given string.
33
- * @throws `Error` If the point string value has a wrong length.
34
- * @throws `Error` If the point format is unknown.
35
- *
36
- * @example
37
- * const pointStr = 'abcdef';
38
- * const point = Point.fromString(pointStr);
39
- */
40
- static fromString (str: string): Point {
41
- const bytes = toArray(str, 'hex')
42
-
43
- const len = 32
44
-
45
- // uncompressed, hybrid-odd, hybrid-even
46
- if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) &&
47
- bytes.length - 1 === 2 * len) {
48
- if (bytes[0] === 0x06) {
49
- if (bytes[bytes.length - 1] % 2 !== 0) {
50
- throw new Error('Point string value is wrong length')
51
- }
52
- } else if (bytes[0] === 0x07) {
53
- if (bytes[bytes.length - 1] % 2 !== 1) {
54
- throw new Error('Point string value is wrong length')
55
- }
56
- }
57
-
58
- const res = new Point(
59
- bytes.slice(1, 1 + len),
60
- bytes.slice(1 + len, 1 + 2 * len)
61
- )
62
-
63
- return res
64
- } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) &&
65
- bytes.length - 1 === len) {
66
- return Point.fromX(bytes.slice(1, 1 + len), bytes[0] === 0x03)
67
- }
68
- throw new Error('Unknown point format')
69
- }
70
-
71
- /**
72
- * Generates a point from an x coordinate and a boolean indicating whether the corresponding
73
- * y coordinate is odd.
74
- *
75
- * @method fromX
76
- * @static
77
- * @param x - The x coordinate of the point.
78
- * @param odd - Boolean indicating whether the corresponding y coordinate is odd or not.
79
- * @returns Returns the new point.
80
- * @throws `Error` If the point is invalid.
81
- *
82
- * @example
83
- * const xCoordinate = new BigNumber('10');
84
- * const point = Point.fromX(xCoordinate, true);
85
- */
86
-
87
- static fromX (x: BigNumber | number | number[] | string, odd: boolean): Point {
88
- const red = new ReductionContext('k256')
89
- const a = new BigNumber(0).toRed(red)
90
- const b = new BigNumber(7).toRed(red)
91
- const zero = new BigNumber(0).toRed(red)
92
- if (!BigNumber.isBN(x)) {
93
- x = new BigNumber(x as number, 16)
94
- }
95
- x = x as BigNumber
96
- if (x.red == null) {
97
- x = x.toRed(red)
98
- }
99
-
100
- const y2 = x.redSqr().redMul(x).redIAdd(x.redMul(a)).redIAdd(b)
101
- let y = y2.redSqrt()
102
- if (y.redSqr().redSub(y2).cmp(zero) !== 0) {
103
- throw new Error('invalid point')
104
- }
105
-
106
- // XXX Is there any way to tell if the number is odd without converting it
107
- // to non-red form?
108
- const isOdd = y.fromRed().isOdd()
109
- if ((odd && !isOdd) || (!odd && isOdd)) {
110
- y = y.redNeg()
111
- }
112
-
113
- return new Point(x, y)
114
- }
115
-
116
- /**
117
- * Generates a point from a serialized JSON object. The function accounts for different options in the JSON object,
118
- * including precomputed values for optimization of EC operations, and calls another helper function to turn nested
119
- * JSON points into proper Point objects.
120
- *
121
- * @method fromJSON
122
- * @static
123
- * @param obj - An object or array that holds the data for the point.
124
- * @param isRed - A boolean to direct how the Point is constructed from the JSON object.
125
- * @returns Returns a new point based on the deserialized JSON object.
126
- *
127
- * @example
128
- * const serializedPoint = '{"x":52,"y":15}';
129
- * const point = Point.fromJSON(serializedPoint, true);
130
- */
131
- static fromJSON (
132
- obj: string | any[], isRed: boolean
133
- ): Point {
134
- if (typeof obj === 'string') {
135
- obj = JSON.parse(obj)
136
- }
137
- const res = new Point(obj[0], obj[1], isRed)
138
- if (typeof obj[2] !== 'object') {
139
- return res
140
- }
141
-
142
- const obj2point = (obj): Point => {
143
- return new Point(obj[0], obj[1], isRed)
144
- }
145
-
146
- const pre = obj[2]
147
- res.precomputed = {
148
- beta: null,
149
- doubles: typeof pre.doubles === 'object' && pre.doubles !== null
150
- ? {
151
- step: pre.doubles.step,
152
- points: [res].concat(pre.doubles.points.map(obj2point))
153
- }
154
- : undefined,
155
- naf: typeof pre.naf === 'object' && pre.naf !== null
156
- ? {
157
- wnd: pre.naf.wnd,
158
- points: [res].concat(pre.naf.points.map(obj2point))
159
- }
160
- : undefined
161
- }
162
- return res
163
- }
164
-
165
- /**
166
- * @constructor
167
- * @param x - The x-coordinate of the point. May be a number, a BigNumber, a string (which will be interpreted as hex), a number array, or null. If null, an "Infinity" point is constructed.
168
- * @param y - The y-coordinate of the point, similar to x.
169
- * @param isRed - A boolean indicating if the point is a member of the field of integers modulo the k256 prime. Default is true.
170
- *
171
- * @example
172
- * new Point('abc123', 'def456');
173
- * new Point(null, null); // Generates Infinity point.
174
- */
175
- constructor (
176
- x: BigNumber | number | number[] | string | null,
177
- y: BigNumber | number | number[] | string | null,
178
- isRed: boolean = true
179
- ) {
180
- super('affine')
181
- this.precomputed = null
182
- if (x === null && y === null) {
183
- this.x = null
184
- this.y = null
185
- this.inf = true
186
- } else {
187
- if (!BigNumber.isBN(x)) {
188
- x = new BigNumber(x as number, 16)
189
- }
190
- this.x = x as BigNumber
191
- if (!BigNumber.isBN(y)) {
192
- y = new BigNumber(y as number, 16)
193
- }
194
- this.y = y as BigNumber
195
- // Force redgomery representation when loading from JSON
196
- if (isRed) {
197
- this.x.forceRed(this.curve.red)
198
- this.y.forceRed(this.curve.red)
199
- }
200
- if (this.x.red === null) { this.x = this.x.toRed(this.curve.red) }
201
- if (this.y.red === null) { this.y = this.y.toRed(this.curve.red) }
202
- this.inf = false
203
- }
204
- }
205
-
206
- /**
207
- * Validates if a point belongs to the curve. Follows the short Weierstrass
208
- * equation for elliptic curves: y^2 = x^3 + ax + b.
209
- *
210
- * @method validate
211
- * @returns {boolean} true if the point is on the curve, false otherwise.
212
- *
213
- * @example
214
- * const aPoint = new Point(x, y);
215
- * const isValid = aPoint.validate();
216
- */
217
- validate (): boolean {
218
- return this.curve.validate(this)
219
- }
220
-
221
- /**
222
- * Encodes the coordinates of a point into an array or a hexadecimal string.
223
- * The details of encoding are determined by the optional compact and enc parameters.
224
- *
225
- * @method encode
226
- * @param compact - If true, an additional prefix byte 0x02 or 0x03 based on the 'y' coordinate being even or odd respectively is used. If false, byte 0x04 is used.
227
- * @param enc - Expects the string 'hex' if hexadecimal string encoding is required instead of an array of numbers.
228
- * @throws Will throw an error if the specified encoding method is not recognized. Expects 'hex'.
229
- * @returns If enc is undefined, a byte array representation of the point will be returned. if enc is 'hex', a hexadecimal string representation of the point will be returned.
230
- *
231
- * @example
232
- * const aPoint = new Point(x, y);
233
- * const encodedPointArray = aPoint.encode();
234
- * const encodedPointHex = aPoint.encode(true, 'hex');
235
- */
236
- encode (compact: boolean = true, enc?: 'hex'): number[] | string {
237
- const len = this.curve.p.byteLength()
238
- const x = this.getX().toArray('be', len)
239
- let res: number[]
240
- if (compact) {
241
- res = [this.getY().isEven() ? 0x02 : 0x03].concat(x)
242
- } else {
243
- res = [0x04].concat(x, this.getY().toArray('be', len))
244
- }
245
- if (enc !== 'hex') {
246
- return res
247
- } else {
248
- return toHex(res)
249
- }
250
- }
251
-
252
- /**
253
- * Converts the point coordinates to a hexadecimal string. A wrapper method
254
- * for encode. Byte 0x02 or 0x03 is used as prefix based on the 'y' coordinate being even or odd respectively.
255
- *
256
- * @method toString
257
- * @returns {string} A hexadecimal string representation of the point coordinates.
258
- *
259
- * @example
260
- * const aPoint = new Point(x, y);
261
- * const stringPoint = aPoint.toString();
262
- */
263
- toString (): string {
264
- return this.encode(true, 'hex') as string
265
- }
266
-
267
- /**
268
- * Exports the x and y coordinates of the point, and the precomputed doubles and non-adjacent form (NAF) for optimization. The output is an array.
269
- *
270
- * @method toJSON
271
- * @returns An Array where first two elements are the coordinates of the point and optional third element is an object with doubles and NAF points.
272
- *
273
- * @example
274
- * const aPoint = new Point(x, y);
275
- * const jsonPoint = aPoint.toJSON();
276
- */
277
- toJSON (): [BigNumber | null, BigNumber | null, { doubles: { step: any, points: any[] } | undefined, naf: { wnd: any, points: any[] } | undefined }?] {
278
- if (this.precomputed == null) { return [this.x, this.y] }
279
-
280
- return [this.x, this.y, typeof this.precomputed === 'object' && this.precomputed !== null
281
- ? {
282
- doubles: (this.precomputed.doubles != null)
283
- ? {
284
- step: this.precomputed.doubles.step,
285
- points: this.precomputed.doubles.points.slice(1)
286
- }
287
- : undefined,
288
- naf: (this.precomputed.naf != null)
289
- ? {
290
- wnd: this.precomputed.naf.wnd,
291
- points: this.precomputed.naf.points.slice(1)
292
- }
293
- : undefined
294
- }
295
- : undefined]
296
- }
297
-
298
- /**
299
- * Provides the point coordinates in a human-readable string format for debugging purposes.
300
- *
301
- * @method inspect
302
- * @returns String of the format '<EC Point x: x-coordinate y: y-coordinate>', or '<EC Point Infinity>' if the point is at infinity.
303
- *
304
- * @example
305
- * const aPoint = new Point(x, y);
306
- * console.log(aPoint.inspect());
307
- */
308
- inspect (): string {
309
- if (this.isInfinity()) {
310
- return '<EC Point Infinity>'
311
- }
312
- return '<EC Point x: ' + this.x.fromRed().toString(16, 2) +
313
- ' y: ' + this.y.fromRed().toString(16, 2) + '>'
314
- }
315
-
316
- /**
317
- * Checks if the point is at infinity.
318
- * @method isInfinity
319
- * @returns Returns whether or not the point is at infinity.
320
- *
321
- * @example
322
- * const p = new Point(null, null);
323
- * console.log(p.isInfinity()); // outputs: true
324
- */
325
- isInfinity (): boolean {
326
- return this.inf
327
- }
328
-
329
- /**
330
- * Adds another Point to this Point, returning a new Point.
331
- *
332
- * @method add
333
- * @param p - The Point to add to this one.
334
- * @returns A new Point that results from the addition.
335
- *
336
- * @example
337
- * const p1 = new Point(1, 2);
338
- * const p2 = new Point(2, 3);
339
- * const result = p1.add(p2);
340
- */
341
- add (p: Point): Point {
342
- // O + P = P
343
- if (this.inf) { return p }
344
-
345
- // P + O = P
346
- if (p.inf) { return this }
347
-
348
- // P + P = 2P
349
- if (this.eq(p)) { return this.dbl() }
350
-
351
- // P + (-P) = O
352
- if (this.neg().eq(p)) { return new Point(null, null) }
353
-
354
- // P + Q = O
355
- if (this.x.cmp(p.x) === 0) { return new Point(null, null) }
356
-
357
- let c = this.y.redSub(p.y)
358
- if (c.cmpn(0) !== 0) { c = c.redMul(this.x.redSub(p.x).redInvm()) }
359
- const nx = c.redSqr().redISub(this.x).redISub(p.x)
360
- const ny = c.redMul(this.x.redSub(nx)).redISub(this.y)
361
- return new Point(nx, ny)
362
- }
363
-
364
- /**
365
- * Doubles the current point.
366
- *
367
- * @method dbl
368
- *
369
- * @example
370
- * const P = new Point('123', '456');
371
- * const result = P.dbl();
372
- * */
373
- dbl (): Point {
374
- if (this.inf) { return this }
375
-
376
- // 2P = O
377
- const ys1 = this.y.redAdd(this.y)
378
- if (ys1.cmpn(0) === 0) {
379
- return new Point(null, null)
380
- }
381
-
382
- const a = this.curve.a
383
-
384
- const x2 = this.x.redSqr()
385
- const dyinv = ys1.redInvm()
386
- const c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv)
387
-
388
- const nx = c.redSqr().redISub(this.x.redAdd(this.x))
389
- const ny = c.redMul(this.x.redSub(nx)).redISub(this.y)
390
- return new Point(nx, ny)
391
- }
392
-
393
- /**
394
- * Returns X coordinate of point
395
- *
396
- * @example
397
- * const P = new Point('123', '456');
398
- * const x = P.getX();
399
- */
400
- getX (): BigNumber {
401
- return this.x.fromRed()
402
- }
403
-
404
- /**
405
- * Returns X coordinate of point
406
- *
407
- * @example
408
- * const P = new Point('123', '456');
409
- * const x = P.getX();
410
- */
411
- getY (): BigNumber {
412
- return this.y.fromRed()
413
- }
414
-
415
- /**
416
- * Multiplies this Point by a scalar value, returning a new Point.
417
- *
418
- * @method mul
419
- * @param k - The scalar value to multiply this Point by.
420
- * @returns A new Point that results from the multiplication.
421
- *
422
- * @example
423
- * const p = new Point(1, 2);
424
- * const result = p.mul(2); // this doubles the Point
425
- */
426
- mul (k: BigNumber | number | number[] | string): Point {
427
- if (!BigNumber.isBN(k)) {
428
- k = new BigNumber(k as number, 16)
429
- }
430
- k = k as BigNumber
431
- if (this.isInfinity()) {
432
- return this
433
- } else if (this._hasDoubles(k)) {
434
- return this._fixedNafMul(k)
435
- } else {
436
- return this._endoWnafMulAdd([this], [k]) as Point
437
- }
438
- }
439
-
440
- /**
441
- * Performs a multiplication and addition operation in a single step.
442
- * Multiplies this Point by k1, adds the resulting Point to the result of p2 multiplied by k2.
443
- *
444
- * @method mulAdd
445
- * @param k1 - The scalar value to multiply this Point by.
446
- * @param p2 - The other Point to be involved in the operation.
447
- * @param k2 - The scalar value to multiply the Point p2 by.
448
- * @returns A Point that results from the combined multiplication and addition operations.
449
- *
450
- * @example
451
- * const p1 = new Point(1, 2);
452
- * const p2 = new Point(2, 3);
453
- * const result = p1.mulAdd(2, p2, 3);
454
- */
455
- mulAdd (k1: BigNumber, p2: Point, k2: BigNumber): Point {
456
- const points = [this, p2]
457
- const coeffs = [k1, k2]
458
- return this._endoWnafMulAdd(points, coeffs) as Point
459
- }
460
-
461
- /**
462
- * Performs the Jacobian multiplication and addition operation in a single
463
- * step. Instead of returning a regular Point, the result is a JacobianPoint.
464
- *
465
- * @method jmulAdd
466
- * @param k1 - The scalar value to multiply this Point by.
467
- * @param p2 - The other Point to be involved in the operation
468
- * @param k2 - The scalar value to multiply the Point p2 by.
469
- * @returns A JacobianPoint that results from the combined multiplication and addition operation.
470
- *
471
- * @example
472
- * const p1 = new Point(1, 2);
473
- * const p2 = new Point(2, 3);
474
- * const result = p1.jmulAdd(2, p2, 3);
475
- */
476
- jmulAdd (k1: BigNumber, p2: Point, k2: BigNumber): JPoint {
477
- const points = [this, p2]
478
- const coeffs = [k1, k2]
479
- return this._endoWnafMulAdd(points, coeffs, true) as JPoint
480
- }
481
-
482
- /**
483
- * Checks if the Point instance is equal to another given Point.
484
- *
485
- * @method eq
486
- * @param p - The Point to be checked if equal to the current instance.
487
- *
488
- * @returns Whether the two Point instances are equal. Both the 'x' and 'y' coordinates have to match, and both points have to either be valid or at infinity for equality. If both conditions are true, it returns true, else it returns false.
489
- *
490
- * @example
491
- * const p1 = new Point(5, 20);
492
- * const p2 = new Point(5, 20);
493
- * const areEqual = p1.eq(p2); // returns true
494
- */
495
- eq (p: Point): boolean {
496
- return this === p || (
497
- (this.inf === p.inf) &&
498
- (this.inf || (this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0)))
499
- }
500
-
501
- /**
502
- * Negate a point. The negation of a point P is the mirror of P about x-axis.
503
- *
504
- * @method neg
505
- *
506
- * @example
507
- * const P = new Point('123', '456');
508
- * const result = P.neg();
509
- */
510
- neg (_precompute?: boolean): Point {
511
- if (this.inf) { return this }
512
-
513
- const res = new Point(this.x, this.y.redNeg())
514
- if (_precompute && (this.precomputed != null)) {
515
- const pre = this.precomputed
516
- const negate = (p: Point): Point => p.neg()
517
- res.precomputed = {
518
- naf: (pre.naf != null) && {
519
- wnd: pre.naf.wnd,
520
- points: pre.naf.points.map(negate)
521
- },
522
- doubles: (pre.doubles != null) && {
523
- step: pre.doubles.step,
524
- points: pre.doubles.points.map((p) => p.neg())
525
- },
526
- beta: undefined
527
- }
528
- }
529
- return res
530
- }
531
-
532
- /**
533
- * Performs the "doubling" operation on the Point a given number of times.
534
- * This is used in elliptic curve operations to perform multiplication by 2, multiple times.
535
- * If the point is at infinity, it simply returns the point because doubling
536
- * a point at infinity is still infinity.
537
- *
538
- * @method dblp
539
- * @param k - The number of times the "doubling" operation is to be performed on the Point.
540
- * @returns The Point after 'k' "doubling" operations have been performed.
541
- *
542
- * @example
543
- * const p = new Point(5, 20);
544
- * const doubledPoint = p.dblp(10); // returns the point after "doubled" 10 times
545
- */
546
- dblp (k: number): Point {
547
- /* eslint-disable @typescript-eslint/no-this-alias */
548
- let r: Point = this
549
- for (let i = 0; i < k; i++) { r = r.dbl() }
550
- return r
551
- }
552
-
553
- /**
554
- * Converts the point to a Jacobian point. If the point is at infinity, the corresponding Jacobian point
555
- * will also be at infinity.
556
- *
557
- * @method toJ
558
- * @returns Returns a new Jacobian point based on the current point.
559
- *
560
- * @example
561
- * const point = new Point(xCoordinate, yCoordinate);
562
- * const jacobianPoint = point.toJ();
563
- */
564
- toJ (): JPoint {
565
- if (this.inf) {
566
- return new JPoint(null, null, null)
567
- }
568
- const res = new JPoint(this.x, this.y, this.curve.one)
569
- return res
570
- }
571
-
572
- private _getBeta (): undefined | Point {
573
- if (typeof this.curve.endo !== 'object') { return }
574
-
575
- const pre = this.precomputed
576
- if (typeof pre === 'object' && pre !== null && typeof pre.beta === 'object' && pre.beta !== null) {
577
- return pre.beta as Point
578
- }
579
-
580
- const beta = new Point(this.x.redMul(this.curve.endo.beta), this.y)
581
- if (pre != null) {
582
- const curve = this.curve
583
- const endoMul = (p: Point): Point => {
584
- return new Point(p.x.redMul(curve.endo.beta), p.y)
585
- }
586
- pre.beta = beta
587
- beta.precomputed = {
588
- beta: null,
589
- naf: (pre.naf != null)
590
- ? {
591
- wnd: pre.naf.wnd,
592
- points: pre.naf.points.map(endoMul)
593
- }
594
- : undefined,
595
- doubles: (pre.doubles != null)
596
- ? {
597
- step: pre.doubles.step,
598
- points: pre.doubles.points.map(endoMul)
599
- }
600
- : undefined
601
- }
602
- }
603
- return beta
604
- }
605
-
606
- private _fixedNafMul (k: BigNumber): Point {
607
- if (typeof this.precomputed !== 'object' || this.precomputed === null) {
608
- throw new Error('_fixedNafMul requires precomputed values for the point')
609
- }
610
- const doubles = this._getDoubles()
611
-
612
- const naf = this.curve.getNAF(k, 1, this.curve._bitLength)
613
- let I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1)
614
- I /= 3
615
-
616
- // Translate into more windowed form
617
- const repr: number[] = []
618
- for (let j = 0; j < naf.length; j += doubles.step) {
619
- let nafW = 0
620
- for (let k = j + doubles.step - 1; k >= j; k--) {
621
- nafW = (nafW << 1) + naf[k]
622
- }
623
- repr.push(nafW)
624
- }
625
-
626
- let a = new JPoint(null, null, null)
627
- let b = new JPoint(null, null, null)
628
- for (let i = I; i > 0; i--) {
629
- for (let j = 0; j < repr.length; j++) {
630
- const nafW = repr[j]
631
- if (nafW === i) {
632
- b = b.mixedAdd(doubles.points[j])
633
- } else if (nafW === -i) {
634
- b = b.mixedAdd((doubles.points[j]).neg())
635
- }
636
- }
637
- a = a.add(b)
638
- }
639
- return a.toP()
640
- }
641
-
642
- private _wnafMulAdd (
643
- defW: number,
644
- points: Point[],
645
- coeffs: BigNumber[],
646
- len: number,
647
- jacobianResult?: boolean
648
- ): BasePoint {
649
- const wndWidth = this.curve._wnafT1
650
- const wnd = this.curve._wnafT2
651
- const naf = this.curve._wnafT3
652
-
653
- // Fill all arrays
654
- let max = 0
655
- for (let i = 0; i < len; i++) {
656
- const p = points[i]
657
- const nafPoints = p._getNAFPoints(defW)
658
- wndWidth[i] = nafPoints.wnd
659
- wnd[i] = nafPoints.points
660
- }
661
-
662
- // Comb small window NAFs
663
- for (let i = len - 1; i >= 1; i -= 2) {
664
- const a = i - 1
665
- const b = i
666
- if (wndWidth[a] !== 1 || wndWidth[b] !== 1) {
667
- naf[a] = this.curve
668
- .getNAF(coeffs[a], wndWidth[a], this.curve._bitLength)
669
- naf[b] = this.curve
670
- .getNAF(coeffs[b], wndWidth[b], this.curve._bitLength)
671
- max = Math.max(naf[a].length, max)
672
- max = Math.max(naf[b].length, max)
673
- continue
674
- }
675
-
676
- const comb: any[] = [
677
- points[a], /* 1 */
678
- null, /* 3 */
679
- null, /* 5 */
680
- points[b] /* 7 */
681
- ]
682
-
683
- // Try to avoid Projective points, if possible
684
- if (points[a].y.cmp(points[b].y) === 0) {
685
- comb[1] = points[a].add(points[b])
686
- comb[2] = points[a].toJ().mixedAdd(points[b].neg())
687
- } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) {
688
- comb[1] = points[a].toJ().mixedAdd(points[b])
689
- comb[2] = points[a].add(points[b].neg())
690
- } else {
691
- comb[1] = points[a].toJ().mixedAdd(points[b])
692
- comb[2] = points[a].toJ().mixedAdd(points[b].neg())
693
- }
694
-
695
- const index = [
696
- -3, /* -1 -1 */
697
- -1, /* -1 0 */
698
- -5, /* -1 1 */
699
- -7, /* 0 -1 */
700
- 0, /* 0 0 */
701
- 7, /* 0 1 */
702
- 5, /* 1 -1 */
703
- 1, /* 1 0 */
704
- 3 /* 1 1 */
705
- ]
706
-
707
- const jsf = this.curve.getJSF(coeffs[a], coeffs[b])
708
- max = Math.max(jsf[0].length, max)
709
- naf[a] = new Array(max)
710
- naf[b] = new Array(max)
711
- for (let j = 0; j < max; j++) {
712
- const ja = jsf[0][j] | 0
713
- const jb = jsf[1][j] | 0
714
-
715
- naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]
716
- naf[b][j] = 0
717
- wnd[a] = comb
718
- }
719
- }
720
-
721
- let acc = new JPoint(null, null, null)
722
- const tmp = this.curve._wnafT4
723
- for (let i = max; i >= 0; i--) {
724
- let k = 0
725
-
726
- while (i >= 0) {
727
- let zero = true
728
- for (let j = 0; j < len; j++) {
729
- tmp[j] = naf[j][i] | 0
730
- if (tmp[j] !== 0) { zero = false }
731
- }
732
- if (!zero) { break }
733
- k++
734
- i--
735
- }
736
- if (i >= 0) { k++ }
737
- acc = acc.dblp(k)
738
- if (i < 0) { break }
739
-
740
- for (let j = 0; j < len; j++) {
741
- const z = tmp[j]
742
- let p
743
- if (z === 0) {
744
- continue
745
- } else if (z > 0) {
746
- p = wnd[j][(z - 1) >> 1]
747
- } else if (z < 0) {
748
- p = wnd[j][(-z - 1) >> 1].neg()
749
- }
750
-
751
- if (p.type === 'affine') {
752
- acc = acc.mixedAdd(p)
753
- } else {
754
- acc = acc.add(p)
755
- }
756
- }
757
- }
758
- // Zeroify references
759
- for (let i = 0; i < len; i++) { wnd[i] = null }
760
-
761
- if (jacobianResult) {
762
- return acc
763
- } else {
764
- return acc.toP()
765
- }
766
- }
767
-
768
- private _endoWnafMulAdd (points: Point[], coeffs, jacobianResult?: boolean): BasePoint {
769
- const npoints = this.curve._endoWnafT1
770
- const ncoeffs = this.curve._endoWnafT2
771
- let i
772
- for (i = 0; i < points.length; i++) {
773
- const split = this.curve._endoSplit(coeffs[i])
774
- let p = points[i]
775
- let beta = p._getBeta()
776
-
777
- if (split.k1.negative !== 0) {
778
- split.k1.ineg()
779
- p = p.neg(true)
780
- }
781
- if (split.k2.negative !== 0) {
782
- split.k2.ineg()
783
- beta = beta.neg(true)
784
- }
785
-
786
- npoints[i * 2] = p
787
- npoints[i * 2 + 1] = beta
788
- ncoeffs[i * 2] = split.k1
789
- ncoeffs[i * 2 + 1] = split.k2
790
- }
791
- const res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult)
792
-
793
- // Clean-up references to points and coefficients
794
- for (let j = 0; j < i * 2; j++) {
795
- npoints[j] = null
796
- ncoeffs[j] = null
797
- }
798
- return res
799
- }
800
-
801
- private _hasDoubles (k: BigNumber): boolean {
802
- if (this.precomputed == null) { return false }
803
-
804
- const doubles = this.precomputed.doubles
805
- if (typeof doubles !== 'object') { return false }
806
-
807
- return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step)
808
- };
809
-
810
- private _getDoubles (
811
- step?: number,
812
- power?: number
813
- ): { step: number, points: any[] } {
814
- if (
815
- typeof this.precomputed === 'object' && this.precomputed !== null &&
816
- typeof this.precomputed.doubles === 'object' &&
817
- this.precomputed.doubles !== null
818
- ) {
819
- return this.precomputed.doubles
820
- }
821
-
822
- const doubles = [this]
823
- /* eslint-disable @typescript-eslint/no-this-alias */
824
- let acc: Point = this
825
- for (let i = 0; i < power; i += step) {
826
- for (let j = 0; j < step; j++) { acc = acc.dbl() }
827
- doubles.push(acc as this)
828
- }
829
- return {
830
- step,
831
- points: doubles
832
- }
833
- };
834
-
835
- private _getNAFPoints (wnd: number): { wnd: number, points: any[] } {
836
- if (
837
- typeof this.precomputed === 'object' && this.precomputed !== null &&
838
- typeof this.precomputed.naf === 'object' && this.precomputed.naf !== null
839
- ) {
840
- return this.precomputed.naf
841
- }
842
-
843
- const res = [this]
844
- const max = (1 << wnd) - 1
845
- const dbl = max === 1 ? null : this.dbl()
846
- for (let i = 1; i < max; i++) { res[i] = res[i - 1].add(dbl) as this }
847
- return {
848
- wnd,
849
- points: res
850
- }
851
- }
852
- }