@bsv/sdk 1.6.19 → 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/dist/cjs/package.json +3 -3
- package/dist/cjs/src/primitives/ECDSA.js +43 -42
- package/dist/cjs/src/primitives/ECDSA.js.map +1 -1
- package/dist/cjs/src/primitives/Point.js +70 -91
- 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/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/primitives/ECDSA.js +43 -42
- package/dist/esm/src/primitives/ECDSA.js.map +1 -1
- package/dist/esm/src/primitives/Point.js +67 -90
- 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/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/primitives/ECDSA.d.ts.map +1 -1
- package/dist/types/src/primitives/Point.d.ts +3 -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/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +5 -5
- package/dist/umd/bundle.js.map +1 -1
- package/package.json +3 -3
- package/src/primitives/ECDSA.ts +50 -49
- package/src/primitives/Point.ts +65 -99
- package/src/script/ScriptEvaluationError.ts +44 -0
- package/src/script/Spend.ts +14 -12
- package/src/script/index.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bsv/sdk",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.20",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "BSV Blockchain Software Development Kit",
|
|
6
6
|
"main": "dist/cjs/mod.js",
|
|
@@ -243,6 +243,7 @@
|
|
|
243
243
|
"devDependencies": {
|
|
244
244
|
"@eslint/js": "^9.23.0",
|
|
245
245
|
"@jest/globals": "^29.7.0",
|
|
246
|
+
"@rspack/cli": "^1.4.9",
|
|
246
247
|
"@types/jest": "^29.5.14",
|
|
247
248
|
"@types/node": "^22.13.14",
|
|
248
249
|
"eslint": "^9.23.0",
|
|
@@ -255,8 +256,7 @@
|
|
|
255
256
|
"ts2md": "^0.2.8",
|
|
256
257
|
"tsconfig-to-dual-package": "^1.2.0",
|
|
257
258
|
"typescript": "5.1",
|
|
258
|
-
"typescript-eslint": "^8.29.0"
|
|
259
|
-
"@rspack/cli": "^0.4.4"
|
|
259
|
+
"typescript-eslint": "^8.29.0"
|
|
260
260
|
},
|
|
261
261
|
"ts-standard": {
|
|
262
262
|
"project": "tsconfig.eslint.json",
|
package/src/primitives/ECDSA.ts
CHANGED
|
@@ -39,6 +39,11 @@ function truncateToN (
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
const curve = new Curve()
|
|
43
|
+
const bytes = curve.n.byteLength()
|
|
44
|
+
const ns1 = curve.n.subn(1)
|
|
45
|
+
const halfN = N_BIGINT >> 1n
|
|
46
|
+
|
|
42
47
|
/**
|
|
43
48
|
* Generates a digital signature for a given message.
|
|
44
49
|
*
|
|
@@ -60,84 +65,80 @@ export const sign = (
|
|
|
60
65
|
forceLowS: boolean = false,
|
|
61
66
|
customK?: BigNumber | ((iter: number) => BigNumber)
|
|
62
67
|
): Signature => {
|
|
63
|
-
|
|
68
|
+
// —— prepare inputs ────────────────────────────────────────────────────────
|
|
64
69
|
msg = truncateToN(msg)
|
|
70
|
+
const msgBig = BigInt('0x' + msg.toString(16))
|
|
71
|
+
const keyBig = BigInt('0x' + key.toString(16))
|
|
65
72
|
|
|
66
|
-
//
|
|
67
|
-
const bytes = curve.n.byteLength()
|
|
73
|
+
// DRBG seeding identical to previous implementation
|
|
68
74
|
const bkey = key.toArray('be', bytes)
|
|
69
|
-
|
|
70
|
-
// Zero-extend nonce to have the same byte size as N
|
|
71
75
|
const nonce = msg.toArray('be', bytes)
|
|
72
|
-
|
|
73
|
-
// Instantiate Hmac_DRBG
|
|
74
76
|
const drbg = new DRBG(bkey, nonce)
|
|
75
77
|
|
|
76
|
-
// Number of bytes to generate
|
|
77
|
-
const ns1 = curve.n.subn(1)
|
|
78
|
-
|
|
79
78
|
for (let iter = 0; ; iter++) {
|
|
80
|
-
//
|
|
81
|
-
let
|
|
79
|
+
// —— k generation & basic validity checks ───────────────────────────────
|
|
80
|
+
let kBN =
|
|
82
81
|
typeof customK === 'function'
|
|
83
82
|
? customK(iter)
|
|
84
83
|
: BigNumber.isBN(customK)
|
|
85
84
|
? customK
|
|
86
85
|
: new BigNumber(drbg.generate(bytes), 16)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) {
|
|
86
|
+
|
|
87
|
+
if (kBN == null) throw new Error('k is undefined')
|
|
88
|
+
kBN = truncateToN(kBN, true)
|
|
89
|
+
|
|
90
|
+
if (kBN.cmpn(1) <= 0 || kBN.cmp(ns1) >= 0) {
|
|
93
91
|
if (BigNumber.isBN(customK)) {
|
|
94
|
-
throw new Error(
|
|
95
|
-
'Invalid fixed custom K value (must be more than 1 and less than N-1)'
|
|
96
|
-
)
|
|
97
|
-
} else {
|
|
98
|
-
continue
|
|
92
|
+
throw new Error('Invalid fixed custom K value (must be >1 and <N‑1)')
|
|
99
93
|
}
|
|
94
|
+
continue
|
|
100
95
|
}
|
|
101
96
|
|
|
102
|
-
const
|
|
103
|
-
|
|
97
|
+
const kBig = BigInt('0x' + kBN.toString(16))
|
|
98
|
+
|
|
99
|
+
// —— R = k·G (Jacobian, window‑NAF) ──────────────────────────────────────
|
|
100
|
+
const R = scalarMultiplyWNAF(kBig, { x: GX_BIGINT, y: GY_BIGINT })
|
|
101
|
+
if (R.Z === 0n) { // point at infinity – should never happen for valid k
|
|
104
102
|
if (BigNumber.isBN(customK)) {
|
|
105
|
-
throw new Error(
|
|
106
|
-
'Invalid fixed custom K value (must not create a point at infinity when multiplied by the generator point)'
|
|
107
|
-
)
|
|
108
|
-
} else {
|
|
109
|
-
continue
|
|
103
|
+
throw new Error('Invalid fixed custom K value (k·G at infinity)')
|
|
110
104
|
}
|
|
105
|
+
continue
|
|
111
106
|
}
|
|
112
107
|
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
|
|
108
|
+
// affine X coordinate of R
|
|
109
|
+
const zInv = biModInv(R.Z)
|
|
110
|
+
const zInv2 = biModMul(zInv, zInv)
|
|
111
|
+
const xAff = biModMul(R.X, zInv2)
|
|
112
|
+
const rBig = modN(xAff)
|
|
113
|
+
|
|
114
|
+
if (rBig === 0n) {
|
|
116
115
|
if (BigNumber.isBN(customK)) {
|
|
117
|
-
throw new Error(
|
|
118
|
-
'Invalid fixed custom K value (when multiplied by G, the resulting x coordinate mod N must not be zero)'
|
|
119
|
-
)
|
|
120
|
-
} else {
|
|
121
|
-
continue
|
|
116
|
+
throw new Error('Invalid fixed custom K value (r == 0)')
|
|
122
117
|
}
|
|
118
|
+
continue
|
|
123
119
|
}
|
|
124
120
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
121
|
+
// —— s = k⁻¹ · (msg + r·key) mod n ─────────────────────────────────────
|
|
122
|
+
const kInv = modInvN(kBig)
|
|
123
|
+
const rTimesKey = modMulN(rBig, keyBig)
|
|
124
|
+
const sum = modN(msgBig + rTimesKey)
|
|
125
|
+
let sBig = modMulN(kInv, sum)
|
|
126
|
+
|
|
127
|
+
if (sBig === 0n) {
|
|
128
128
|
if (BigNumber.isBN(customK)) {
|
|
129
|
-
throw new Error(
|
|
130
|
-
'Invalid fixed custom K value (when used with the key, it cannot create a zero value for S)'
|
|
131
|
-
)
|
|
132
|
-
} else {
|
|
133
|
-
continue
|
|
129
|
+
throw new Error('Invalid fixed custom K value (s == 0)')
|
|
134
130
|
}
|
|
131
|
+
continue
|
|
135
132
|
}
|
|
136
133
|
|
|
137
|
-
//
|
|
138
|
-
if (forceLowS &&
|
|
139
|
-
|
|
134
|
+
// low‑S mitigation (BIP‑62/BIP‑340 style)
|
|
135
|
+
if (forceLowS && sBig > halfN) {
|
|
136
|
+
sBig = N_BIGINT - sBig
|
|
140
137
|
}
|
|
138
|
+
|
|
139
|
+
// —— convert back to BigNumber & return ─────────────────────────────────
|
|
140
|
+
const r = new BigNumber(rBig.toString(16), 16)
|
|
141
|
+
const s = new BigNumber(sBig.toString(16), 16)
|
|
141
142
|
return new Signature(r, s)
|
|
142
143
|
}
|
|
143
144
|
}
|
package/src/primitives/Point.ts
CHANGED
|
@@ -2,7 +2,6 @@ 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
|
-
import ReductionContext from './ReductionContext.js'
|
|
6
5
|
|
|
7
6
|
// -----------------------------------------------------------------------------
|
|
8
7
|
// BigInt helpers & constants (secp256k1) – hoisted so we don't recreate them on
|
|
@@ -44,6 +43,32 @@ export const biModInv = (a: bigint): bigint => { // binary‑ext GCD
|
|
|
44
43
|
}
|
|
45
44
|
export const biModSqr = (a: bigint): bigint => biModMul(a, a)
|
|
46
45
|
|
|
46
|
+
export const biModPow = (base: bigint, exp: bigint): bigint => {
|
|
47
|
+
let result = BI_ONE
|
|
48
|
+
base = biMod(base)
|
|
49
|
+
let e = exp
|
|
50
|
+
while (e > BI_ZERO) {
|
|
51
|
+
if ((e & BI_ONE) === BI_ONE) result = biModMul(result, base)
|
|
52
|
+
base = biModMul(base, base)
|
|
53
|
+
e >>= BI_ONE
|
|
54
|
+
}
|
|
55
|
+
return result
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const P_PLUS1_DIV4 = (P_BIGINT + 1n) >> 2n
|
|
59
|
+
|
|
60
|
+
export const biModSqrt = (a: bigint): bigint | null => {
|
|
61
|
+
const r = biModPow(a, P_PLUS1_DIV4)
|
|
62
|
+
return biModMul(r, r) === biMod(a) ? r : null
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const toBigInt = (x: BigNumber | number | number[] | string): bigint => {
|
|
66
|
+
if (BigNumber.isBN(x)) return BigInt('0x' + (x as BigNumber).toString(16))
|
|
67
|
+
if (typeof x === 'string') return BigInt('0x' + x)
|
|
68
|
+
if (Array.isArray(x)) return BigInt('0x' + toHex(x))
|
|
69
|
+
return BigInt(x as number)
|
|
70
|
+
}
|
|
71
|
+
|
|
47
72
|
// Generator point coordinates as bigint constants
|
|
48
73
|
export const GX_BIGINT = BigInt('0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798')
|
|
49
74
|
export const GY_BIGINT = BigInt('0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8')
|
|
@@ -191,10 +216,6 @@ export const modInvN = (a: bigint): bigint => {
|
|
|
191
216
|
* @property inf - Flag to record if the point is at infinity in the Elliptic Curve.
|
|
192
217
|
*/
|
|
193
218
|
export default class Point extends BasePoint {
|
|
194
|
-
private static readonly red: any = new ReductionContext('k256')
|
|
195
|
-
private static readonly a: BigNumber = new BigNumber(0).toRed(Point.red)
|
|
196
|
-
private static readonly b: BigNumber = new BigNumber(7).toRed(Point.red)
|
|
197
|
-
private static readonly zero: BigNumber = new BigNumber(0).toRed(Point.red)
|
|
198
219
|
x: BigNumber | null
|
|
199
220
|
y: BigNumber | null
|
|
200
221
|
inf: boolean
|
|
@@ -269,13 +290,6 @@ export default class Point extends BasePoint {
|
|
|
269
290
|
return Point.fromDER(bytes)
|
|
270
291
|
}
|
|
271
292
|
|
|
272
|
-
static redSqrtOptimized (y2: BigNumber): BigNumber {
|
|
273
|
-
const red = Point.red
|
|
274
|
-
const p = red.m // The modulus
|
|
275
|
-
const exponent = p.addn(1).iushrn(2) // (p + 1) / 4
|
|
276
|
-
return y2.redPow(exponent)
|
|
277
|
-
}
|
|
278
|
-
|
|
279
293
|
/**
|
|
280
294
|
* Generates a point from an x coordinate and a boolean indicating whether the corresponding
|
|
281
295
|
* y coordinate is odd.
|
|
@@ -292,66 +306,17 @@ export default class Point extends BasePoint {
|
|
|
292
306
|
* const point = Point.fromX(xCoordinate, true);
|
|
293
307
|
*/
|
|
294
308
|
static fromX (x: BigNumber | number | number[] | string, odd: boolean): Point {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
result = mod(result * base, modulus)
|
|
304
|
-
}
|
|
305
|
-
exponent >>= BigInt(1)
|
|
306
|
-
base = mod(base * base, modulus)
|
|
307
|
-
}
|
|
308
|
-
return result
|
|
309
|
-
}
|
|
310
|
-
function sqrtMod (a: bigint, p: bigint): bigint | null {
|
|
311
|
-
const exponent = (p + BigInt(1)) >> BigInt(2)
|
|
312
|
-
const sqrtCandidate = modPow(a, exponent, p)
|
|
313
|
-
if (mod(sqrtCandidate * sqrtCandidate, p) === mod(a, p)) {
|
|
314
|
-
return sqrtCandidate
|
|
315
|
-
} else {
|
|
316
|
-
return null
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Curve parameters for secp256k1
|
|
321
|
-
const p = BigInt(
|
|
322
|
-
'0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'
|
|
323
|
-
)
|
|
324
|
-
const b = BigInt(7)
|
|
325
|
-
|
|
326
|
-
let xBigInt: bigint
|
|
327
|
-
if (x instanceof BigNumber) {
|
|
328
|
-
xBigInt = BigInt('0x' + x.toString(16))
|
|
329
|
-
} else if (typeof x === 'string') {
|
|
330
|
-
xBigInt = BigInt('0x' + x)
|
|
331
|
-
} else if (Array.isArray(x)) {
|
|
332
|
-
xBigInt = BigInt('0x' + toHex(x).padStart(64, '0'))
|
|
333
|
-
} else if (typeof x === 'number') {
|
|
334
|
-
xBigInt = BigInt(x)
|
|
335
|
-
} else {
|
|
336
|
-
throw new Error('Invalid x-coordinate type')
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
xBigInt = mod(xBigInt, p)
|
|
340
|
-
|
|
341
|
-
const y2 = mod(modPow(xBigInt, BigInt(3), p) + b, p)
|
|
342
|
-
|
|
343
|
-
let y = sqrtMod(y2, p)
|
|
344
|
-
if (y === null) {
|
|
345
|
-
throw new Error('Invalid point')
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
const isYOdd = y % BigInt(2) === BigInt(1)
|
|
349
|
-
if ((odd && !isYOdd) || (!odd && isYOdd)) {
|
|
350
|
-
y = p - y
|
|
309
|
+
let xBigInt = toBigInt(x)
|
|
310
|
+
xBigInt = biMod(xBigInt)
|
|
311
|
+
const y2 = biModAdd(biModMul(biModSqr(xBigInt), xBigInt), 7n)
|
|
312
|
+
const y = biModSqrt(y2)
|
|
313
|
+
if (y === null) throw new Error('Invalid point')
|
|
314
|
+
let yBig = y
|
|
315
|
+
if ((yBig & BI_ONE) !== (odd ? BI_ONE : BI_ZERO)) {
|
|
316
|
+
yBig = biModSub(P_BIGINT, yBig)
|
|
351
317
|
}
|
|
352
|
-
|
|
353
318
|
const xBN = new BigNumber(xBigInt.toString(16), 16)
|
|
354
|
-
const yBN = new BigNumber(
|
|
319
|
+
const yBN = new BigNumber(yBig.toString(16), 16)
|
|
355
320
|
return new Point(xBN, yBN)
|
|
356
321
|
}
|
|
357
322
|
|
|
@@ -622,26 +587,31 @@ export default class Point extends BasePoint {
|
|
|
622
587
|
|
|
623
588
|
// P + (-P) = O
|
|
624
589
|
if (this.neg().eq(p)) {
|
|
625
|
-
return new Point(
|
|
590
|
+
return new Point(null, null)
|
|
626
591
|
}
|
|
627
592
|
|
|
628
593
|
// P + Q = O
|
|
629
594
|
if (this.x?.cmp(p.x ?? new BigNumber(0)) === 0) {
|
|
630
|
-
return new Point(
|
|
595
|
+
return new Point(null, null)
|
|
631
596
|
}
|
|
632
597
|
|
|
633
|
-
const
|
|
634
|
-
|
|
635
|
-
|
|
598
|
+
const P1 = {
|
|
599
|
+
X: BigInt('0x' + (this.x as BigNumber).fromRed().toString(16)),
|
|
600
|
+
Y: BigInt('0x' + (this.y as BigNumber).fromRed().toString(16)),
|
|
601
|
+
Z: BI_ONE
|
|
636
602
|
}
|
|
637
|
-
const
|
|
638
|
-
|
|
639
|
-
|
|
603
|
+
const Q1 = {
|
|
604
|
+
X: BigInt('0x' + (p.x as BigNumber).fromRed().toString(16)),
|
|
605
|
+
Y: BigInt('0x' + (p.y as BigNumber).fromRed().toString(16)),
|
|
606
|
+
Z: BI_ONE
|
|
640
607
|
}
|
|
641
|
-
const
|
|
642
|
-
|
|
643
|
-
const
|
|
644
|
-
|
|
608
|
+
const R = jpAdd(P1, Q1)
|
|
609
|
+
if (R.Z === BI_ZERO) return new Point(null, null)
|
|
610
|
+
const zInv = biModInv(R.Z)
|
|
611
|
+
const zInv2 = biModMul(zInv, zInv)
|
|
612
|
+
const xRes = biModMul(R.X, zInv2)
|
|
613
|
+
const yRes = biModMul(R.Y, biModMul(zInv2, zInv))
|
|
614
|
+
return new Point(xRes.toString(16), yRes.toString(16))
|
|
645
615
|
}
|
|
646
616
|
|
|
647
617
|
/**
|
|
@@ -654,25 +624,21 @@ export default class Point extends BasePoint {
|
|
|
654
624
|
* const result = P.dbl();
|
|
655
625
|
* */
|
|
656
626
|
dbl (): Point {
|
|
657
|
-
if (this.inf)
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
// 2P = O
|
|
662
|
-
const ys1 = (this.y ?? new BigNumber(0)).redAdd(this.y ?? new BigNumber(0))
|
|
663
|
-
if (ys1.cmpn(0) === 0) {
|
|
664
|
-
return new Point(new BigNumber(0), new BigNumber(0))
|
|
627
|
+
if (this.inf) return this
|
|
628
|
+
if (this.x === null || this.y === null) {
|
|
629
|
+
throw new Error('Point coordinates cannot be null')
|
|
665
630
|
}
|
|
666
631
|
|
|
667
|
-
const
|
|
668
|
-
const
|
|
669
|
-
|
|
670
|
-
const c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv)
|
|
632
|
+
const X = BigInt('0x' + this.x.fromRed().toString(16))
|
|
633
|
+
const Y = BigInt('0x' + this.y.fromRed().toString(16))
|
|
634
|
+
if (Y === BI_ZERO) return new Point(null, null)
|
|
671
635
|
|
|
672
|
-
const
|
|
673
|
-
const
|
|
674
|
-
|
|
675
|
-
|
|
636
|
+
const R = jpDouble({ X, Y, Z: BI_ONE })
|
|
637
|
+
const zInv = biModInv(R.Z)
|
|
638
|
+
const zInv2 = biModMul(zInv, zInv)
|
|
639
|
+
const xRes = biModMul(R.X, zInv2)
|
|
640
|
+
const yRes = biModMul(R.Y, biModMul(zInv2, zInv))
|
|
641
|
+
return new Point(xRes.toString(16), yRes.toString(16))
|
|
676
642
|
}
|
|
677
643
|
|
|
678
644
|
/**
|
|
@@ -1134,7 +1100,7 @@ export default class Point extends BasePoint {
|
|
|
1134
1100
|
for (i = 0; i < points.length; i++) {
|
|
1135
1101
|
const split = this.curve._endoSplit(coeffs[i])
|
|
1136
1102
|
let p = points[i]
|
|
1137
|
-
let beta: Point = p._getBeta() ?? new Point(
|
|
1103
|
+
let beta: Point = p._getBeta() ?? new Point(null, null)
|
|
1138
1104
|
|
|
1139
1105
|
if (split.k1.negative !== 0) {
|
|
1140
1106
|
split.k1.ineg()
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { toHex } from '../primitives/utils.js'
|
|
2
|
+
export default class ScriptEvaluationError extends Error {
|
|
3
|
+
txid: string
|
|
4
|
+
outputIndex: number
|
|
5
|
+
context: 'UnlockingScript' | 'LockingScript'
|
|
6
|
+
programCounter: number
|
|
7
|
+
stackState: number[][]
|
|
8
|
+
altStackState: number[][]
|
|
9
|
+
ifStackState: boolean[]
|
|
10
|
+
stackMem: number
|
|
11
|
+
altStackMem: number
|
|
12
|
+
|
|
13
|
+
constructor (params: {
|
|
14
|
+
message: string
|
|
15
|
+
txid: string
|
|
16
|
+
outputIndex: number
|
|
17
|
+
context: 'UnlockingScript' | 'LockingScript'
|
|
18
|
+
programCounter: number
|
|
19
|
+
stackState: number[][]
|
|
20
|
+
altStackState: number[][]
|
|
21
|
+
ifStackState: boolean[]
|
|
22
|
+
stackMem: number
|
|
23
|
+
altStackMem: number
|
|
24
|
+
}) {
|
|
25
|
+
const stackHex = params.stackState.map(s => s != null && typeof s.length !== 'undefined' ? toHex(s) : (s === null || s === undefined ? 'null/undef' : 'INVALID_STACK_ITEM')).join(', ')
|
|
26
|
+
const altStackHex = params.altStackState.map(s => s != null && typeof s.length !== 'undefined' ? toHex(s) : (s === null || s === undefined ? 'null/undef' : 'INVALID_STACK_ITEM')).join(', ')
|
|
27
|
+
const pcInfo = `Context: ${params.context}, PC: ${params.programCounter}`
|
|
28
|
+
const stackInfo = `Stack: [${stackHex}] (len: ${params.stackState.length}, mem: ${params.stackMem})`
|
|
29
|
+
const altStackInfo = `AltStack: [${altStackHex}] (len: ${params.altStackState.length}, mem: ${params.altStackMem})`
|
|
30
|
+
const ifStackInfo = `IfStack: [${params.ifStackState.join(', ')}]`
|
|
31
|
+
const fullMessage = `Script evaluation error: ${params.message}\nTXID: ${params.txid}, OutputIdx: ${params.outputIndex}\n${pcInfo}\n${stackInfo}\n${altStackInfo}\n${ifStackInfo}`
|
|
32
|
+
super(fullMessage)
|
|
33
|
+
this.name = this.constructor.name
|
|
34
|
+
this.txid = params.txid
|
|
35
|
+
this.outputIndex = params.outputIndex
|
|
36
|
+
this.context = params.context
|
|
37
|
+
this.programCounter = params.programCounter
|
|
38
|
+
this.stackState = params.stackState.map(s => s.slice())
|
|
39
|
+
this.altStackState = params.altStackState.map(s => s.slice())
|
|
40
|
+
this.ifStackState = params.ifStackState.slice()
|
|
41
|
+
this.stackMem = params.stackMem
|
|
42
|
+
this.altStackMem = params.altStackMem
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/script/Spend.ts
CHANGED
|
@@ -4,7 +4,8 @@ import Script from './Script.js'
|
|
|
4
4
|
import BigNumber from '../primitives/BigNumber.js'
|
|
5
5
|
import OP from './OP.js'
|
|
6
6
|
import ScriptChunk from './ScriptChunk.js'
|
|
7
|
-
import {
|
|
7
|
+
import { minimallyEncode } from '../primitives/utils.js'
|
|
8
|
+
import ScriptEvaluationError from './ScriptEvaluationError.js'
|
|
8
9
|
import * as Hash from '../primitives/Hash.js'
|
|
9
10
|
import TransactionSignature from '../primitives/TransactionSignature.js'
|
|
10
11
|
import PublicKey from '../primitives/PublicKey.js'
|
|
@@ -1054,16 +1055,17 @@ export default class Spend {
|
|
|
1054
1055
|
}
|
|
1055
1056
|
|
|
1056
1057
|
private scriptEvaluationError (str: string): void {
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1058
|
+
throw new ScriptEvaluationError({
|
|
1059
|
+
message: str,
|
|
1060
|
+
txid: this.sourceTXID,
|
|
1061
|
+
outputIndex: this.sourceOutputIndex,
|
|
1062
|
+
context: this.context,
|
|
1063
|
+
programCounter: this.programCounter,
|
|
1064
|
+
stackState: this.stack,
|
|
1065
|
+
altStackState: this.altStack,
|
|
1066
|
+
ifStackState: this.ifStack,
|
|
1067
|
+
stackMem: this.stackMem,
|
|
1068
|
+
altStackMem: this.altStackMem
|
|
1069
|
+
})
|
|
1068
1070
|
}
|
|
1069
1071
|
}
|
package/src/script/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ export { default as LockingScript } from './LockingScript.js'
|
|
|
4
4
|
export { default as UnlockingScript } from './UnlockingScript.js'
|
|
5
5
|
export { default as Spend } from './Spend.js'
|
|
6
6
|
export type { default as ScriptTemplateUnlock } from './ScriptTemplateUnlock.js'
|
|
7
|
+
export { default as ScriptEvaluationError } from './ScriptEvaluationError.js'
|
|
7
8
|
export type { default as ScriptTemplate } from './ScriptTemplate.js'
|
|
8
9
|
export * from './templates/index.js'
|
|
9
10
|
export type { default as ScriptChunk } from './ScriptChunk.js'
|