dcr-ts 0.2.0
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/CHANGELOG.md +563 -0
- package/LICENSE +15 -0
- package/README.md +259 -0
- package/SECURITY.md +106 -0
- package/dist/index.cjs +2424 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +955 -0
- package/dist/index.d.ts +955 -0
- package/dist/index.js +2328 -0
- package/dist/index.js.map +1 -0
- package/package.json +76 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2424 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var ripemd160 = require('@noble/hashes/ripemd160');
|
|
4
|
+
var secp256k1 = require('@noble/curves/secp256k1');
|
|
5
|
+
var ed25519 = require('@noble/curves/ed25519');
|
|
6
|
+
var hmac = require('@noble/hashes/hmac');
|
|
7
|
+
var sha512 = require('@noble/hashes/sha512');
|
|
8
|
+
var bip39 = require('@scure/bip39');
|
|
9
|
+
var english = require('@scure/bip39/wordlists/english');
|
|
10
|
+
|
|
11
|
+
// src/errors.ts
|
|
12
|
+
var BRAND = /* @__PURE__ */ Symbol.for("dcr-ts.DcrError");
|
|
13
|
+
var DcrError = class extends Error {
|
|
14
|
+
constructor(code, message, options) {
|
|
15
|
+
super(message, options);
|
|
16
|
+
this.code = code;
|
|
17
|
+
Object.defineProperty(this, BRAND, { value: true });
|
|
18
|
+
}
|
|
19
|
+
code;
|
|
20
|
+
name = "DcrError";
|
|
21
|
+
};
|
|
22
|
+
function isDcrError(e) {
|
|
23
|
+
return e instanceof DcrError || typeof e === "object" && e !== null && BRAND in e;
|
|
24
|
+
}
|
|
25
|
+
function hasErrorCode(e, code) {
|
|
26
|
+
return isDcrError(e) && e.code === code;
|
|
27
|
+
}
|
|
28
|
+
function err(code, who, message) {
|
|
29
|
+
return new DcrError(code, `${who}: ${message}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/bytes.ts
|
|
33
|
+
function copyOf(src, off, n) {
|
|
34
|
+
if (!Number.isInteger(off) || !Number.isInteger(n) || off < 0 || n < 0) {
|
|
35
|
+
throw err(
|
|
36
|
+
"not-an-integer",
|
|
37
|
+
"copyOf",
|
|
38
|
+
`offset and length must be non-negative integers, got ${shown(off)}, ${shown(n)}`
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
if (off + n > src.length) {
|
|
42
|
+
throw err(
|
|
43
|
+
"out-of-range",
|
|
44
|
+
"copyOf",
|
|
45
|
+
`reading ${n} bytes at ${off} overruns a ${src.length}-byte source`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
const out = new Uint8Array(n);
|
|
49
|
+
out.set(src.subarray(off, off + n));
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
function isBytes(v) {
|
|
53
|
+
return Object.prototype.toString.call(v) === "[object Uint8Array]";
|
|
54
|
+
}
|
|
55
|
+
function typeName(v) {
|
|
56
|
+
return Object.prototype.toString.call(v).slice(8, -1).toLowerCase();
|
|
57
|
+
}
|
|
58
|
+
var MAX_SHOWN_LENGTH = 32;
|
|
59
|
+
function shown(v) {
|
|
60
|
+
if (typeof v === "string") {
|
|
61
|
+
const head = v.length > MAX_SHOWN_LENGTH ? v.slice(0, MAX_SHOWN_LENGTH) : v;
|
|
62
|
+
let out = "";
|
|
63
|
+
for (const ch of head) {
|
|
64
|
+
const c = ch.codePointAt(0);
|
|
65
|
+
out += c < 32 || c === 127 ? `\\u${c.toString(16).padStart(4, "0")}` : ch;
|
|
66
|
+
}
|
|
67
|
+
const clipped = v.length > MAX_SHOWN_LENGTH ? `\u2026 (${v.length} characters)` : "";
|
|
68
|
+
return `"${out}"${clipped}`;
|
|
69
|
+
}
|
|
70
|
+
if (typeof v === "number" || typeof v === "bigint" || typeof v === "boolean" || v === null || v === void 0) {
|
|
71
|
+
return String(v);
|
|
72
|
+
}
|
|
73
|
+
return typeName(v);
|
|
74
|
+
}
|
|
75
|
+
function checkUint(v, bits, who) {
|
|
76
|
+
if (!Number.isInteger(v) || v < 0 || v > (bits === 32 ? 4294967295 : (1 << bits) - 1)) {
|
|
77
|
+
throw err(
|
|
78
|
+
Number.isInteger(v) ? "out-of-range" : "not-an-integer",
|
|
79
|
+
`Writer.${who}`,
|
|
80
|
+
`expected an integer in 0..2^${bits}-1, got ${shown(v)}`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
var Writer = class {
|
|
85
|
+
buf = new Uint8Array(256);
|
|
86
|
+
view = new DataView(this.buf.buffer);
|
|
87
|
+
len = 0;
|
|
88
|
+
ensure(extra) {
|
|
89
|
+
if (this.len + extra <= this.buf.length) return;
|
|
90
|
+
let cap = this.buf.length * 2;
|
|
91
|
+
while (cap < this.len + extra) cap *= 2;
|
|
92
|
+
const next = new Uint8Array(cap);
|
|
93
|
+
next.set(this.buf.subarray(0, this.len));
|
|
94
|
+
this.buf = next;
|
|
95
|
+
this.view = new DataView(next.buffer);
|
|
96
|
+
}
|
|
97
|
+
u8(v) {
|
|
98
|
+
checkUint(v, 8, "u8");
|
|
99
|
+
this.ensure(1);
|
|
100
|
+
this.buf[this.len++] = v;
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
u16(v) {
|
|
104
|
+
checkUint(v, 16, "u16");
|
|
105
|
+
this.ensure(2);
|
|
106
|
+
this.view.setUint16(this.len, v, true);
|
|
107
|
+
this.len += 2;
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
u32(v) {
|
|
111
|
+
checkUint(v, 32, "u32");
|
|
112
|
+
this.ensure(4);
|
|
113
|
+
this.view.setUint32(this.len, v, true);
|
|
114
|
+
this.len += 4;
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
// The 64-bit paths go through DataView rather than eight BigInt shift/mask
|
|
118
|
+
// steps. Every input amount and output value in a transaction crosses one of
|
|
119
|
+
// these, and the loop version measured ~33x slower on the primitive.
|
|
120
|
+
u64(v) {
|
|
121
|
+
if (v < 0n || v > 0xffffffffffffffffn) throw err("out-of-range", "Writer.u64", "value must fit in an unsigned 64-bit integer");
|
|
122
|
+
this.ensure(8);
|
|
123
|
+
this.view.setBigUint64(this.len, v, true);
|
|
124
|
+
this.len += 8;
|
|
125
|
+
return this;
|
|
126
|
+
}
|
|
127
|
+
/** Signed 64-bit little-endian (two's complement). Used for atom amounts. */
|
|
128
|
+
i64(v) {
|
|
129
|
+
if (v < -(1n << 63n) || v >= 1n << 63n) throw err("out-of-range", "Writer.i64", "value must fit in a signed 64-bit integer");
|
|
130
|
+
this.ensure(8);
|
|
131
|
+
this.view.setBigInt64(this.len, v, true);
|
|
132
|
+
this.len += 8;
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
bytes(b) {
|
|
136
|
+
this.ensure(b.length);
|
|
137
|
+
this.buf.set(b, this.len);
|
|
138
|
+
this.len += b.length;
|
|
139
|
+
return this;
|
|
140
|
+
}
|
|
141
|
+
/** Compact-size varint. */
|
|
142
|
+
varInt(v) {
|
|
143
|
+
if (typeof v === "number") {
|
|
144
|
+
if (!Number.isInteger(v)) {
|
|
145
|
+
throw err("not-an-integer", "Writer.varInt", `expected an integer, got ${v}`);
|
|
146
|
+
}
|
|
147
|
+
if (v < 0) throw err("out-of-range", "Writer.varInt", "value must not be negative");
|
|
148
|
+
if (v < 253) return this.u8(v);
|
|
149
|
+
if (v <= 65535) return this.u8(253).u16(v);
|
|
150
|
+
if (v <= 4294967295) return this.u8(254).u32(v);
|
|
151
|
+
return this.u8(255).u64(BigInt(v));
|
|
152
|
+
}
|
|
153
|
+
if (typeof v !== "bigint") {
|
|
154
|
+
throw err("not-an-integer", "Writer.varInt", `expected an integer, got ${typeName(v)}`);
|
|
155
|
+
}
|
|
156
|
+
const n = v;
|
|
157
|
+
if (n < 0n) throw err("out-of-range", "Writer.varInt", "value must not be negative");
|
|
158
|
+
if (n < 0xfdn) return this.u8(Number(n));
|
|
159
|
+
if (n <= 0xffffn) return this.u8(253).u16(Number(n));
|
|
160
|
+
if (n <= 0xffffffffn) return this.u8(254).u32(Number(n));
|
|
161
|
+
return this.u8(255).u64(n);
|
|
162
|
+
}
|
|
163
|
+
/** A varint length prefix followed by the bytes themselves. */
|
|
164
|
+
varBytes(b) {
|
|
165
|
+
return this.varInt(b.length).bytes(b);
|
|
166
|
+
}
|
|
167
|
+
finish() {
|
|
168
|
+
return this.buf.slice(0, this.len);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
var Reader = class {
|
|
172
|
+
constructor(data) {
|
|
173
|
+
this.data = data;
|
|
174
|
+
this.view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
175
|
+
}
|
|
176
|
+
data;
|
|
177
|
+
off = 0;
|
|
178
|
+
view;
|
|
179
|
+
get offset() {
|
|
180
|
+
return this.off;
|
|
181
|
+
}
|
|
182
|
+
get remaining() {
|
|
183
|
+
return this.data.length - this.off;
|
|
184
|
+
}
|
|
185
|
+
need(n) {
|
|
186
|
+
if (this.off + n > this.data.length) throw err("unexpected-end", "Reader", `wanted ${n} more byte(s), ${this.data.length - this.off} remain`);
|
|
187
|
+
}
|
|
188
|
+
u8() {
|
|
189
|
+
this.need(1);
|
|
190
|
+
return this.data[this.off++];
|
|
191
|
+
}
|
|
192
|
+
u16() {
|
|
193
|
+
this.need(2);
|
|
194
|
+
const v = this.data[this.off] | this.data[this.off + 1] << 8;
|
|
195
|
+
this.off += 2;
|
|
196
|
+
return v >>> 0;
|
|
197
|
+
}
|
|
198
|
+
u32() {
|
|
199
|
+
this.need(4);
|
|
200
|
+
const v = (this.data[this.off] | this.data[this.off + 1] << 8 | this.data[this.off + 2] << 16 | this.data[this.off + 3] << 24) >>> 0;
|
|
201
|
+
this.off += 4;
|
|
202
|
+
return v;
|
|
203
|
+
}
|
|
204
|
+
u64() {
|
|
205
|
+
this.need(8);
|
|
206
|
+
const v = this.view.getBigUint64(this.off, true);
|
|
207
|
+
this.off += 8;
|
|
208
|
+
return v;
|
|
209
|
+
}
|
|
210
|
+
/** Signed 64-bit little-endian (two's complement). */
|
|
211
|
+
i64() {
|
|
212
|
+
this.need(8);
|
|
213
|
+
const v = this.view.getBigInt64(this.off, true);
|
|
214
|
+
this.off += 8;
|
|
215
|
+
return v;
|
|
216
|
+
}
|
|
217
|
+
bytes(n) {
|
|
218
|
+
if (!Number.isInteger(n) || n < 0) throw err(Number.isInteger(n) ? "out-of-range" : "not-an-integer", "Reader.bytes", `bad length ${n}`);
|
|
219
|
+
this.need(n);
|
|
220
|
+
const out = copyOf(this.data, this.off, n);
|
|
221
|
+
this.off += n;
|
|
222
|
+
return out;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Compact-size varint. Rejects non-canonical encodings (a value that could
|
|
226
|
+
* have been encoded in fewer bytes), matching dcrd's `ErrNonCanonicalVarInt`.
|
|
227
|
+
* Without this check two distinct byte strings could parse to the same
|
|
228
|
+
* transaction while hashing to different ids.
|
|
229
|
+
*/
|
|
230
|
+
varInt() {
|
|
231
|
+
const first = this.u8();
|
|
232
|
+
if (first < 253) return first;
|
|
233
|
+
if (first === 253) {
|
|
234
|
+
const v = this.u16();
|
|
235
|
+
if (v < 253) throw err("non-canonical-varint", "Reader.varInt", "value could have been encoded in fewer bytes");
|
|
236
|
+
return v;
|
|
237
|
+
}
|
|
238
|
+
if (first === 254) {
|
|
239
|
+
const v = this.u32();
|
|
240
|
+
if (v < 65536) throw err("non-canonical-varint", "Reader.varInt", "value could have been encoded in fewer bytes");
|
|
241
|
+
return v;
|
|
242
|
+
}
|
|
243
|
+
const big = this.u64();
|
|
244
|
+
if (big < 0x100000000n) throw err("non-canonical-varint", "Reader.varInt", "value could have been encoded in fewer bytes");
|
|
245
|
+
if (big > BigInt(Number.MAX_SAFE_INTEGER)) throw err("out-of-range", "Reader.varInt", "value exceeds Number.MAX_SAFE_INTEGER");
|
|
246
|
+
return Number(big);
|
|
247
|
+
}
|
|
248
|
+
varBytes() {
|
|
249
|
+
return this.bytes(this.varInt());
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
// src/blake256.ts
|
|
254
|
+
var IV = Uint32Array.of(
|
|
255
|
+
1779033703,
|
|
256
|
+
3144134277,
|
|
257
|
+
1013904242,
|
|
258
|
+
2773480762,
|
|
259
|
+
1359893119,
|
|
260
|
+
2600822924,
|
|
261
|
+
528734635,
|
|
262
|
+
1541459225
|
|
263
|
+
);
|
|
264
|
+
var C = Uint32Array.of(
|
|
265
|
+
608135816,
|
|
266
|
+
2242054355,
|
|
267
|
+
320440878,
|
|
268
|
+
57701188,
|
|
269
|
+
2752067618,
|
|
270
|
+
698298832,
|
|
271
|
+
137296536,
|
|
272
|
+
3964562569,
|
|
273
|
+
1160258022,
|
|
274
|
+
953160567,
|
|
275
|
+
3193202383,
|
|
276
|
+
887688300,
|
|
277
|
+
3232508343,
|
|
278
|
+
3380367581,
|
|
279
|
+
1065670069,
|
|
280
|
+
3041331479
|
|
281
|
+
);
|
|
282
|
+
var SIGMA = Uint8Array.of(
|
|
283
|
+
0,
|
|
284
|
+
1,
|
|
285
|
+
2,
|
|
286
|
+
3,
|
|
287
|
+
4,
|
|
288
|
+
5,
|
|
289
|
+
6,
|
|
290
|
+
7,
|
|
291
|
+
8,
|
|
292
|
+
9,
|
|
293
|
+
10,
|
|
294
|
+
11,
|
|
295
|
+
12,
|
|
296
|
+
13,
|
|
297
|
+
14,
|
|
298
|
+
15,
|
|
299
|
+
14,
|
|
300
|
+
10,
|
|
301
|
+
4,
|
|
302
|
+
8,
|
|
303
|
+
9,
|
|
304
|
+
15,
|
|
305
|
+
13,
|
|
306
|
+
6,
|
|
307
|
+
1,
|
|
308
|
+
12,
|
|
309
|
+
0,
|
|
310
|
+
2,
|
|
311
|
+
11,
|
|
312
|
+
7,
|
|
313
|
+
5,
|
|
314
|
+
3,
|
|
315
|
+
11,
|
|
316
|
+
8,
|
|
317
|
+
12,
|
|
318
|
+
0,
|
|
319
|
+
5,
|
|
320
|
+
2,
|
|
321
|
+
15,
|
|
322
|
+
13,
|
|
323
|
+
10,
|
|
324
|
+
14,
|
|
325
|
+
3,
|
|
326
|
+
6,
|
|
327
|
+
7,
|
|
328
|
+
1,
|
|
329
|
+
9,
|
|
330
|
+
4,
|
|
331
|
+
7,
|
|
332
|
+
9,
|
|
333
|
+
3,
|
|
334
|
+
1,
|
|
335
|
+
13,
|
|
336
|
+
12,
|
|
337
|
+
11,
|
|
338
|
+
14,
|
|
339
|
+
2,
|
|
340
|
+
6,
|
|
341
|
+
5,
|
|
342
|
+
10,
|
|
343
|
+
4,
|
|
344
|
+
0,
|
|
345
|
+
15,
|
|
346
|
+
8,
|
|
347
|
+
9,
|
|
348
|
+
0,
|
|
349
|
+
5,
|
|
350
|
+
7,
|
|
351
|
+
2,
|
|
352
|
+
4,
|
|
353
|
+
10,
|
|
354
|
+
15,
|
|
355
|
+
14,
|
|
356
|
+
1,
|
|
357
|
+
11,
|
|
358
|
+
12,
|
|
359
|
+
6,
|
|
360
|
+
8,
|
|
361
|
+
3,
|
|
362
|
+
13,
|
|
363
|
+
2,
|
|
364
|
+
12,
|
|
365
|
+
6,
|
|
366
|
+
10,
|
|
367
|
+
0,
|
|
368
|
+
11,
|
|
369
|
+
8,
|
|
370
|
+
3,
|
|
371
|
+
4,
|
|
372
|
+
13,
|
|
373
|
+
7,
|
|
374
|
+
5,
|
|
375
|
+
15,
|
|
376
|
+
14,
|
|
377
|
+
1,
|
|
378
|
+
9,
|
|
379
|
+
12,
|
|
380
|
+
5,
|
|
381
|
+
1,
|
|
382
|
+
15,
|
|
383
|
+
14,
|
|
384
|
+
13,
|
|
385
|
+
4,
|
|
386
|
+
10,
|
|
387
|
+
0,
|
|
388
|
+
7,
|
|
389
|
+
6,
|
|
390
|
+
3,
|
|
391
|
+
9,
|
|
392
|
+
2,
|
|
393
|
+
8,
|
|
394
|
+
11,
|
|
395
|
+
13,
|
|
396
|
+
11,
|
|
397
|
+
7,
|
|
398
|
+
14,
|
|
399
|
+
12,
|
|
400
|
+
1,
|
|
401
|
+
3,
|
|
402
|
+
9,
|
|
403
|
+
5,
|
|
404
|
+
0,
|
|
405
|
+
15,
|
|
406
|
+
4,
|
|
407
|
+
8,
|
|
408
|
+
6,
|
|
409
|
+
2,
|
|
410
|
+
10,
|
|
411
|
+
6,
|
|
412
|
+
15,
|
|
413
|
+
14,
|
|
414
|
+
9,
|
|
415
|
+
11,
|
|
416
|
+
3,
|
|
417
|
+
0,
|
|
418
|
+
8,
|
|
419
|
+
12,
|
|
420
|
+
2,
|
|
421
|
+
13,
|
|
422
|
+
7,
|
|
423
|
+
1,
|
|
424
|
+
4,
|
|
425
|
+
10,
|
|
426
|
+
5,
|
|
427
|
+
10,
|
|
428
|
+
2,
|
|
429
|
+
8,
|
|
430
|
+
4,
|
|
431
|
+
7,
|
|
432
|
+
6,
|
|
433
|
+
1,
|
|
434
|
+
5,
|
|
435
|
+
15,
|
|
436
|
+
11,
|
|
437
|
+
9,
|
|
438
|
+
14,
|
|
439
|
+
3,
|
|
440
|
+
12,
|
|
441
|
+
13,
|
|
442
|
+
0
|
|
443
|
+
);
|
|
444
|
+
var ROUNDS = 14;
|
|
445
|
+
var BLAKE256_DIGEST_LENGTH = 32;
|
|
446
|
+
var BLAKE256_BLOCK_LENGTH = 64;
|
|
447
|
+
var V = new Uint32Array(16);
|
|
448
|
+
var M = new Uint32Array(16);
|
|
449
|
+
function compress(h, block, offset, t0, t1, nullt) {
|
|
450
|
+
for (let i = 0; i < 16; i++) {
|
|
451
|
+
const j = offset + i * 4;
|
|
452
|
+
M[i] = (block[j] << 24 | block[j + 1] << 16 | block[j + 2] << 8 | block[j + 3]) >>> 0;
|
|
453
|
+
}
|
|
454
|
+
V[0] = h[0];
|
|
455
|
+
V[1] = h[1];
|
|
456
|
+
V[2] = h[2];
|
|
457
|
+
V[3] = h[3];
|
|
458
|
+
V[4] = h[4];
|
|
459
|
+
V[5] = h[5];
|
|
460
|
+
V[6] = h[6];
|
|
461
|
+
V[7] = h[7];
|
|
462
|
+
V[8] = C[0];
|
|
463
|
+
V[9] = C[1];
|
|
464
|
+
V[10] = C[2];
|
|
465
|
+
V[11] = C[3];
|
|
466
|
+
V[12] = C[4];
|
|
467
|
+
V[13] = C[5];
|
|
468
|
+
V[14] = C[6];
|
|
469
|
+
V[15] = C[7];
|
|
470
|
+
if (!nullt) {
|
|
471
|
+
V[12] ^= t0;
|
|
472
|
+
V[13] ^= t0;
|
|
473
|
+
V[14] ^= t1;
|
|
474
|
+
V[15] ^= t1;
|
|
475
|
+
}
|
|
476
|
+
let p, s0, s1;
|
|
477
|
+
let va, vb, vc, vd, t;
|
|
478
|
+
for (let r = 0; r < ROUNDS; r++) {
|
|
479
|
+
const s = r % 10 * 16;
|
|
480
|
+
p = s + 0;
|
|
481
|
+
s0 = SIGMA[p];
|
|
482
|
+
s1 = SIGMA[p + 1];
|
|
483
|
+
va = V[0];
|
|
484
|
+
vb = V[4];
|
|
485
|
+
vc = V[8];
|
|
486
|
+
vd = V[12];
|
|
487
|
+
va = va + vb + ((M[s0] ^ C[s1]) >>> 0) >>> 0;
|
|
488
|
+
t = vd ^ va;
|
|
489
|
+
vd = t >>> 16 | t << 16;
|
|
490
|
+
vc = vc + vd >>> 0;
|
|
491
|
+
t = vb ^ vc;
|
|
492
|
+
vb = t >>> 12 | t << 20;
|
|
493
|
+
va = va + vb + ((M[s1] ^ C[s0]) >>> 0) >>> 0;
|
|
494
|
+
t = vd ^ va;
|
|
495
|
+
vd = t >>> 8 | t << 24;
|
|
496
|
+
vc = vc + vd >>> 0;
|
|
497
|
+
t = vb ^ vc;
|
|
498
|
+
vb = t >>> 7 | t << 25;
|
|
499
|
+
V[0] = va;
|
|
500
|
+
V[4] = vb;
|
|
501
|
+
V[8] = vc;
|
|
502
|
+
V[12] = vd;
|
|
503
|
+
p = s + 2;
|
|
504
|
+
s0 = SIGMA[p];
|
|
505
|
+
s1 = SIGMA[p + 1];
|
|
506
|
+
va = V[1];
|
|
507
|
+
vb = V[5];
|
|
508
|
+
vc = V[9];
|
|
509
|
+
vd = V[13];
|
|
510
|
+
va = va + vb + ((M[s0] ^ C[s1]) >>> 0) >>> 0;
|
|
511
|
+
t = vd ^ va;
|
|
512
|
+
vd = t >>> 16 | t << 16;
|
|
513
|
+
vc = vc + vd >>> 0;
|
|
514
|
+
t = vb ^ vc;
|
|
515
|
+
vb = t >>> 12 | t << 20;
|
|
516
|
+
va = va + vb + ((M[s1] ^ C[s0]) >>> 0) >>> 0;
|
|
517
|
+
t = vd ^ va;
|
|
518
|
+
vd = t >>> 8 | t << 24;
|
|
519
|
+
vc = vc + vd >>> 0;
|
|
520
|
+
t = vb ^ vc;
|
|
521
|
+
vb = t >>> 7 | t << 25;
|
|
522
|
+
V[1] = va;
|
|
523
|
+
V[5] = vb;
|
|
524
|
+
V[9] = vc;
|
|
525
|
+
V[13] = vd;
|
|
526
|
+
p = s + 4;
|
|
527
|
+
s0 = SIGMA[p];
|
|
528
|
+
s1 = SIGMA[p + 1];
|
|
529
|
+
va = V[2];
|
|
530
|
+
vb = V[6];
|
|
531
|
+
vc = V[10];
|
|
532
|
+
vd = V[14];
|
|
533
|
+
va = va + vb + ((M[s0] ^ C[s1]) >>> 0) >>> 0;
|
|
534
|
+
t = vd ^ va;
|
|
535
|
+
vd = t >>> 16 | t << 16;
|
|
536
|
+
vc = vc + vd >>> 0;
|
|
537
|
+
t = vb ^ vc;
|
|
538
|
+
vb = t >>> 12 | t << 20;
|
|
539
|
+
va = va + vb + ((M[s1] ^ C[s0]) >>> 0) >>> 0;
|
|
540
|
+
t = vd ^ va;
|
|
541
|
+
vd = t >>> 8 | t << 24;
|
|
542
|
+
vc = vc + vd >>> 0;
|
|
543
|
+
t = vb ^ vc;
|
|
544
|
+
vb = t >>> 7 | t << 25;
|
|
545
|
+
V[2] = va;
|
|
546
|
+
V[6] = vb;
|
|
547
|
+
V[10] = vc;
|
|
548
|
+
V[14] = vd;
|
|
549
|
+
p = s + 6;
|
|
550
|
+
s0 = SIGMA[p];
|
|
551
|
+
s1 = SIGMA[p + 1];
|
|
552
|
+
va = V[3];
|
|
553
|
+
vb = V[7];
|
|
554
|
+
vc = V[11];
|
|
555
|
+
vd = V[15];
|
|
556
|
+
va = va + vb + ((M[s0] ^ C[s1]) >>> 0) >>> 0;
|
|
557
|
+
t = vd ^ va;
|
|
558
|
+
vd = t >>> 16 | t << 16;
|
|
559
|
+
vc = vc + vd >>> 0;
|
|
560
|
+
t = vb ^ vc;
|
|
561
|
+
vb = t >>> 12 | t << 20;
|
|
562
|
+
va = va + vb + ((M[s1] ^ C[s0]) >>> 0) >>> 0;
|
|
563
|
+
t = vd ^ va;
|
|
564
|
+
vd = t >>> 8 | t << 24;
|
|
565
|
+
vc = vc + vd >>> 0;
|
|
566
|
+
t = vb ^ vc;
|
|
567
|
+
vb = t >>> 7 | t << 25;
|
|
568
|
+
V[3] = va;
|
|
569
|
+
V[7] = vb;
|
|
570
|
+
V[11] = vc;
|
|
571
|
+
V[15] = vd;
|
|
572
|
+
p = s + 8;
|
|
573
|
+
s0 = SIGMA[p];
|
|
574
|
+
s1 = SIGMA[p + 1];
|
|
575
|
+
va = V[0];
|
|
576
|
+
vb = V[5];
|
|
577
|
+
vc = V[10];
|
|
578
|
+
vd = V[15];
|
|
579
|
+
va = va + vb + ((M[s0] ^ C[s1]) >>> 0) >>> 0;
|
|
580
|
+
t = vd ^ va;
|
|
581
|
+
vd = t >>> 16 | t << 16;
|
|
582
|
+
vc = vc + vd >>> 0;
|
|
583
|
+
t = vb ^ vc;
|
|
584
|
+
vb = t >>> 12 | t << 20;
|
|
585
|
+
va = va + vb + ((M[s1] ^ C[s0]) >>> 0) >>> 0;
|
|
586
|
+
t = vd ^ va;
|
|
587
|
+
vd = t >>> 8 | t << 24;
|
|
588
|
+
vc = vc + vd >>> 0;
|
|
589
|
+
t = vb ^ vc;
|
|
590
|
+
vb = t >>> 7 | t << 25;
|
|
591
|
+
V[0] = va;
|
|
592
|
+
V[5] = vb;
|
|
593
|
+
V[10] = vc;
|
|
594
|
+
V[15] = vd;
|
|
595
|
+
p = s + 10;
|
|
596
|
+
s0 = SIGMA[p];
|
|
597
|
+
s1 = SIGMA[p + 1];
|
|
598
|
+
va = V[1];
|
|
599
|
+
vb = V[6];
|
|
600
|
+
vc = V[11];
|
|
601
|
+
vd = V[12];
|
|
602
|
+
va = va + vb + ((M[s0] ^ C[s1]) >>> 0) >>> 0;
|
|
603
|
+
t = vd ^ va;
|
|
604
|
+
vd = t >>> 16 | t << 16;
|
|
605
|
+
vc = vc + vd >>> 0;
|
|
606
|
+
t = vb ^ vc;
|
|
607
|
+
vb = t >>> 12 | t << 20;
|
|
608
|
+
va = va + vb + ((M[s1] ^ C[s0]) >>> 0) >>> 0;
|
|
609
|
+
t = vd ^ va;
|
|
610
|
+
vd = t >>> 8 | t << 24;
|
|
611
|
+
vc = vc + vd >>> 0;
|
|
612
|
+
t = vb ^ vc;
|
|
613
|
+
vb = t >>> 7 | t << 25;
|
|
614
|
+
V[1] = va;
|
|
615
|
+
V[6] = vb;
|
|
616
|
+
V[11] = vc;
|
|
617
|
+
V[12] = vd;
|
|
618
|
+
p = s + 12;
|
|
619
|
+
s0 = SIGMA[p];
|
|
620
|
+
s1 = SIGMA[p + 1];
|
|
621
|
+
va = V[2];
|
|
622
|
+
vb = V[7];
|
|
623
|
+
vc = V[8];
|
|
624
|
+
vd = V[13];
|
|
625
|
+
va = va + vb + ((M[s0] ^ C[s1]) >>> 0) >>> 0;
|
|
626
|
+
t = vd ^ va;
|
|
627
|
+
vd = t >>> 16 | t << 16;
|
|
628
|
+
vc = vc + vd >>> 0;
|
|
629
|
+
t = vb ^ vc;
|
|
630
|
+
vb = t >>> 12 | t << 20;
|
|
631
|
+
va = va + vb + ((M[s1] ^ C[s0]) >>> 0) >>> 0;
|
|
632
|
+
t = vd ^ va;
|
|
633
|
+
vd = t >>> 8 | t << 24;
|
|
634
|
+
vc = vc + vd >>> 0;
|
|
635
|
+
t = vb ^ vc;
|
|
636
|
+
vb = t >>> 7 | t << 25;
|
|
637
|
+
V[2] = va;
|
|
638
|
+
V[7] = vb;
|
|
639
|
+
V[8] = vc;
|
|
640
|
+
V[13] = vd;
|
|
641
|
+
p = s + 14;
|
|
642
|
+
s0 = SIGMA[p];
|
|
643
|
+
s1 = SIGMA[p + 1];
|
|
644
|
+
va = V[3];
|
|
645
|
+
vb = V[4];
|
|
646
|
+
vc = V[9];
|
|
647
|
+
vd = V[14];
|
|
648
|
+
va = va + vb + ((M[s0] ^ C[s1]) >>> 0) >>> 0;
|
|
649
|
+
t = vd ^ va;
|
|
650
|
+
vd = t >>> 16 | t << 16;
|
|
651
|
+
vc = vc + vd >>> 0;
|
|
652
|
+
t = vb ^ vc;
|
|
653
|
+
vb = t >>> 12 | t << 20;
|
|
654
|
+
va = va + vb + ((M[s1] ^ C[s0]) >>> 0) >>> 0;
|
|
655
|
+
t = vd ^ va;
|
|
656
|
+
vd = t >>> 8 | t << 24;
|
|
657
|
+
vc = vc + vd >>> 0;
|
|
658
|
+
t = vb ^ vc;
|
|
659
|
+
vb = t >>> 7 | t << 25;
|
|
660
|
+
V[3] = va;
|
|
661
|
+
V[4] = vb;
|
|
662
|
+
V[9] = vc;
|
|
663
|
+
V[14] = vd;
|
|
664
|
+
}
|
|
665
|
+
for (let i = 0; i < 8; i++) {
|
|
666
|
+
h[i] = (h[i] ^ V[i] ^ V[i + 8]) >>> 0;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
var Blake256 = class {
|
|
670
|
+
h = IV.slice();
|
|
671
|
+
buf = new Uint8Array(BLAKE256_BLOCK_LENGTH);
|
|
672
|
+
buflen = 0;
|
|
673
|
+
/** Total message bytes fed in (used for the final length encoding). */
|
|
674
|
+
total = 0;
|
|
675
|
+
/** Message bytes already absorbed by the compression function. */
|
|
676
|
+
compressed = 0;
|
|
677
|
+
finished = false;
|
|
678
|
+
update(data) {
|
|
679
|
+
if (this.finished) throw err("invalid-argument", "Blake256", "update after digest");
|
|
680
|
+
if (!isBytes(data)) {
|
|
681
|
+
throw err("invalid-argument", "Blake256", `data must be a Uint8Array, got ${typeName(data)}`);
|
|
682
|
+
}
|
|
683
|
+
let i = 0;
|
|
684
|
+
const n = data.length;
|
|
685
|
+
this.total += n;
|
|
686
|
+
if (this.buflen > 0) {
|
|
687
|
+
const need = BLAKE256_BLOCK_LENGTH - this.buflen;
|
|
688
|
+
const take = Math.min(need, n);
|
|
689
|
+
this.buf.set(data.subarray(0, take), this.buflen);
|
|
690
|
+
this.buflen += take;
|
|
691
|
+
i = take;
|
|
692
|
+
if (this.buflen === BLAKE256_BLOCK_LENGTH) {
|
|
693
|
+
this.compressed += BLAKE256_BLOCK_LENGTH;
|
|
694
|
+
compress(this.h, this.buf, 0, lo32(this.compressed), hi32(this.compressed), false);
|
|
695
|
+
this.buflen = 0;
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
while (n - i >= BLAKE256_BLOCK_LENGTH) {
|
|
699
|
+
this.compressed += BLAKE256_BLOCK_LENGTH;
|
|
700
|
+
compress(this.h, data, i, lo32(this.compressed), hi32(this.compressed), false);
|
|
701
|
+
i += BLAKE256_BLOCK_LENGTH;
|
|
702
|
+
}
|
|
703
|
+
if (i < n) {
|
|
704
|
+
this.buf.set(data.subarray(i), this.buflen);
|
|
705
|
+
this.buflen += n - i;
|
|
706
|
+
}
|
|
707
|
+
return this;
|
|
708
|
+
}
|
|
709
|
+
digest() {
|
|
710
|
+
if (this.finished) throw err("invalid-argument", "Blake256", "digest called twice");
|
|
711
|
+
this.finished = true;
|
|
712
|
+
const rem = this.buflen;
|
|
713
|
+
const block = new Uint8Array(BLAKE256_BLOCK_LENGTH);
|
|
714
|
+
block.set(this.buf.subarray(0, rem));
|
|
715
|
+
if (rem <= 55) {
|
|
716
|
+
block[rem] = 128;
|
|
717
|
+
block[55] |= 1;
|
|
718
|
+
writeLen(block, this.total);
|
|
719
|
+
if (rem === 0) compress(this.h, block, 0, 0, 0, true);
|
|
720
|
+
else compress(this.h, block, 0, lo32(this.total), hi32(this.total), false);
|
|
721
|
+
} else {
|
|
722
|
+
block[rem] = 128;
|
|
723
|
+
compress(this.h, block, 0, lo32(this.total), hi32(this.total), false);
|
|
724
|
+
const tail = new Uint8Array(BLAKE256_BLOCK_LENGTH);
|
|
725
|
+
tail[55] = 1;
|
|
726
|
+
writeLen(tail, this.total);
|
|
727
|
+
compress(this.h, tail, 0, 0, 0, true);
|
|
728
|
+
}
|
|
729
|
+
const out = new Uint8Array(BLAKE256_DIGEST_LENGTH);
|
|
730
|
+
for (let i = 0; i < 8; i++) {
|
|
731
|
+
const v = this.h[i];
|
|
732
|
+
out[i * 4] = v >>> 24 & 255;
|
|
733
|
+
out[i * 4 + 1] = v >>> 16 & 255;
|
|
734
|
+
out[i * 4 + 2] = v >>> 8 & 255;
|
|
735
|
+
out[i * 4 + 3] = v & 255;
|
|
736
|
+
}
|
|
737
|
+
return out;
|
|
738
|
+
}
|
|
739
|
+
};
|
|
740
|
+
function lo32(bytes) {
|
|
741
|
+
return bytes * 8 >>> 0;
|
|
742
|
+
}
|
|
743
|
+
function hi32(bytes) {
|
|
744
|
+
return Math.floor(bytes * 8 / 4294967296) >>> 0;
|
|
745
|
+
}
|
|
746
|
+
function writeLen(block, totalBytes) {
|
|
747
|
+
const h = hi32(totalBytes);
|
|
748
|
+
const l = lo32(totalBytes);
|
|
749
|
+
block[56] = h >>> 24 & 255;
|
|
750
|
+
block[57] = h >>> 16 & 255;
|
|
751
|
+
block[58] = h >>> 8 & 255;
|
|
752
|
+
block[59] = h & 255;
|
|
753
|
+
block[60] = l >>> 24 & 255;
|
|
754
|
+
block[61] = l >>> 16 & 255;
|
|
755
|
+
block[62] = l >>> 8 & 255;
|
|
756
|
+
block[63] = l & 255;
|
|
757
|
+
}
|
|
758
|
+
function blake256(data) {
|
|
759
|
+
return new Blake256().update(data).digest();
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// src/hash.ts
|
|
763
|
+
function hash256(data) {
|
|
764
|
+
return blake256(blake256(data));
|
|
765
|
+
}
|
|
766
|
+
function hash160(data) {
|
|
767
|
+
return ripemd160.ripemd160(blake256(data));
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// src/base58.ts
|
|
771
|
+
var ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
772
|
+
var BASE = 58n;
|
|
773
|
+
var INDEX = new Uint8Array(128).fill(255);
|
|
774
|
+
for (let i = 0; i < ALPHABET.length; i++) {
|
|
775
|
+
INDEX[ALPHABET.charCodeAt(i)] = i;
|
|
776
|
+
}
|
|
777
|
+
function base58Encode(bytes) {
|
|
778
|
+
let zeros = 0;
|
|
779
|
+
while (zeros < bytes.length && bytes[zeros] === 0) zeros++;
|
|
780
|
+
let num = 0n;
|
|
781
|
+
for (const b of bytes) num = num * 256n + BigInt(b);
|
|
782
|
+
let out = "";
|
|
783
|
+
while (num > 0n) {
|
|
784
|
+
const rem = num % BASE;
|
|
785
|
+
num = num / BASE;
|
|
786
|
+
out = ALPHABET[Number(rem)] + out;
|
|
787
|
+
}
|
|
788
|
+
return "1".repeat(zeros) + out;
|
|
789
|
+
}
|
|
790
|
+
function maxBase58Length(decodedLen) {
|
|
791
|
+
return Math.floor(decodedLen * 137 / 100) + 1;
|
|
792
|
+
}
|
|
793
|
+
function base58Decode(str) {
|
|
794
|
+
let zeros = 0;
|
|
795
|
+
while (zeros < str.length && str[zeros] === "1") zeros++;
|
|
796
|
+
let num = 0n;
|
|
797
|
+
for (let i = 0; i < str.length; i++) {
|
|
798
|
+
const code = str.charCodeAt(i);
|
|
799
|
+
const val = code < 128 ? INDEX[code] : 255;
|
|
800
|
+
if (val === 255) throw err("invalid-base58", "base58Decode", `invalid character ${shown(str[i])} at index ${i}`);
|
|
801
|
+
num = num * BASE + BigInt(val);
|
|
802
|
+
}
|
|
803
|
+
const tail = [];
|
|
804
|
+
while (num > 0n) {
|
|
805
|
+
tail.push(Number(num % 256n));
|
|
806
|
+
num = num / 256n;
|
|
807
|
+
}
|
|
808
|
+
tail.reverse();
|
|
809
|
+
const out = new Uint8Array(zeros + tail.length);
|
|
810
|
+
out.set(tail, zeros);
|
|
811
|
+
return out;
|
|
812
|
+
}
|
|
813
|
+
function checkEncode(data) {
|
|
814
|
+
const checksum = hash256(data).subarray(0, 4);
|
|
815
|
+
const full = new Uint8Array(data.length + 4);
|
|
816
|
+
full.set(data);
|
|
817
|
+
full.set(checksum, data.length);
|
|
818
|
+
return base58Encode(full);
|
|
819
|
+
}
|
|
820
|
+
function checkDecode(str) {
|
|
821
|
+
const full = base58Decode(str);
|
|
822
|
+
if (full.length < 4) throw err("bad-length", "base58check", "input is shorter than the 4-byte checksum");
|
|
823
|
+
const data = full.subarray(0, full.length - 4);
|
|
824
|
+
const checksum = full.subarray(full.length - 4);
|
|
825
|
+
const expected = hash256(data).subarray(0, 4);
|
|
826
|
+
for (let i = 0; i < 4; i++) {
|
|
827
|
+
if (checksum[i] !== expected[i]) throw err("bad-checksum", "base58check", "checksum does not match");
|
|
828
|
+
}
|
|
829
|
+
return data.slice();
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
// src/networks.ts
|
|
833
|
+
var mainnet = {
|
|
834
|
+
name: "mainnet",
|
|
835
|
+
net: 3652452601,
|
|
836
|
+
addressPrefix: "D",
|
|
837
|
+
pubKeyAddrId: [19, 134],
|
|
838
|
+
pubKeyHashAddrId: [7, 63],
|
|
839
|
+
pubKeyHashEdwardsAddrId: [7, 31],
|
|
840
|
+
pubKeyHashSchnorrAddrId: [7, 1],
|
|
841
|
+
scriptHashAddrId: [7, 26],
|
|
842
|
+
privateKeyId: [34, 222],
|
|
843
|
+
hdPrivateKeyId: [2, 253, 164, 232],
|
|
844
|
+
hdPublicKeyId: [2, 253, 169, 38],
|
|
845
|
+
slip44: 42
|
|
846
|
+
};
|
|
847
|
+
var testnet3 = {
|
|
848
|
+
name: "testnet3",
|
|
849
|
+
net: 2979310197,
|
|
850
|
+
addressPrefix: "T",
|
|
851
|
+
pubKeyAddrId: [40, 247],
|
|
852
|
+
pubKeyHashAddrId: [15, 33],
|
|
853
|
+
pubKeyHashEdwardsAddrId: [15, 1],
|
|
854
|
+
pubKeyHashSchnorrAddrId: [14, 227],
|
|
855
|
+
scriptHashAddrId: [14, 252],
|
|
856
|
+
privateKeyId: [35, 14],
|
|
857
|
+
hdPrivateKeyId: [4, 53, 131, 151],
|
|
858
|
+
hdPublicKeyId: [4, 53, 135, 209],
|
|
859
|
+
slip44: 1
|
|
860
|
+
};
|
|
861
|
+
var simnet = {
|
|
862
|
+
name: "simnet",
|
|
863
|
+
net: 303307798,
|
|
864
|
+
addressPrefix: "S",
|
|
865
|
+
pubKeyAddrId: [39, 111],
|
|
866
|
+
pubKeyHashAddrId: [14, 145],
|
|
867
|
+
pubKeyHashEdwardsAddrId: [14, 113],
|
|
868
|
+
pubKeyHashSchnorrAddrId: [14, 83],
|
|
869
|
+
scriptHashAddrId: [14, 108],
|
|
870
|
+
privateKeyId: [35, 7],
|
|
871
|
+
hdPrivateKeyId: [4, 32, 185, 3],
|
|
872
|
+
hdPublicKeyId: [4, 32, 189, 61],
|
|
873
|
+
slip44: 1
|
|
874
|
+
};
|
|
875
|
+
var regnet = {
|
|
876
|
+
name: "regnet",
|
|
877
|
+
net: 3669295354,
|
|
878
|
+
addressPrefix: "R",
|
|
879
|
+
pubKeyAddrId: [37, 229],
|
|
880
|
+
pubKeyHashAddrId: [14, 0],
|
|
881
|
+
pubKeyHashEdwardsAddrId: [13, 224],
|
|
882
|
+
pubKeyHashSchnorrAddrId: [13, 194],
|
|
883
|
+
scriptHashAddrId: [13, 219],
|
|
884
|
+
privateKeyId: [34, 254],
|
|
885
|
+
hdPrivateKeyId: [234, 180, 4, 72],
|
|
886
|
+
hdPublicKeyId: [234, 180, 249, 135],
|
|
887
|
+
slip44: 1
|
|
888
|
+
};
|
|
889
|
+
var networks = { mainnet, testnet3, simnet, regnet };
|
|
890
|
+
var CURVE_ORDER = secp256k1.secp256k1.CURVE.n;
|
|
891
|
+
var ED25519_CURVE_ORDER = 2n ** 252n + 27742317777372353535851937790883648493n;
|
|
892
|
+
function isValidPrivateKey(key) {
|
|
893
|
+
if (!isBytes(key) || key.length !== 32) return false;
|
|
894
|
+
const n = bytesToBigInt(key);
|
|
895
|
+
return n > 0n && n < CURVE_ORDER;
|
|
896
|
+
}
|
|
897
|
+
function assertPrivateKey(key, who) {
|
|
898
|
+
if (!isBytes(key)) {
|
|
899
|
+
throw err("invalid-argument", who, `private key must be a Uint8Array, got ${typeName(key)}`);
|
|
900
|
+
}
|
|
901
|
+
if (key.length !== 32) {
|
|
902
|
+
throw err("bad-length", who, `private key must be 32 bytes, got ${key.length}`);
|
|
903
|
+
}
|
|
904
|
+
if (!isValidPrivateKey(key)) {
|
|
905
|
+
throw err("invalid-private-key", who, "private key is zero, or at or above the group order");
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
function publicKeyFromPrivate(privateKey, compressed = true) {
|
|
909
|
+
assertPrivateKey(privateKey, "publicKeyFromPrivate");
|
|
910
|
+
return secp256k1.secp256k1.getPublicKey(privateKey, compressed);
|
|
911
|
+
}
|
|
912
|
+
function isValidPublicKey(key) {
|
|
913
|
+
try {
|
|
914
|
+
secp256k1.secp256k1.ProjectivePoint.fromHex(key);
|
|
915
|
+
return true;
|
|
916
|
+
} catch {
|
|
917
|
+
return false;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
function isValidEd25519PublicKey(key) {
|
|
921
|
+
if (!isBytes(key) || key.length !== 32) return false;
|
|
922
|
+
try {
|
|
923
|
+
const point = ed25519.ed25519.ExtendedPoint.fromHex(key, true);
|
|
924
|
+
return !(point.toAffine().x === 0n && (key[31] & 128) !== 0);
|
|
925
|
+
} catch {
|
|
926
|
+
return false;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
function assertCompressedPubKey(key, who) {
|
|
930
|
+
if (!isBytes(key)) {
|
|
931
|
+
throw err("invalid-argument", who, `public key must be a Uint8Array, got ${typeName(key)}`);
|
|
932
|
+
}
|
|
933
|
+
if (key.length !== 33) {
|
|
934
|
+
throw err("invalid-public-key", who, `public key must be 33 compressed bytes, got ${key.length}`);
|
|
935
|
+
}
|
|
936
|
+
if (key[0] !== 2 && key[0] !== 3) {
|
|
937
|
+
throw err(
|
|
938
|
+
"invalid-public-key",
|
|
939
|
+
who,
|
|
940
|
+
`public key must start with 0x02 or 0x03, got 0x${key[0].toString(16).padStart(2, "0")}`
|
|
941
|
+
);
|
|
942
|
+
}
|
|
943
|
+
if (!isValidPublicKey(key)) {
|
|
944
|
+
throw err("invalid-public-key", who, "public key is not a point on the secp256k1 curve");
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
function assertPubKey(key, who) {
|
|
948
|
+
if (!isBytes(key)) {
|
|
949
|
+
throw err("invalid-argument", who, `public key must be a Uint8Array, got ${typeName(key)}`);
|
|
950
|
+
}
|
|
951
|
+
if (key.length !== 33 && key.length !== 65) {
|
|
952
|
+
throw err(
|
|
953
|
+
"invalid-public-key",
|
|
954
|
+
who,
|
|
955
|
+
`public key must be 33 (compressed) or 65 (uncompressed) bytes, got ${key.length}`
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
const prefix = key[0];
|
|
959
|
+
const ok = key.length === 33 ? prefix === 2 || prefix === 3 : prefix === 4;
|
|
960
|
+
if (!ok) {
|
|
961
|
+
throw err(
|
|
962
|
+
"invalid-public-key",
|
|
963
|
+
who,
|
|
964
|
+
`public key has prefix 0x${prefix.toString(16).padStart(2, "0")}, which is not valid for a ${key.length}-byte key`
|
|
965
|
+
);
|
|
966
|
+
}
|
|
967
|
+
if (!isValidPublicKey(key)) {
|
|
968
|
+
throw err("invalid-public-key", who, "public key is not a point on the secp256k1 curve");
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
function scalarToBytes(x) {
|
|
972
|
+
const out = new Uint8Array(32);
|
|
973
|
+
let v = x;
|
|
974
|
+
for (let i = 31; i >= 0; i--) {
|
|
975
|
+
out[i] = Number(v & 0xffn);
|
|
976
|
+
v >>= 8n;
|
|
977
|
+
}
|
|
978
|
+
return out;
|
|
979
|
+
}
|
|
980
|
+
function bytesToBigInt(b) {
|
|
981
|
+
let v = 0n;
|
|
982
|
+
for (const x of b) v = v << 8n | BigInt(x);
|
|
983
|
+
return v;
|
|
984
|
+
}
|
|
985
|
+
function privateKeyTweakAdd(kPar, il) {
|
|
986
|
+
const ilInt = bytesToBigInt(il);
|
|
987
|
+
if (ilInt === 0n || ilInt >= CURVE_ORDER) return null;
|
|
988
|
+
const child = (ilInt + bytesToBigInt(kPar)) % CURVE_ORDER;
|
|
989
|
+
if (child === 0n) return null;
|
|
990
|
+
return scalarToBytes(child);
|
|
991
|
+
}
|
|
992
|
+
function parsePublicKeyPoint(key) {
|
|
993
|
+
try {
|
|
994
|
+
return secp256k1.secp256k1.ProjectivePoint.fromHex(key);
|
|
995
|
+
} catch {
|
|
996
|
+
return null;
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
function publicKeyTweakAddPoint(parent, il) {
|
|
1000
|
+
const ilInt = bytesToBigInt(il);
|
|
1001
|
+
if (ilInt >= CURVE_ORDER || ilInt === 0n) return null;
|
|
1002
|
+
const P = secp256k1.secp256k1.ProjectivePoint;
|
|
1003
|
+
try {
|
|
1004
|
+
const child = P.BASE.multiply(ilInt).add(parent);
|
|
1005
|
+
if (child.equals(P.ZERO)) return null;
|
|
1006
|
+
return child.toRawBytes(true);
|
|
1007
|
+
} catch {
|
|
1008
|
+
return null;
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
// src/script.ts
|
|
1013
|
+
var OP = {
|
|
1014
|
+
OP_0: 0,
|
|
1015
|
+
DATA_20: 20,
|
|
1016
|
+
DATA_32: 32,
|
|
1017
|
+
DATA_33: 33,
|
|
1018
|
+
PUSHDATA1: 76,
|
|
1019
|
+
PUSHDATA2: 77,
|
|
1020
|
+
PUSHDATA4: 78,
|
|
1021
|
+
OP_1NEGATE: 79,
|
|
1022
|
+
OP_1: 81,
|
|
1023
|
+
OP_2: 82,
|
|
1024
|
+
OP_16: 96,
|
|
1025
|
+
DUP: 118,
|
|
1026
|
+
EQUAL: 135,
|
|
1027
|
+
EQUALVERIFY: 136,
|
|
1028
|
+
HASH160: 169,
|
|
1029
|
+
CHECKSIG: 172,
|
|
1030
|
+
CHECKSIGALT: 190
|
|
1031
|
+
};
|
|
1032
|
+
var MAX_SCRIPT_ELEMENT_SIZE = 2048;
|
|
1033
|
+
function pushData(data) {
|
|
1034
|
+
if (!isBytes(data)) {
|
|
1035
|
+
throw err("invalid-argument", "pushData", `data must be a Uint8Array, got ${typeName(data)}`);
|
|
1036
|
+
}
|
|
1037
|
+
const n = data.length;
|
|
1038
|
+
if (n > MAX_SCRIPT_ELEMENT_SIZE) {
|
|
1039
|
+
throw err(
|
|
1040
|
+
"element-too-large",
|
|
1041
|
+
"pushData",
|
|
1042
|
+
`${n} bytes exceeds MaxScriptElementSize (${MAX_SCRIPT_ELEMENT_SIZE})`
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
if (n === 1) {
|
|
1046
|
+
const b = data[0];
|
|
1047
|
+
if (b === 0) return Uint8Array.of(OP.OP_0);
|
|
1048
|
+
if (b >= 1 && b <= 16) return Uint8Array.of(OP.OP_1 + b - 1);
|
|
1049
|
+
if (b === 129) return Uint8Array.of(OP.OP_1NEGATE);
|
|
1050
|
+
}
|
|
1051
|
+
if (n < OP.PUSHDATA1) {
|
|
1052
|
+
const out2 = new Uint8Array(1 + n);
|
|
1053
|
+
out2[0] = n;
|
|
1054
|
+
out2.set(data, 1);
|
|
1055
|
+
return out2;
|
|
1056
|
+
}
|
|
1057
|
+
if (n <= 255) {
|
|
1058
|
+
const out2 = new Uint8Array(2 + n);
|
|
1059
|
+
out2[0] = OP.PUSHDATA1;
|
|
1060
|
+
out2[1] = n;
|
|
1061
|
+
out2.set(data, 2);
|
|
1062
|
+
return out2;
|
|
1063
|
+
}
|
|
1064
|
+
const out = new Uint8Array(3 + n);
|
|
1065
|
+
out[0] = OP.PUSHDATA2;
|
|
1066
|
+
out[1] = n & 255;
|
|
1067
|
+
out[2] = n >>> 8 & 255;
|
|
1068
|
+
out.set(data, 3);
|
|
1069
|
+
return out;
|
|
1070
|
+
}
|
|
1071
|
+
function scriptParses(script) {
|
|
1072
|
+
if (!isBytes(script)) return false;
|
|
1073
|
+
let i = 0;
|
|
1074
|
+
while (i < script.length) {
|
|
1075
|
+
const op = script[i];
|
|
1076
|
+
if (op >= 1 && op <= 75) {
|
|
1077
|
+
if (script.length - i < op + 1) return false;
|
|
1078
|
+
i += op + 1;
|
|
1079
|
+
} else if (op === OP.PUSHDATA1 || op === OP.PUSHDATA2 || op === OP.PUSHDATA4) {
|
|
1080
|
+
const lenSize = op === OP.PUSHDATA1 ? 1 : op === OP.PUSHDATA2 ? 2 : 4;
|
|
1081
|
+
if (script.length - (i + 1) < lenSize) return false;
|
|
1082
|
+
let dataLen = 0;
|
|
1083
|
+
for (let b = 0; b < lenSize; b++) dataLen |= script[i + 1 + b] << 8 * b;
|
|
1084
|
+
if (dataLen < 0 || dataLen > script.length - (i + 1 + lenSize)) return false;
|
|
1085
|
+
i += 1 + lenSize + dataLen;
|
|
1086
|
+
} else {
|
|
1087
|
+
i += 1;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
return true;
|
|
1091
|
+
}
|
|
1092
|
+
function assertHash160(hash1602, who) {
|
|
1093
|
+
if (!isBytes(hash1602)) {
|
|
1094
|
+
throw err("invalid-argument", who, `hash must be a Uint8Array, got ${typeName(hash1602)}`);
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
function payToPubKeyHashScript(hash1602) {
|
|
1098
|
+
assertHash160(hash1602, "payToPubKeyHash");
|
|
1099
|
+
if (hash1602.length !== 20) throw err("bad-length", "payToPubKeyHash", `hash must be 20 bytes, got ${hash1602.length}`);
|
|
1100
|
+
const out = new Uint8Array(25);
|
|
1101
|
+
out[0] = OP.DUP;
|
|
1102
|
+
out[1] = OP.HASH160;
|
|
1103
|
+
out[2] = OP.DATA_20;
|
|
1104
|
+
out.set(hash1602, 3);
|
|
1105
|
+
out[23] = OP.EQUALVERIFY;
|
|
1106
|
+
out[24] = OP.CHECKSIG;
|
|
1107
|
+
return out;
|
|
1108
|
+
}
|
|
1109
|
+
function payToPubKeyHashAltScript(hash1602, sigType) {
|
|
1110
|
+
assertHash160(hash1602, "payToPubKeyHashAlt");
|
|
1111
|
+
if (hash1602.length !== 20) throw err("bad-length", "payToPubKeyHashAlt", `hash must be 20 bytes, got ${hash1602.length}`);
|
|
1112
|
+
if (sigType !== 1 && sigType !== 2) throw err("unsupported-signature-type", "payToPubKeyHashAlt", `sigType must be 1 or 2, got ${shown(sigType)}`);
|
|
1113
|
+
const out = new Uint8Array(26);
|
|
1114
|
+
out[0] = OP.DUP;
|
|
1115
|
+
out[1] = OP.HASH160;
|
|
1116
|
+
out[2] = OP.DATA_20;
|
|
1117
|
+
out.set(hash1602, 3);
|
|
1118
|
+
out[23] = OP.EQUALVERIFY;
|
|
1119
|
+
out[24] = sigType === 1 ? OP.OP_1 : OP.OP_2;
|
|
1120
|
+
out[25] = OP.CHECKSIGALT;
|
|
1121
|
+
return out;
|
|
1122
|
+
}
|
|
1123
|
+
function payToScriptHashScript(hash1602) {
|
|
1124
|
+
assertHash160(hash1602, "payToScriptHash");
|
|
1125
|
+
if (hash1602.length !== 20) throw err("bad-length", "payToScriptHash", `hash must be 20 bytes, got ${hash1602.length}`);
|
|
1126
|
+
const out = new Uint8Array(23);
|
|
1127
|
+
out[0] = OP.HASH160;
|
|
1128
|
+
out[1] = OP.DATA_20;
|
|
1129
|
+
out.set(hash1602, 2);
|
|
1130
|
+
out[22] = OP.EQUAL;
|
|
1131
|
+
return out;
|
|
1132
|
+
}
|
|
1133
|
+
function payToPubKeyScript(compressedPubKey) {
|
|
1134
|
+
assertCompressedPubKey(compressedPubKey, "payToPubKey");
|
|
1135
|
+
const out = new Uint8Array(35);
|
|
1136
|
+
out[0] = OP.DATA_33;
|
|
1137
|
+
out.set(compressedPubKey, 1);
|
|
1138
|
+
out[34] = OP.CHECKSIG;
|
|
1139
|
+
return out;
|
|
1140
|
+
}
|
|
1141
|
+
function payToPubKeyAltScript(pubKey, sigType) {
|
|
1142
|
+
if (sigType === 1) {
|
|
1143
|
+
if (pubKey.length !== 32) {
|
|
1144
|
+
throw err(
|
|
1145
|
+
"invalid-public-key",
|
|
1146
|
+
"payToPubKeyAlt",
|
|
1147
|
+
`an Ed25519 public key must be 32 bytes, got ${pubKey.length}`
|
|
1148
|
+
);
|
|
1149
|
+
}
|
|
1150
|
+
if (!isValidEd25519PublicKey(pubKey)) {
|
|
1151
|
+
throw err("invalid-public-key", "payToPubKeyAlt", "public key is not a valid Ed25519 curve point");
|
|
1152
|
+
}
|
|
1153
|
+
const out2 = new Uint8Array(35);
|
|
1154
|
+
out2[0] = OP.DATA_32;
|
|
1155
|
+
out2.set(pubKey, 1);
|
|
1156
|
+
out2[33] = OP.OP_1;
|
|
1157
|
+
out2[34] = OP.CHECKSIGALT;
|
|
1158
|
+
return out2;
|
|
1159
|
+
}
|
|
1160
|
+
if (sigType !== 2) throw err("unsupported-signature-type", "payToPubKeyAlt", `sigType must be 1 or 2, got ${shown(sigType)}`);
|
|
1161
|
+
assertCompressedPubKey(pubKey, "payToPubKeyAlt");
|
|
1162
|
+
const out = new Uint8Array(36);
|
|
1163
|
+
out[0] = OP.DATA_33;
|
|
1164
|
+
out.set(pubKey, 1);
|
|
1165
|
+
out[34] = OP.OP_2;
|
|
1166
|
+
out[35] = OP.CHECKSIGALT;
|
|
1167
|
+
return out;
|
|
1168
|
+
}
|
|
1169
|
+
function isPayToPubKeyHash(script) {
|
|
1170
|
+
return isBytes(script) && script.length === 25 && script[0] === OP.DUP && script[1] === OP.HASH160 && script[2] === OP.DATA_20 && script[23] === OP.EQUALVERIFY && script[24] === OP.CHECKSIG;
|
|
1171
|
+
}
|
|
1172
|
+
function isPayToScriptHash(script) {
|
|
1173
|
+
return isBytes(script) && script.length === 23 && script[0] === OP.HASH160 && script[1] === OP.DATA_20 && script[22] === OP.EQUAL;
|
|
1174
|
+
}
|
|
1175
|
+
function extractHash160(script) {
|
|
1176
|
+
if (isPayToPubKeyHash(script)) return copyOf(script, 3, 20);
|
|
1177
|
+
if (isPayToScriptHash(script)) return copyOf(script, 2, 20);
|
|
1178
|
+
return null;
|
|
1179
|
+
}
|
|
1180
|
+
function classifyScript(script) {
|
|
1181
|
+
if (!isBytes(script)) return null;
|
|
1182
|
+
if (isPayToPubKeyHash(script)) return { kind: "pubkeyhash-ecdsa", hash: copyOf(script, 3, 20) };
|
|
1183
|
+
if (isPayToScriptHash(script)) return { kind: "scripthash", hash: copyOf(script, 2, 20) };
|
|
1184
|
+
if (script.length === 26 && script[0] === OP.DUP && script[1] === OP.HASH160 && script[2] === OP.DATA_20 && script[23] === OP.EQUALVERIFY && script[25] === OP.CHECKSIGALT) {
|
|
1185
|
+
if (script[24] === OP.OP_1) {
|
|
1186
|
+
return { kind: "pubkeyhash-ed25519", hash: copyOf(script, 3, 20) };
|
|
1187
|
+
}
|
|
1188
|
+
if (script[24] === OP.OP_2) {
|
|
1189
|
+
return { kind: "pubkeyhash-schnorr", hash: copyOf(script, 3, 20) };
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
return null;
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
// src/address.ts
|
|
1196
|
+
var MAX_ADDRESS_LENGTH = maxBase58Length(33 + 2 + 4);
|
|
1197
|
+
var PREFIXES = [];
|
|
1198
|
+
for (const network of Object.values(networks)) {
|
|
1199
|
+
PREFIXES.push(
|
|
1200
|
+
{ network, kind: "pubkeyhash-ecdsa", prefix: network.pubKeyHashAddrId },
|
|
1201
|
+
{ network, kind: "pubkeyhash-ed25519", prefix: network.pubKeyHashEdwardsAddrId },
|
|
1202
|
+
{ network, kind: "pubkeyhash-schnorr", prefix: network.pubKeyHashSchnorrAddrId },
|
|
1203
|
+
{ network, kind: "scripthash", prefix: network.scriptHashAddrId },
|
|
1204
|
+
{ network, kind: "pubkey-ecdsa", prefix: network.pubKeyAddrId }
|
|
1205
|
+
);
|
|
1206
|
+
}
|
|
1207
|
+
function encode(prefix, payload) {
|
|
1208
|
+
const data = new Uint8Array(2 + payload.length);
|
|
1209
|
+
data[0] = prefix[0];
|
|
1210
|
+
data[1] = prefix[1];
|
|
1211
|
+
data.set(payload, 2);
|
|
1212
|
+
return checkEncode(data);
|
|
1213
|
+
}
|
|
1214
|
+
function pubKeyHashAddress(hash, network) {
|
|
1215
|
+
if (hash.length !== 20) throw err("bad-length", "pubKeyHashAddress", `hash must be 20 bytes, got ${hash.length}`);
|
|
1216
|
+
return encode(network.pubKeyHashAddrId, hash);
|
|
1217
|
+
}
|
|
1218
|
+
function scriptHashAddress(hash, network) {
|
|
1219
|
+
if (hash.length !== 20) throw err("bad-length", "scriptHashAddress", `hash must be 20 bytes, got ${hash.length}`);
|
|
1220
|
+
return encode(network.scriptHashAddrId, hash);
|
|
1221
|
+
}
|
|
1222
|
+
function pubKeyHashEd25519Address(hash, network) {
|
|
1223
|
+
if (hash.length !== 20) throw err("bad-length", "pubKeyHashEd25519Address", `hash must be 20 bytes, got ${hash.length}`);
|
|
1224
|
+
return encode(network.pubKeyHashEdwardsAddrId, hash);
|
|
1225
|
+
}
|
|
1226
|
+
function pubKeyHashSchnorrAddress(hash, network) {
|
|
1227
|
+
if (hash.length !== 20) throw err("bad-length", "pubKeyHashSchnorrAddress", `hash must be 20 bytes, got ${hash.length}`);
|
|
1228
|
+
return encode(network.pubKeyHashSchnorrAddrId, hash);
|
|
1229
|
+
}
|
|
1230
|
+
var SIG_TYPE_ODD_FLAG = 128;
|
|
1231
|
+
function encodePubKeyData(compressedPubKey) {
|
|
1232
|
+
assertCompressedPubKey(compressedPubKey, "pubKeyAddress");
|
|
1233
|
+
const prefix = compressedPubKey[0];
|
|
1234
|
+
const data = new Uint8Array(33);
|
|
1235
|
+
data[0] = SignatureTypeEcdsa | (prefix === 3 ? SIG_TYPE_ODD_FLAG : 0);
|
|
1236
|
+
data.set(compressedPubKey.subarray(1), 1);
|
|
1237
|
+
return data;
|
|
1238
|
+
}
|
|
1239
|
+
function decodePubKeyData(data) {
|
|
1240
|
+
const sigType = data[0] & ~SIG_TYPE_ODD_FLAG;
|
|
1241
|
+
const odd = (data[0] & SIG_TYPE_ODD_FLAG) !== 0;
|
|
1242
|
+
if (sigType === SignatureTypeEd25519) {
|
|
1243
|
+
const pubKey2 = copyOf(data, 1, 32);
|
|
1244
|
+
if (!isValidEd25519PublicKey(pubKey2)) {
|
|
1245
|
+
throw err("invalid-public-key", "decodeAddress", "pubkey is not a valid Ed25519 curve point");
|
|
1246
|
+
}
|
|
1247
|
+
return { kind: "pubkey-ed25519", pubKey: pubKey2 };
|
|
1248
|
+
}
|
|
1249
|
+
if (sigType !== SignatureTypeEcdsa && sigType !== SignatureTypeSchnorr) {
|
|
1250
|
+
throw err("unsupported-signature-type", "decodeAddress", `unsupported pubkey signature type ${sigType}`);
|
|
1251
|
+
}
|
|
1252
|
+
const pubKey = new Uint8Array(33);
|
|
1253
|
+
pubKey[0] = odd ? 3 : 2;
|
|
1254
|
+
pubKey.set(data.subarray(1), 1);
|
|
1255
|
+
if (!isValidPublicKey(pubKey)) {
|
|
1256
|
+
throw err("invalid-public-key", "decodeAddress", "pubkey is not a valid curve point");
|
|
1257
|
+
}
|
|
1258
|
+
return { kind: sigType === SignatureTypeEcdsa ? "pubkey-ecdsa" : "pubkey-schnorr", pubKey };
|
|
1259
|
+
}
|
|
1260
|
+
var SignatureTypeEcdsa = 0;
|
|
1261
|
+
var SignatureTypeEd25519 = 1;
|
|
1262
|
+
var SignatureTypeSchnorr = 2;
|
|
1263
|
+
function pubKeyAddress(compressedPubKey, network) {
|
|
1264
|
+
return encode(network.pubKeyAddrId, encodePubKeyData(compressedPubKey));
|
|
1265
|
+
}
|
|
1266
|
+
function pubKeyEd25519Address(pubKey, network) {
|
|
1267
|
+
if (pubKey.length !== 32) {
|
|
1268
|
+
throw err("invalid-public-key", "pubKeyEd25519Address", `an Ed25519 public key must be 32 bytes, got ${pubKey.length}`);
|
|
1269
|
+
}
|
|
1270
|
+
if (!isValidEd25519PublicKey(pubKey)) {
|
|
1271
|
+
throw err("invalid-public-key", "pubKeyEd25519Address", "public key is not a valid Ed25519 curve point");
|
|
1272
|
+
}
|
|
1273
|
+
const data = new Uint8Array(33);
|
|
1274
|
+
data[0] = SignatureTypeEd25519;
|
|
1275
|
+
data.set(pubKey, 1);
|
|
1276
|
+
return encode(network.pubKeyAddrId, data);
|
|
1277
|
+
}
|
|
1278
|
+
function pubKeySchnorrAddress(compressedPubKey, network) {
|
|
1279
|
+
assertCompressedPubKey(compressedPubKey, "pubKeySchnorrAddress");
|
|
1280
|
+
const data = new Uint8Array(33);
|
|
1281
|
+
data[0] = SignatureTypeSchnorr | (compressedPubKey[0] === 3 ? SIG_TYPE_ODD_FLAG : 0);
|
|
1282
|
+
data.set(compressedPubKey.subarray(1), 1);
|
|
1283
|
+
return encode(network.pubKeyAddrId, data);
|
|
1284
|
+
}
|
|
1285
|
+
function addressFromPubKey(pubKey, network) {
|
|
1286
|
+
assertPubKey(pubKey, "addressFromPubKey");
|
|
1287
|
+
return pubKeyHashAddress(hash160(pubKey), network);
|
|
1288
|
+
}
|
|
1289
|
+
function addressFromScript(redeemScript, network) {
|
|
1290
|
+
return scriptHashAddress(hash160(redeemScript), network);
|
|
1291
|
+
}
|
|
1292
|
+
function decodeAddress(address, network) {
|
|
1293
|
+
if (typeof address !== "string") {
|
|
1294
|
+
throw err("invalid-argument", "decodeAddress", `address must be a string, got ${typeName(address)}`);
|
|
1295
|
+
}
|
|
1296
|
+
if (address.length > MAX_ADDRESS_LENGTH) {
|
|
1297
|
+
throw err(
|
|
1298
|
+
"input-too-long",
|
|
1299
|
+
"decodeAddress",
|
|
1300
|
+
`${address.length} characters exceeds the ${MAX_ADDRESS_LENGTH}-character maximum`
|
|
1301
|
+
);
|
|
1302
|
+
}
|
|
1303
|
+
const data = checkDecode(address);
|
|
1304
|
+
if (data.length < 3) throw err("bad-length", "decodeAddress", `payload is ${data.length} bytes, too short to hold a prefix and data`);
|
|
1305
|
+
const prefix = [data[0], data[1]];
|
|
1306
|
+
const payload = data.subarray(2);
|
|
1307
|
+
const match = PREFIXES.find(
|
|
1308
|
+
(e) => e.prefix[0] === prefix[0] && e.prefix[1] === prefix[1] && (!network || e.network === network)
|
|
1309
|
+
);
|
|
1310
|
+
if (!match) {
|
|
1311
|
+
const hex = `0x${prefix[0].toString(16).padStart(2, "0")}${prefix[1].toString(16).padStart(2, "0")}`;
|
|
1312
|
+
const onAnotherNetwork = network && PREFIXES.find((e) => e.prefix[0] === prefix[0] && e.prefix[1] === prefix[1]);
|
|
1313
|
+
if (onAnotherNetwork) {
|
|
1314
|
+
throw err(
|
|
1315
|
+
"wrong-network",
|
|
1316
|
+
"decodeAddress",
|
|
1317
|
+
`address is a ${onAnotherNetwork.kind} address for ${onAnotherNetwork.network.name}, not ${network.name}`
|
|
1318
|
+
);
|
|
1319
|
+
}
|
|
1320
|
+
throw err("unknown-prefix", "decodeAddress", `unknown address prefix ${hex}`);
|
|
1321
|
+
}
|
|
1322
|
+
if (match.kind === "pubkey-ecdsa") {
|
|
1323
|
+
if (payload.length !== 33) throw err("bad-length", "decodeAddress", `pay-to-pubkey payload must be 33 bytes, got ${payload.length}`);
|
|
1324
|
+
const { kind, pubKey } = decodePubKeyData(payload);
|
|
1325
|
+
return { network: match.network, kind, pubKey, address };
|
|
1326
|
+
}
|
|
1327
|
+
if (payload.length !== 20) throw err("bad-length", "decodeAddress", `hash payload must be 20 bytes, got ${payload.length}`);
|
|
1328
|
+
return {
|
|
1329
|
+
network: match.network,
|
|
1330
|
+
kind: match.kind,
|
|
1331
|
+
hash: copyOf(payload, 0, 20),
|
|
1332
|
+
address
|
|
1333
|
+
};
|
|
1334
|
+
}
|
|
1335
|
+
function isValidAddress(address, network) {
|
|
1336
|
+
try {
|
|
1337
|
+
decodeAddress(address, network);
|
|
1338
|
+
return true;
|
|
1339
|
+
} catch {
|
|
1340
|
+
return false;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
function addressToScript(address, network) {
|
|
1344
|
+
if (!network || typeof network.name !== "string") {
|
|
1345
|
+
throw err(
|
|
1346
|
+
"invalid-argument",
|
|
1347
|
+
"addressToScript",
|
|
1348
|
+
"a network is required (pass mainnet, testnet3, simnet or regnet)"
|
|
1349
|
+
);
|
|
1350
|
+
}
|
|
1351
|
+
const d = decodeAddress(address, network);
|
|
1352
|
+
switch (d.kind) {
|
|
1353
|
+
case "pubkeyhash-ecdsa":
|
|
1354
|
+
return payToPubKeyHashScript(d.hash);
|
|
1355
|
+
// The alternative signature suites use OP_CHECKSIGALT with the signature
|
|
1356
|
+
// type pushed as a small integer (Ed25519 = 1, Schnorr = 2).
|
|
1357
|
+
case "pubkeyhash-ed25519":
|
|
1358
|
+
return payToPubKeyHashAltScript(d.hash, 1);
|
|
1359
|
+
case "pubkeyhash-schnorr":
|
|
1360
|
+
return payToPubKeyHashAltScript(d.hash, 2);
|
|
1361
|
+
case "scripthash":
|
|
1362
|
+
return payToScriptHashScript(d.hash);
|
|
1363
|
+
case "pubkey-ecdsa":
|
|
1364
|
+
return payToPubKeyScript(d.pubKey);
|
|
1365
|
+
case "pubkey-ed25519":
|
|
1366
|
+
return payToPubKeyAltScript(d.pubKey, 1);
|
|
1367
|
+
case "pubkey-schnorr":
|
|
1368
|
+
return payToPubKeyAltScript(d.pubKey, 2);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
// src/wif.ts
|
|
1373
|
+
var SignatureType = /* @__PURE__ */ ((SignatureType2) => {
|
|
1374
|
+
SignatureType2[SignatureType2["Ecdsa"] = 0] = "Ecdsa";
|
|
1375
|
+
SignatureType2[SignatureType2["Ed25519"] = 1] = "Ed25519";
|
|
1376
|
+
SignatureType2[SignatureType2["SchnorrSecp256k1"] = 2] = "SchnorrSecp256k1";
|
|
1377
|
+
return SignatureType2;
|
|
1378
|
+
})(SignatureType || {});
|
|
1379
|
+
function wifChecksum(data) {
|
|
1380
|
+
return blake256(data).subarray(0, 4);
|
|
1381
|
+
}
|
|
1382
|
+
function assertWifScalar(privateKey, signatureType, who) {
|
|
1383
|
+
if (signatureType !== 1 /* Ed25519 */) return;
|
|
1384
|
+
const scalar = bytesToBigInt(privateKey);
|
|
1385
|
+
if (scalar === 0n || scalar > ED25519_CURVE_ORDER) {
|
|
1386
|
+
throw err("invalid-private-key", who, "Ed25519 scalar is zero or above the group order");
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
function encodeWif(privateKey, network, signatureType = 0 /* Ecdsa */) {
|
|
1390
|
+
if (!isBytes(privateKey)) throw err("invalid-argument", "encodeWif", "private key must be a Uint8Array");
|
|
1391
|
+
if (privateKey.length !== 32) throw err("bad-length", "encodeWif", `private key must be 32 bytes, got ${privateKey.length}`);
|
|
1392
|
+
if (!Number.isInteger(signatureType) || SignatureType[signatureType] === void 0) {
|
|
1393
|
+
throw err("unsupported-signature-type", "encodeWif", `unknown signature type ${signatureType}`);
|
|
1394
|
+
}
|
|
1395
|
+
assertWifScalar(privateKey, signatureType, "encodeWif");
|
|
1396
|
+
const payload = new Uint8Array(3 + 32);
|
|
1397
|
+
payload[0] = network.privateKeyId[0];
|
|
1398
|
+
payload[1] = network.privateKeyId[1];
|
|
1399
|
+
payload[2] = signatureType;
|
|
1400
|
+
payload.set(privateKey, 3);
|
|
1401
|
+
const full = new Uint8Array(payload.length + 4);
|
|
1402
|
+
full.set(payload);
|
|
1403
|
+
full.set(wifChecksum(payload), payload.length);
|
|
1404
|
+
return base58Encode(full);
|
|
1405
|
+
}
|
|
1406
|
+
var MAX_WIF_LENGTH = maxBase58Length(39);
|
|
1407
|
+
function decodeWif(wif) {
|
|
1408
|
+
if (typeof wif !== "string") {
|
|
1409
|
+
throw err("invalid-argument", "decodeWif", `WIF must be a string, got ${typeName(wif)}`);
|
|
1410
|
+
}
|
|
1411
|
+
if (wif.length > MAX_WIF_LENGTH) {
|
|
1412
|
+
throw err(
|
|
1413
|
+
"input-too-long",
|
|
1414
|
+
"decodeWif",
|
|
1415
|
+
`${wif.length} characters exceeds the ${MAX_WIF_LENGTH}-character maximum`
|
|
1416
|
+
);
|
|
1417
|
+
}
|
|
1418
|
+
const full = base58Decode(wif);
|
|
1419
|
+
if (full.length !== 39) throw err("bad-length", "decodeWif", `decoded to ${full.length} bytes, expected 39`);
|
|
1420
|
+
const data = full.subarray(0, 35);
|
|
1421
|
+
const checksum = full.subarray(35);
|
|
1422
|
+
const expected = wifChecksum(data);
|
|
1423
|
+
for (let i = 0; i < 4; i++) {
|
|
1424
|
+
if (checksum[i] !== expected[i]) throw err("bad-checksum", "decodeWif", "checksum does not match");
|
|
1425
|
+
}
|
|
1426
|
+
const prefix = [data[0], data[1]];
|
|
1427
|
+
const signatureType = data[2];
|
|
1428
|
+
const privateKey = data.slice(3);
|
|
1429
|
+
const network = Object.values(networks).find(
|
|
1430
|
+
(n) => n.privateKeyId[0] === prefix[0] && n.privateKeyId[1] === prefix[1]
|
|
1431
|
+
);
|
|
1432
|
+
if (!network) throw err("unknown-prefix", "decodeWif", `no network has the private-key prefix 0x${prefix[0].toString(16).padStart(2, "0")}${prefix[1].toString(16).padStart(2, "0")}`);
|
|
1433
|
+
if (SignatureType[signatureType] === void 0) {
|
|
1434
|
+
throw err("unsupported-signature-type", "decodeWif", `unknown signature type ${signatureType}`);
|
|
1435
|
+
}
|
|
1436
|
+
assertWifScalar(privateKey, signatureType, "decodeWif");
|
|
1437
|
+
return { privateKey, network, signatureType };
|
|
1438
|
+
}
|
|
1439
|
+
var HARDENED_OFFSET = 2147483648;
|
|
1440
|
+
var MASTER_HMAC_KEY = new TextEncoder().encode("Bitcoin seed");
|
|
1441
|
+
var SERIALIZED_LENGTH = 78;
|
|
1442
|
+
var MAX_EXTENDED_KEY_LENGTH = maxBase58Length(SERIALIZED_LENGTH + 4);
|
|
1443
|
+
function hardened(index) {
|
|
1444
|
+
if (!Number.isInteger(index) || index < 0 || index >= HARDENED_OFFSET) {
|
|
1445
|
+
throw err(Number.isInteger(index) ? "out-of-range" : "not-an-integer", "hardened", `index must be an integer in 0..2^31-1, got ${shown(index)}`);
|
|
1446
|
+
}
|
|
1447
|
+
return index + HARDENED_OFFSET >>> 0;
|
|
1448
|
+
}
|
|
1449
|
+
function ser32(value) {
|
|
1450
|
+
return Uint8Array.of(
|
|
1451
|
+
value >>> 24 & 255,
|
|
1452
|
+
value >>> 16 & 255,
|
|
1453
|
+
value >>> 8 & 255,
|
|
1454
|
+
value & 255
|
|
1455
|
+
);
|
|
1456
|
+
}
|
|
1457
|
+
function leadingZeros(key) {
|
|
1458
|
+
let n = 0;
|
|
1459
|
+
while (n < key.length && key[n] === 0) n++;
|
|
1460
|
+
return n;
|
|
1461
|
+
}
|
|
1462
|
+
var ExtendedKey = class _ExtendedKey {
|
|
1463
|
+
constructor(network, isPrivate, privateKey, compressedPublicKey, chainCodeBytes, depth, parentFingerprintBytes, childNumber, scalarStripped = false) {
|
|
1464
|
+
this.network = network;
|
|
1465
|
+
this.isPrivate = isPrivate;
|
|
1466
|
+
this.privateKey = privateKey;
|
|
1467
|
+
this.compressedPublicKey = compressedPublicKey;
|
|
1468
|
+
this.chainCodeBytes = chainCodeBytes;
|
|
1469
|
+
this.depth = depth;
|
|
1470
|
+
this.parentFingerprintBytes = parentFingerprintBytes;
|
|
1471
|
+
this.childNumber = childNumber;
|
|
1472
|
+
this.scalarStripped = scalarStripped;
|
|
1473
|
+
}
|
|
1474
|
+
network;
|
|
1475
|
+
isPrivate;
|
|
1476
|
+
privateKey;
|
|
1477
|
+
compressedPublicKey;
|
|
1478
|
+
chainCodeBytes;
|
|
1479
|
+
depth;
|
|
1480
|
+
parentFingerprintBytes;
|
|
1481
|
+
childNumber;
|
|
1482
|
+
scalarStripped;
|
|
1483
|
+
/** Memoized hash160 of the public key; see {@link identifier}. */
|
|
1484
|
+
cachedIdentifier = void 0;
|
|
1485
|
+
/**
|
|
1486
|
+
* Memoized decompression of {@link compressedPublicKey}, so deriving a chain of
|
|
1487
|
+
* public children does the modular square root once instead of per step. Only
|
|
1488
|
+
* populated on the public-derivation path.
|
|
1489
|
+
*/
|
|
1490
|
+
cachedPoint = void 0;
|
|
1491
|
+
/** Derive a master key from a BIP32 seed (16–64 bytes). */
|
|
1492
|
+
static fromSeed(seed, network) {
|
|
1493
|
+
if (seed.length < 16 || seed.length > 64) {
|
|
1494
|
+
throw err("out-of-range", "ExtendedKey.fromSeed", `seed must be 16..64 bytes, got ${seed.length}`);
|
|
1495
|
+
}
|
|
1496
|
+
const I = hmac.hmac(sha512.sha512, MASTER_HMAC_KEY, seed);
|
|
1497
|
+
const il = I.subarray(0, 32);
|
|
1498
|
+
const ir = I.subarray(32, 64);
|
|
1499
|
+
if (!isValidPrivateKey(il)) throw err("invalid-private-key", "ExtendedKey.fromSeed", "seed produced an unusable master key; retry with a new seed");
|
|
1500
|
+
return new _ExtendedKey(
|
|
1501
|
+
network,
|
|
1502
|
+
true,
|
|
1503
|
+
il.slice(),
|
|
1504
|
+
publicKeyFromPrivate(il),
|
|
1505
|
+
ir.slice(),
|
|
1506
|
+
0,
|
|
1507
|
+
new Uint8Array(4),
|
|
1508
|
+
0
|
|
1509
|
+
);
|
|
1510
|
+
}
|
|
1511
|
+
/** The compressed public key (33 bytes). */
|
|
1512
|
+
publicKey() {
|
|
1513
|
+
return this.compressedPublicKey.slice();
|
|
1514
|
+
}
|
|
1515
|
+
/** The 32-byte private scalar. Throws for a public key. */
|
|
1516
|
+
privateKeyBytes() {
|
|
1517
|
+
if (!this.privateKey) throw err("not-a-private-key", "ExtendedKey.privateKeyBytes", "this is a public (neutered) key");
|
|
1518
|
+
return this.privateKey.slice();
|
|
1519
|
+
}
|
|
1520
|
+
/**
|
|
1521
|
+
* The 32-byte chain code. A copy: the key's own derivation reads the internal
|
|
1522
|
+
* bytes, so handing out a live view would let a caller change what this key
|
|
1523
|
+
* derives.
|
|
1524
|
+
*/
|
|
1525
|
+
get chainCode() {
|
|
1526
|
+
return copyOf(this.chainCodeBytes, 0, 32);
|
|
1527
|
+
}
|
|
1528
|
+
/** The parent's 4-byte fingerprint, or four zero bytes for a master key. A copy. */
|
|
1529
|
+
get parentFingerprint() {
|
|
1530
|
+
return copyOf(this.parentFingerprintBytes, 0, 4);
|
|
1531
|
+
}
|
|
1532
|
+
/**
|
|
1533
|
+
* Identifier = hash160(compressed pubkey); the fingerprint is its first 4 bytes.
|
|
1534
|
+
*
|
|
1535
|
+
* Memoized, because `derive` needs the parent fingerprint for every child and
|
|
1536
|
+
* would otherwise recompute a BLAKE-256 plus a RIPEMD-160 of the same key at
|
|
1537
|
+
* every step. Both accessors return copies: the memo turned what used to be a
|
|
1538
|
+
* per-call throwaway digest into long-lived shared state, so handing out a view
|
|
1539
|
+
* would let one caller's write corrupt the cache, this key's own fingerprint,
|
|
1540
|
+
* every sibling's `parentFingerprint` and every child derived afterwards.
|
|
1541
|
+
*/
|
|
1542
|
+
identifier() {
|
|
1543
|
+
return copyOf(this.identifierBytes(), 0, 20);
|
|
1544
|
+
}
|
|
1545
|
+
fingerprint() {
|
|
1546
|
+
return copyOf(this.identifierBytes(), 0, 4);
|
|
1547
|
+
}
|
|
1548
|
+
/** The memoized digest itself. Never escapes this class. */
|
|
1549
|
+
identifierBytes() {
|
|
1550
|
+
if (this.cachedIdentifier === void 0) {
|
|
1551
|
+
this.cachedIdentifier = hash160(this.compressedPublicKey);
|
|
1552
|
+
}
|
|
1553
|
+
return this.cachedIdentifier;
|
|
1554
|
+
}
|
|
1555
|
+
/**
|
|
1556
|
+
* Derive a child key by index, the **Decred way** — the equivalent of dcrd
|
|
1557
|
+
* `hdkeychain.Child`, and what dcrwallet and Decrediton derive with for the
|
|
1558
|
+
* whole wallet path. Use {@link hardened} for hardened indices.
|
|
1559
|
+
*
|
|
1560
|
+
* This is the default because it is what the Decred ecosystem derives; see
|
|
1561
|
+
* {@link deriveBip32Std} for the strict form and the module docs for why they
|
|
1562
|
+
* differ.
|
|
1563
|
+
*/
|
|
1564
|
+
derive(index) {
|
|
1565
|
+
return this.deriveInner(index, false);
|
|
1566
|
+
}
|
|
1567
|
+
/**
|
|
1568
|
+
* Derive a child key by **strict BIP32** — the equivalent of dcrd
|
|
1569
|
+
* `hdkeychain.ChildBIP32Std`, retaining the leading zero bytes of the parent
|
|
1570
|
+
* private key that {@link derive} strips.
|
|
1571
|
+
*
|
|
1572
|
+
* Produces different hardened children from {@link derive} for any parent
|
|
1573
|
+
* scalar with a leading zero byte, which is about 1 key in 256 at each
|
|
1574
|
+
* hardened step. Use it only when strict BIP32 is what you want; anything that
|
|
1575
|
+
* has to agree with a dcrwallet or Decrediton seed must not.
|
|
1576
|
+
*/
|
|
1577
|
+
deriveBip32Std(index) {
|
|
1578
|
+
return this.deriveInner(index, true);
|
|
1579
|
+
}
|
|
1580
|
+
deriveInner(index, strictBip32) {
|
|
1581
|
+
if (this.depth >= 255) throw err("max-depth", "ExtendedKey.derive", "cannot derive beyond depth 255, which is all a single byte can serialize");
|
|
1582
|
+
if (!Number.isInteger(index)) throw err("not-an-integer", "ExtendedKey.derive", `index must be an integer, got ${shown(index)}`);
|
|
1583
|
+
if (index < 0 || index > 4294967295) throw err("out-of-range", "ExtendedKey.derive", `index ${index} is outside 0..2^32-1`);
|
|
1584
|
+
const idx = index >>> 0;
|
|
1585
|
+
const isHardened = idx >= HARDENED_OFFSET;
|
|
1586
|
+
const data = new Uint8Array(37);
|
|
1587
|
+
if (isHardened) {
|
|
1588
|
+
if (!this.privateKey) {
|
|
1589
|
+
throw err("hardened-from-public", "ExtendedKey.derive", "cannot derive a hardened child from a public key");
|
|
1590
|
+
}
|
|
1591
|
+
const skip = this.scalarStripped ? leadingZeros(this.privateKey) : 0;
|
|
1592
|
+
data.set(this.privateKey.subarray(skip), 1);
|
|
1593
|
+
} else {
|
|
1594
|
+
data.set(this.compressedPublicKey, 0);
|
|
1595
|
+
}
|
|
1596
|
+
data.set(ser32(idx), 33);
|
|
1597
|
+
const I = hmac.hmac(sha512.sha512, this.chainCodeBytes, data);
|
|
1598
|
+
const il = I.subarray(0, 32);
|
|
1599
|
+
const childChainCode = I.subarray(32, 64).slice();
|
|
1600
|
+
const parentFp = this.fingerprint();
|
|
1601
|
+
const childDepth = this.depth + 1;
|
|
1602
|
+
if (this.privateKey) {
|
|
1603
|
+
const childPriv = privateKeyTweakAdd(this.privateKey, il);
|
|
1604
|
+
if (!childPriv) throw err("invalid-child", "ExtendedKey.derive", "derived an invalid child key; retry with the next index");
|
|
1605
|
+
return new _ExtendedKey(
|
|
1606
|
+
this.network,
|
|
1607
|
+
true,
|
|
1608
|
+
childPriv,
|
|
1609
|
+
publicKeyFromPrivate(childPriv),
|
|
1610
|
+
childChainCode,
|
|
1611
|
+
childDepth,
|
|
1612
|
+
parentFp,
|
|
1613
|
+
idx,
|
|
1614
|
+
// dcrd's `child` strips the derived scalar unless strict BIP32 was asked
|
|
1615
|
+
// for, and that state is what the next hardened step reads.
|
|
1616
|
+
!strictBip32
|
|
1617
|
+
);
|
|
1618
|
+
}
|
|
1619
|
+
if (this.cachedPoint === void 0) {
|
|
1620
|
+
const parsed = parsePublicKeyPoint(this.compressedPublicKey);
|
|
1621
|
+
if (parsed === null) throw err("invalid-public-key", "ExtendedKey.derive", "public key is not a valid curve point");
|
|
1622
|
+
this.cachedPoint = parsed;
|
|
1623
|
+
}
|
|
1624
|
+
const childPub = publicKeyTweakAddPoint(this.cachedPoint, il);
|
|
1625
|
+
if (!childPub) throw err("invalid-child", "ExtendedKey.derive", "derived an invalid child key; retry with the next index");
|
|
1626
|
+
return new _ExtendedKey(
|
|
1627
|
+
this.network,
|
|
1628
|
+
false,
|
|
1629
|
+
null,
|
|
1630
|
+
childPub,
|
|
1631
|
+
childChainCode,
|
|
1632
|
+
childDepth,
|
|
1633
|
+
parentFp,
|
|
1634
|
+
idx
|
|
1635
|
+
);
|
|
1636
|
+
}
|
|
1637
|
+
/**
|
|
1638
|
+
* Derive along a path like `m/44'/42'/0'/0/0`, the **Decred way** (see
|
|
1639
|
+
* {@link derive}). An apostrophe or `h` marks a hardened index.
|
|
1640
|
+
*/
|
|
1641
|
+
derivePath(path) {
|
|
1642
|
+
return this.derivePathInner(path, false);
|
|
1643
|
+
}
|
|
1644
|
+
/**
|
|
1645
|
+
* Derive along a path using **strict BIP32** (see {@link deriveBip32Std}).
|
|
1646
|
+
* Diverges from {@link derivePath} below any hardened step whose parent scalar
|
|
1647
|
+
* has a leading zero byte, so do not use it to reproduce a wallet seed.
|
|
1648
|
+
*/
|
|
1649
|
+
derivePathBip32Std(path) {
|
|
1650
|
+
return this.derivePathInner(path, true);
|
|
1651
|
+
}
|
|
1652
|
+
derivePathInner(path, strictBip32) {
|
|
1653
|
+
const parts = path.trim().split("/");
|
|
1654
|
+
if (parts[0] === "m" || parts[0] === "M") parts.shift();
|
|
1655
|
+
let key = this;
|
|
1656
|
+
for (const raw of parts) {
|
|
1657
|
+
const isH = raw.endsWith("'") || raw.endsWith("h") || raw.endsWith("H");
|
|
1658
|
+
const numStr = isH ? raw.slice(0, -1) : raw;
|
|
1659
|
+
if (!/^\d+$/.test(numStr)) {
|
|
1660
|
+
throw err("invalid-path", "ExtendedKey.derivePath", `invalid path element ${shown(raw)}`);
|
|
1661
|
+
}
|
|
1662
|
+
const n = Number(numStr);
|
|
1663
|
+
if (n >= HARDENED_OFFSET) {
|
|
1664
|
+
throw err("invalid-path", "ExtendedKey.derivePath", `path index ${n} is at or above the hardened offset; write it as ${n - HARDENED_OFFSET}' instead`);
|
|
1665
|
+
}
|
|
1666
|
+
const idx = isH ? hardened(n) : n;
|
|
1667
|
+
key = strictBip32 ? key.deriveBip32Std(idx) : key.derive(idx);
|
|
1668
|
+
}
|
|
1669
|
+
return key;
|
|
1670
|
+
}
|
|
1671
|
+
/** Return the public (watch-only) version of this key. */
|
|
1672
|
+
neuter() {
|
|
1673
|
+
if (!this.isPrivate) return this;
|
|
1674
|
+
return new _ExtendedKey(
|
|
1675
|
+
this.network,
|
|
1676
|
+
false,
|
|
1677
|
+
null,
|
|
1678
|
+
this.compressedPublicKey,
|
|
1679
|
+
this.chainCodeBytes,
|
|
1680
|
+
this.depth,
|
|
1681
|
+
this.parentFingerprintBytes,
|
|
1682
|
+
this.childNumber
|
|
1683
|
+
);
|
|
1684
|
+
}
|
|
1685
|
+
/** The standard P2PKH address for this key on its network. */
|
|
1686
|
+
address(network = this.network) {
|
|
1687
|
+
return pubKeyHashAddress(hash160(this.compressedPublicKey), network);
|
|
1688
|
+
}
|
|
1689
|
+
/** Serialize to the 78-byte BIP32 form (without the base58check checksum). */
|
|
1690
|
+
serialize() {
|
|
1691
|
+
const version = this.isPrivate ? this.network.hdPrivateKeyId : this.network.hdPublicKeyId;
|
|
1692
|
+
const out = new Uint8Array(SERIALIZED_LENGTH);
|
|
1693
|
+
out[0] = version[0];
|
|
1694
|
+
out[1] = version[1];
|
|
1695
|
+
out[2] = version[2];
|
|
1696
|
+
out[3] = version[3];
|
|
1697
|
+
out[4] = this.depth & 255;
|
|
1698
|
+
out.set(this.parentFingerprintBytes, 5);
|
|
1699
|
+
out.set(ser32(this.childNumber), 9);
|
|
1700
|
+
out.set(this.chainCodeBytes, 13);
|
|
1701
|
+
if (this.isPrivate) {
|
|
1702
|
+
out[45] = 0;
|
|
1703
|
+
out.set(this.privateKey, 46);
|
|
1704
|
+
} else {
|
|
1705
|
+
out.set(this.compressedPublicKey, 45);
|
|
1706
|
+
}
|
|
1707
|
+
return out;
|
|
1708
|
+
}
|
|
1709
|
+
/** Encode as a `dprv`/`dpub` (or per-network) base58check string. */
|
|
1710
|
+
toString() {
|
|
1711
|
+
return checkEncode(this.serialize());
|
|
1712
|
+
}
|
|
1713
|
+
/** Parse an extended key string, validating the checksum and version. */
|
|
1714
|
+
static fromString(str) {
|
|
1715
|
+
if (typeof str !== "string") {
|
|
1716
|
+
throw err(
|
|
1717
|
+
"invalid-argument",
|
|
1718
|
+
"ExtendedKey.fromString",
|
|
1719
|
+
`extended key must be a string, got ${typeName(str)}`
|
|
1720
|
+
);
|
|
1721
|
+
}
|
|
1722
|
+
if (str.length > MAX_EXTENDED_KEY_LENGTH) {
|
|
1723
|
+
throw err(
|
|
1724
|
+
"input-too-long",
|
|
1725
|
+
"ExtendedKey.fromString",
|
|
1726
|
+
`${str.length} characters exceeds the ${MAX_EXTENDED_KEY_LENGTH}-character maximum`
|
|
1727
|
+
);
|
|
1728
|
+
}
|
|
1729
|
+
const data = checkDecode(str);
|
|
1730
|
+
return _ExtendedKey.fromSerialized(data);
|
|
1731
|
+
}
|
|
1732
|
+
/**
|
|
1733
|
+
* Parse a raw 78-byte serialization (checksum already verified/absent).
|
|
1734
|
+
*
|
|
1735
|
+
* Every field is copied out of `data`, so the returned key does not alias the
|
|
1736
|
+
* caller's buffer — which matters most here, because a caller doing the right
|
|
1737
|
+
* thing and wiping the serialization after parsing would otherwise destroy the
|
|
1738
|
+
* key it just parsed. See {@link copyOf}.
|
|
1739
|
+
*/
|
|
1740
|
+
static fromSerialized(data) {
|
|
1741
|
+
if (data.length !== SERIALIZED_LENGTH) throw err("bad-length", "ExtendedKey.fromSerialized", `expected ${SERIALIZED_LENGTH} bytes, got ${data.length}`);
|
|
1742
|
+
const version = [data[0], data[1], data[2], data[3]];
|
|
1743
|
+
const depth = data[4];
|
|
1744
|
+
const parentFingerprint = copyOf(data, 5, 4);
|
|
1745
|
+
const childNumber = (data[9] << 24 | data[10] << 16 | data[11] << 8 | data[12]) >>> 0;
|
|
1746
|
+
const chainCode = copyOf(data, 13, 32);
|
|
1747
|
+
const keyData = copyOf(data, 45, 33);
|
|
1748
|
+
const found = matchVersion(version);
|
|
1749
|
+
if (!found) throw err("unknown-version", "ExtendedKey.fromSerialized", `no network has the extended-key version 0x${version.map((b) => b.toString(16).padStart(2, "0")).join("")}`);
|
|
1750
|
+
const { network, isPrivate } = found;
|
|
1751
|
+
if (isPrivate) {
|
|
1752
|
+
if (keyData[0] !== 0) throw err("invalid-private-key", "ExtendedKey.fromSerialized", `a private key must be padded with a leading 0x00, got 0x${keyData[0].toString(16).padStart(2, "0")}`);
|
|
1753
|
+
const priv = copyOf(keyData, 1, 32);
|
|
1754
|
+
if (!isValidPrivateKey(priv)) throw err("invalid-private-key", "ExtendedKey.fromSerialized", "not a valid secp256k1 scalar");
|
|
1755
|
+
return new _ExtendedKey(
|
|
1756
|
+
network,
|
|
1757
|
+
true,
|
|
1758
|
+
priv,
|
|
1759
|
+
publicKeyFromPrivate(priv),
|
|
1760
|
+
chainCode,
|
|
1761
|
+
depth,
|
|
1762
|
+
parentFingerprint,
|
|
1763
|
+
childNumber
|
|
1764
|
+
);
|
|
1765
|
+
}
|
|
1766
|
+
if (keyData[0] !== 2 && keyData[0] !== 3) {
|
|
1767
|
+
throw err("invalid-public-key", "ExtendedKey.fromSerialized", `a compressed public key must start with 0x02 or 0x03, got 0x${keyData[0].toString(16).padStart(2, "0")}`);
|
|
1768
|
+
}
|
|
1769
|
+
if (!isValidPublicKey(keyData)) {
|
|
1770
|
+
throw err("invalid-public-key", "ExtendedKey.fromSerialized", "public key is not a valid curve point");
|
|
1771
|
+
}
|
|
1772
|
+
return new _ExtendedKey(
|
|
1773
|
+
network,
|
|
1774
|
+
false,
|
|
1775
|
+
null,
|
|
1776
|
+
keyData,
|
|
1777
|
+
chainCode,
|
|
1778
|
+
depth,
|
|
1779
|
+
parentFingerprint,
|
|
1780
|
+
childNumber
|
|
1781
|
+
);
|
|
1782
|
+
}
|
|
1783
|
+
};
|
|
1784
|
+
function matchVersion(v) {
|
|
1785
|
+
for (const network of Object.values(networks)) {
|
|
1786
|
+
if (eq4(v, network.hdPrivateKeyId)) return { network, isPrivate: true };
|
|
1787
|
+
if (eq4(v, network.hdPublicKeyId)) return { network, isPrivate: false };
|
|
1788
|
+
}
|
|
1789
|
+
return null;
|
|
1790
|
+
}
|
|
1791
|
+
function eq4(a, b) {
|
|
1792
|
+
return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];
|
|
1793
|
+
}
|
|
1794
|
+
var englishWordlist = english.wordlist;
|
|
1795
|
+
var MNEMONIC_WORD_COUNTS = [12, 15, 18, 21, 24];
|
|
1796
|
+
function assertMnemonicString(mnemonic, who) {
|
|
1797
|
+
if (typeof mnemonic !== "string") {
|
|
1798
|
+
throw err("invalid-argument", who, `mnemonic must be a string, got ${typeof mnemonic}`);
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
function assertWordlist(wordlist, who) {
|
|
1802
|
+
if (wordlist.length !== 2048) {
|
|
1803
|
+
throw err("invalid-argument", who, `wordlist must hold 2048 words, got ${wordlist.length}`);
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
function generateMnemonic(strength = 128, wordlist = english.wordlist) {
|
|
1807
|
+
if (!Number.isInteger(strength) || strength < 128 || strength > 256 || strength % 32 !== 0) {
|
|
1808
|
+
throw err(
|
|
1809
|
+
Number.isInteger(strength) ? "out-of-range" : "not-an-integer",
|
|
1810
|
+
"generateMnemonic",
|
|
1811
|
+
`strength must be 128, 160, 192, 224 or 256 bits, got ${shown(strength)}`
|
|
1812
|
+
);
|
|
1813
|
+
}
|
|
1814
|
+
assertWordlist(wordlist, "generateMnemonic");
|
|
1815
|
+
return bip39.generateMnemonic(wordlist, strength);
|
|
1816
|
+
}
|
|
1817
|
+
function validateMnemonic(mnemonic, wordlist = english.wordlist) {
|
|
1818
|
+
return bip39.validateMnemonic(mnemonic, wordlist);
|
|
1819
|
+
}
|
|
1820
|
+
function mnemonicToEntropy(mnemonic, wordlist = english.wordlist) {
|
|
1821
|
+
assertMnemonicString(mnemonic, "mnemonicToEntropy");
|
|
1822
|
+
assertWordlist(wordlist, "mnemonicToEntropy");
|
|
1823
|
+
try {
|
|
1824
|
+
return bip39.mnemonicToEntropy(mnemonic, wordlist);
|
|
1825
|
+
} catch {
|
|
1826
|
+
throw err(
|
|
1827
|
+
"invalid-mnemonic",
|
|
1828
|
+
"mnemonicToEntropy",
|
|
1829
|
+
"bad checksum, wrong word count, or a word not in the wordlist \u2014 pass the matching wordlist for a non-English phrase"
|
|
1830
|
+
);
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
function entropyToMnemonic(entropy, wordlist = english.wordlist) {
|
|
1834
|
+
if (entropy.length < 16 || entropy.length > 32 || entropy.length % 4 !== 0) {
|
|
1835
|
+
throw err(
|
|
1836
|
+
"bad-length",
|
|
1837
|
+
"entropyToMnemonic",
|
|
1838
|
+
`entropy must be 16\u201332 bytes and a multiple of 4, got ${entropy.length}`
|
|
1839
|
+
);
|
|
1840
|
+
}
|
|
1841
|
+
assertWordlist(wordlist, "entropyToMnemonic");
|
|
1842
|
+
return bip39.entropyToMnemonic(entropy, wordlist);
|
|
1843
|
+
}
|
|
1844
|
+
function mnemonicToSeed(mnemonic, passphrase = "") {
|
|
1845
|
+
assertMnemonicString(mnemonic, "mnemonicToSeed");
|
|
1846
|
+
const words = mnemonic.normalize("NFKD").split(" ").length;
|
|
1847
|
+
if (!MNEMONIC_WORD_COUNTS.includes(words)) {
|
|
1848
|
+
throw err(
|
|
1849
|
+
"invalid-mnemonic",
|
|
1850
|
+
"mnemonicToSeed",
|
|
1851
|
+
`a mnemonic is 12, 15, 18, 21 or 24 words, got ${words}`
|
|
1852
|
+
);
|
|
1853
|
+
}
|
|
1854
|
+
return bip39.mnemonicToSeedSync(mnemonic, passphrase);
|
|
1855
|
+
}
|
|
1856
|
+
function mnemonicToMasterKey(mnemonic, network, passphrase = "", wordlist = english.wordlist) {
|
|
1857
|
+
assertMnemonicString(mnemonic, "mnemonicToMasterKey");
|
|
1858
|
+
assertWordlist(wordlist, "mnemonicToMasterKey");
|
|
1859
|
+
if (!validateMnemonic(mnemonic, wordlist)) {
|
|
1860
|
+
throw err(
|
|
1861
|
+
"invalid-mnemonic",
|
|
1862
|
+
"mnemonicToMasterKey",
|
|
1863
|
+
"bad checksum, or a word not in the wordlist \u2014 pass the matching wordlist for a non-English phrase"
|
|
1864
|
+
);
|
|
1865
|
+
}
|
|
1866
|
+
return ExtendedKey.fromSeed(mnemonicToSeed(mnemonic, passphrase), network);
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
// src/tx.ts
|
|
1870
|
+
var TxSerializeType = /* @__PURE__ */ ((TxSerializeType2) => {
|
|
1871
|
+
TxSerializeType2[TxSerializeType2["Full"] = 0] = "Full";
|
|
1872
|
+
TxSerializeType2[TxSerializeType2["NoWitness"] = 1] = "NoWitness";
|
|
1873
|
+
TxSerializeType2[TxSerializeType2["OnlyWitness"] = 2] = "OnlyWitness";
|
|
1874
|
+
return TxSerializeType2;
|
|
1875
|
+
})(TxSerializeType || {});
|
|
1876
|
+
var MAX_SERIALIZE_TYPE = 3;
|
|
1877
|
+
var TxTree = /* @__PURE__ */ ((TxTree2) => {
|
|
1878
|
+
TxTree2[TxTree2["Regular"] = 0] = "Regular";
|
|
1879
|
+
TxTree2[TxTree2["Stake"] = 1] = "Stake";
|
|
1880
|
+
return TxTree2;
|
|
1881
|
+
})(TxTree || {});
|
|
1882
|
+
var DEFAULT_TX_VERSION = 1;
|
|
1883
|
+
var MAX_SEQUENCE = 4294967295;
|
|
1884
|
+
var NULL_VALUE_IN = -1n;
|
|
1885
|
+
var NULL_BLOCK_HEIGHT = 0;
|
|
1886
|
+
var NULL_BLOCK_INDEX = 4294967295;
|
|
1887
|
+
function reverse(bytes) {
|
|
1888
|
+
const out = new Uint8Array(bytes.length);
|
|
1889
|
+
for (let i = 0; i < bytes.length; i++) out[i] = bytes[bytes.length - 1 - i];
|
|
1890
|
+
return out;
|
|
1891
|
+
}
|
|
1892
|
+
function toHex(bytes) {
|
|
1893
|
+
let s = "";
|
|
1894
|
+
for (const b of bytes) s += b.toString(16).padStart(2, "0");
|
|
1895
|
+
return s;
|
|
1896
|
+
}
|
|
1897
|
+
function packVersion(version, serType) {
|
|
1898
|
+
if (!Number.isInteger(version) || version < 0 || version > 65535) {
|
|
1899
|
+
throw err(
|
|
1900
|
+
Number.isInteger(version) ? "out-of-range" : "not-an-integer",
|
|
1901
|
+
"tx.version",
|
|
1902
|
+
`expected an integer in 0..2^16-1, got ${shown(version)}`
|
|
1903
|
+
);
|
|
1904
|
+
}
|
|
1905
|
+
if (!Number.isInteger(serType) || serType < 0 || serType > MAX_SERIALIZE_TYPE) {
|
|
1906
|
+
throw err(
|
|
1907
|
+
Number.isInteger(serType) ? "out-of-range" : "not-an-integer",
|
|
1908
|
+
"tx.serializeType",
|
|
1909
|
+
`expected an integer in 0..${MAX_SERIALIZE_TYPE}, got ${shown(serType)}`
|
|
1910
|
+
);
|
|
1911
|
+
}
|
|
1912
|
+
return (serType << 16 | version) >>> 0;
|
|
1913
|
+
}
|
|
1914
|
+
var Transaction = class _Transaction {
|
|
1915
|
+
version = DEFAULT_TX_VERSION;
|
|
1916
|
+
inputs = [];
|
|
1917
|
+
outputs = [];
|
|
1918
|
+
lockTime = 0;
|
|
1919
|
+
expiry = 0;
|
|
1920
|
+
/**
|
|
1921
|
+
* Add an input. Witness fields default to the "unsigned/unknown" sentinels.
|
|
1922
|
+
*
|
|
1923
|
+
* The outpoint and signature script are copied, so a caller that reuses or
|
|
1924
|
+
* scrubs its own buffers afterwards cannot silently rewrite this transaction's
|
|
1925
|
+
* bytes — which would change its txid and invalidate every signature already
|
|
1926
|
+
* computed over it, with nothing to detect the change.
|
|
1927
|
+
*/
|
|
1928
|
+
addInput(previousOutPoint, opts = {}) {
|
|
1929
|
+
if (previousOutPoint === null || typeof previousOutPoint !== "object") {
|
|
1930
|
+
throw err(
|
|
1931
|
+
"invalid-argument",
|
|
1932
|
+
"tx.addInput",
|
|
1933
|
+
`outpoint must be an object, got ${typeName(previousOutPoint)}`
|
|
1934
|
+
);
|
|
1935
|
+
}
|
|
1936
|
+
if (!isBytes(previousOutPoint.hash)) {
|
|
1937
|
+
throw err(
|
|
1938
|
+
"invalid-argument",
|
|
1939
|
+
"tx.addInput",
|
|
1940
|
+
`outpoint hash must be a Uint8Array, got ${typeName(previousOutPoint.hash)}`
|
|
1941
|
+
);
|
|
1942
|
+
}
|
|
1943
|
+
if (previousOutPoint.hash.length !== 32) {
|
|
1944
|
+
throw err(
|
|
1945
|
+
"bad-length",
|
|
1946
|
+
"tx.addInput",
|
|
1947
|
+
`outpoint hash must be 32 bytes, got ${previousOutPoint.hash.length}`
|
|
1948
|
+
);
|
|
1949
|
+
}
|
|
1950
|
+
if (previousOutPoint.tree !== 0 /* Regular */ && previousOutPoint.tree !== 1 /* Stake */) {
|
|
1951
|
+
throw err(
|
|
1952
|
+
"out-of-range",
|
|
1953
|
+
"tx.addInput",
|
|
1954
|
+
`outpoint tree must be ${0 /* Regular */} (regular) or ${1 /* Stake */} (stake), got ${shown(previousOutPoint.tree)}`
|
|
1955
|
+
);
|
|
1956
|
+
}
|
|
1957
|
+
this.inputs.push({
|
|
1958
|
+
previousOutPoint: {
|
|
1959
|
+
hash: copyOf(previousOutPoint.hash, 0, 32),
|
|
1960
|
+
index: previousOutPoint.index,
|
|
1961
|
+
tree: previousOutPoint.tree
|
|
1962
|
+
},
|
|
1963
|
+
sequence: opts.sequence ?? MAX_SEQUENCE,
|
|
1964
|
+
valueIn: opts.valueIn ?? NULL_VALUE_IN,
|
|
1965
|
+
blockHeight: opts.blockHeight ?? NULL_BLOCK_HEIGHT,
|
|
1966
|
+
blockIndex: opts.blockIndex ?? NULL_BLOCK_INDEX,
|
|
1967
|
+
signatureScript: opts.signatureScript ? copyOf(opts.signatureScript, 0, opts.signatureScript.length) : new Uint8Array(0)
|
|
1968
|
+
});
|
|
1969
|
+
return this;
|
|
1970
|
+
}
|
|
1971
|
+
/** Add an output. The script is copied; see {@link addInput}. */
|
|
1972
|
+
addOutput(value, pkScript, version = 0) {
|
|
1973
|
+
if (!isBytes(pkScript)) {
|
|
1974
|
+
throw err(
|
|
1975
|
+
"invalid-argument",
|
|
1976
|
+
"tx.addOutput",
|
|
1977
|
+
`pkScript must be a Uint8Array, got ${typeName(pkScript)}`
|
|
1978
|
+
);
|
|
1979
|
+
}
|
|
1980
|
+
this.outputs.push({ value, version, pkScript: copyOf(pkScript, 0, pkScript.length) });
|
|
1981
|
+
return this;
|
|
1982
|
+
}
|
|
1983
|
+
writeVersion(w, serType) {
|
|
1984
|
+
w.u32(packVersion(this.version, serType));
|
|
1985
|
+
}
|
|
1986
|
+
writePrefixBody(w) {
|
|
1987
|
+
w.varInt(this.inputs.length);
|
|
1988
|
+
for (const input of this.inputs) {
|
|
1989
|
+
const op = input.previousOutPoint;
|
|
1990
|
+
if (op.hash.length !== 32) throw err("bad-length", "tx", `outpoint hash must be 32 bytes, got ${op.hash.length}`);
|
|
1991
|
+
w.bytes(op.hash).u32(op.index).u8(op.tree).u32(input.sequence);
|
|
1992
|
+
}
|
|
1993
|
+
w.varInt(this.outputs.length);
|
|
1994
|
+
for (const out of this.outputs) {
|
|
1995
|
+
w.i64(out.value).u16(out.version).varBytes(out.pkScript);
|
|
1996
|
+
}
|
|
1997
|
+
w.u32(this.lockTime).u32(this.expiry);
|
|
1998
|
+
}
|
|
1999
|
+
writeWitnessBody(w) {
|
|
2000
|
+
w.varInt(this.inputs.length);
|
|
2001
|
+
for (const input of this.inputs) {
|
|
2002
|
+
w.i64(input.valueIn).u32(input.blockHeight).u32(input.blockIndex).varBytes(input.signatureScript);
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
/** Serialize as prefix ‖ witness (the full form). */
|
|
2006
|
+
serialize() {
|
|
2007
|
+
const w = new Writer();
|
|
2008
|
+
this.writeVersion(w, 0 /* Full */);
|
|
2009
|
+
this.writePrefixBody(w);
|
|
2010
|
+
this.writeWitnessBody(w);
|
|
2011
|
+
return w.finish();
|
|
2012
|
+
}
|
|
2013
|
+
/** Serialize the prefix only (no witness). This is what the txid hashes. */
|
|
2014
|
+
serializePrefix() {
|
|
2015
|
+
const w = new Writer();
|
|
2016
|
+
this.writeVersion(w, 1 /* NoWitness */);
|
|
2017
|
+
this.writePrefixBody(w);
|
|
2018
|
+
return w.finish();
|
|
2019
|
+
}
|
|
2020
|
+
/** Serialize the witness only. */
|
|
2021
|
+
serializeWitness() {
|
|
2022
|
+
const w = new Writer();
|
|
2023
|
+
this.writeVersion(w, 2 /* OnlyWitness */);
|
|
2024
|
+
this.writeWitnessBody(w);
|
|
2025
|
+
return w.finish();
|
|
2026
|
+
}
|
|
2027
|
+
/** Raw 32-byte prefix hash (internal byte order). */
|
|
2028
|
+
hash() {
|
|
2029
|
+
return blake256(this.serializePrefix());
|
|
2030
|
+
}
|
|
2031
|
+
/** The transaction id (reversed-hex display form of the prefix hash). */
|
|
2032
|
+
txid() {
|
|
2033
|
+
return toHex(reverse(this.hash()));
|
|
2034
|
+
}
|
|
2035
|
+
/** The witness hash id (display form). */
|
|
2036
|
+
witnessTxid() {
|
|
2037
|
+
return toHex(reverse(blake256(this.serializeWitness())));
|
|
2038
|
+
}
|
|
2039
|
+
/** The full hash id: `blake256(prefixHash ‖ witnessHash)`, display form. */
|
|
2040
|
+
fullTxid() {
|
|
2041
|
+
const concat = new Uint8Array(64);
|
|
2042
|
+
concat.set(blake256(this.serializePrefix()), 0);
|
|
2043
|
+
concat.set(blake256(this.serializeWitness()), 32);
|
|
2044
|
+
return toHex(reverse(blake256(concat)));
|
|
2045
|
+
}
|
|
2046
|
+
/**
|
|
2047
|
+
* Parse a full (prefix ‖ witness) serialization.
|
|
2048
|
+
*
|
|
2049
|
+
* The declared input and output counts are deliberately **not** capped, where
|
|
2050
|
+
* dcrd's `decodePrefix` and `decodeWitness` reject anything above
|
|
2051
|
+
* `maxTxInPerMessage` (780336) or `maxTxOutPerMessage` (3728271) — the counts
|
|
2052
|
+
* that could fit a 32 MiB `MaxMessagePayload`. Those bounds exist because dcrd
|
|
2053
|
+
* decodes from an `io.Reader` of unknown length and sizes `make([]TxIn, count)`
|
|
2054
|
+
* from the count *before* reading an input; here the argument is a `Uint8Array`
|
|
2055
|
+
* whose length is already the bound, and nothing is sized from a count —
|
|
2056
|
+
* `Reader` checks every read against the bytes that remain, so an inflated
|
|
2057
|
+
* count fails at the first short read having allocated nothing. The only
|
|
2058
|
+
* observable difference is that a blob of ~43 MiB or larger declaring more than
|
|
2059
|
+
* 780336 inputs parses here and does not in dcrd; such a transaction is neither
|
|
2060
|
+
* relayable (over `MaxMessagePayload`) nor valid (mainnet `MaxTxSize` is 393216
|
|
2061
|
+
* bytes, 115x smaller). On a *truncated* blob both reject, only with different
|
|
2062
|
+
* errors: dcrd's `ErrTooManyTxs` against this library's `unexpected-end`.
|
|
2063
|
+
*
|
|
2064
|
+
* Cost is still linear in `bytes.length`, so cap the size of untrusted input at
|
|
2065
|
+
* the call site. dcrd's count limits would not help with that: 32 MiB holds
|
|
2066
|
+
* 818400 minimal prefix inputs and the cap is 780336, so a buffer at the wire
|
|
2067
|
+
* maximum stays under it.
|
|
2068
|
+
*/
|
|
2069
|
+
static fromBytes(bytes) {
|
|
2070
|
+
const r = new Reader(bytes);
|
|
2071
|
+
const versionWord = r.u32();
|
|
2072
|
+
const serType = versionWord >>> 16;
|
|
2073
|
+
if (serType !== 0 /* Full */) {
|
|
2074
|
+
throw err("invalid-argument", "tx.fromBytes", `expects the full serialization, got serialization type ${serType}`);
|
|
2075
|
+
}
|
|
2076
|
+
const tx = new _Transaction();
|
|
2077
|
+
tx.version = versionWord & 65535;
|
|
2078
|
+
const numIn = r.varInt();
|
|
2079
|
+
const prefixes = [];
|
|
2080
|
+
const sequences = [];
|
|
2081
|
+
for (let i = 0; i < numIn; i++) {
|
|
2082
|
+
const hash = r.bytes(32);
|
|
2083
|
+
const index = r.u32();
|
|
2084
|
+
const tree = r.u8();
|
|
2085
|
+
const sequence = r.u32();
|
|
2086
|
+
prefixes.push({ hash, index, tree });
|
|
2087
|
+
sequences.push(sequence);
|
|
2088
|
+
}
|
|
2089
|
+
const numOut = r.varInt();
|
|
2090
|
+
for (let i = 0; i < numOut; i++) {
|
|
2091
|
+
const value = r.i64();
|
|
2092
|
+
const version = r.u16();
|
|
2093
|
+
const pkScript = r.varBytes();
|
|
2094
|
+
tx.outputs.push({ value, version, pkScript });
|
|
2095
|
+
}
|
|
2096
|
+
tx.lockTime = r.u32();
|
|
2097
|
+
tx.expiry = r.u32();
|
|
2098
|
+
const numWit = r.varInt();
|
|
2099
|
+
if (numWit !== numIn) throw err("bad-length", "tx.fromBytes", `witness declares ${numWit} inputs, prefix declares ${numIn}`);
|
|
2100
|
+
for (let i = 0; i < numIn; i++) {
|
|
2101
|
+
const valueIn = r.i64();
|
|
2102
|
+
const blockHeight = r.u32();
|
|
2103
|
+
const blockIndex = r.u32();
|
|
2104
|
+
const signatureScript2 = r.varBytes();
|
|
2105
|
+
tx.inputs.push({
|
|
2106
|
+
previousOutPoint: prefixes[i],
|
|
2107
|
+
sequence: sequences[i],
|
|
2108
|
+
valueIn,
|
|
2109
|
+
blockHeight,
|
|
2110
|
+
blockIndex,
|
|
2111
|
+
signatureScript: signatureScript2
|
|
2112
|
+
});
|
|
2113
|
+
}
|
|
2114
|
+
if (r.remaining !== 0) throw err("trailing-bytes", "tx.fromBytes", `${r.remaining} byte(s) remain after the transaction`);
|
|
2115
|
+
return tx;
|
|
2116
|
+
}
|
|
2117
|
+
};
|
|
2118
|
+
function outPointFromTxid(txid, index, tree = 0 /* Regular */) {
|
|
2119
|
+
if (!/^[0-9a-fA-F]{64}$/.test(txid)) {
|
|
2120
|
+
throw err("invalid-argument", "outPointFromTxid", "txid must be 64 hex characters");
|
|
2121
|
+
}
|
|
2122
|
+
const display = new Uint8Array(32);
|
|
2123
|
+
for (let i = 0; i < 32; i++) display[i] = parseInt(txid.slice(i * 2, i * 2 + 2), 16);
|
|
2124
|
+
return { hash: reverse(display), index, tree };
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
// src/sighash.ts
|
|
2128
|
+
var SigHashType = /* @__PURE__ */ ((SigHashType2) => {
|
|
2129
|
+
SigHashType2[SigHashType2["All"] = 1] = "All";
|
|
2130
|
+
SigHashType2[SigHashType2["None"] = 2] = "None";
|
|
2131
|
+
SigHashType2[SigHashType2["Single"] = 3] = "Single";
|
|
2132
|
+
SigHashType2[SigHashType2["AnyOneCanPay"] = 128] = "AnyOneCanPay";
|
|
2133
|
+
return SigHashType2;
|
|
2134
|
+
})(SigHashType || {});
|
|
2135
|
+
var SIG_HASH_MASK = 31;
|
|
2136
|
+
var SIG_HASH_SERIALIZE_PREFIX = 1;
|
|
2137
|
+
var SIG_HASH_SERIALIZE_WITNESS = 3;
|
|
2138
|
+
function isSignableSigHashType(hashType) {
|
|
2139
|
+
if (!Number.isInteger(hashType) || hashType < 0 || hashType > 255) return false;
|
|
2140
|
+
const masked = hashType & 127;
|
|
2141
|
+
return masked >= 1 /* All */ && masked <= 3 /* Single */;
|
|
2142
|
+
}
|
|
2143
|
+
function assertSignableSigHashType(hashType) {
|
|
2144
|
+
if (!isSignableSigHashType(hashType)) {
|
|
2145
|
+
const label = Number.isInteger(hashType) ? `0x${Number(hashType).toString(16)}` : shown(hashType);
|
|
2146
|
+
throw err(
|
|
2147
|
+
"invalid-hash-type",
|
|
2148
|
+
"sighash",
|
|
2149
|
+
`hash type ${label} is not one dcrd accepts (All/None/Single, optionally |AnyOneCanPay)`
|
|
2150
|
+
);
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
function sigHashPrefixAll(tx) {
|
|
2154
|
+
return tx.hash();
|
|
2155
|
+
}
|
|
2156
|
+
function calcSignatureHash(subScript, hashType, tx, idx, cachedPrefix) {
|
|
2157
|
+
if (!Number.isInteger(hashType) || hashType < 0 || hashType > 255) {
|
|
2158
|
+
throw err("invalid-hash-type", "sighash", `hash type must be a byte (0..255), got ${shown(hashType)}`);
|
|
2159
|
+
}
|
|
2160
|
+
if (!Number.isInteger(idx)) {
|
|
2161
|
+
throw err("not-an-integer", "sighash", `input index must be an integer, got ${shown(idx)}`);
|
|
2162
|
+
}
|
|
2163
|
+
const masked = hashType & SIG_HASH_MASK;
|
|
2164
|
+
const anyoneCanPay = (hashType & 128 /* AnyOneCanPay */) !== 0;
|
|
2165
|
+
if (!scriptParses(subScript)) {
|
|
2166
|
+
throw err("malformed-script", "sighash", "subScript does not tokenize (malformed data push)");
|
|
2167
|
+
}
|
|
2168
|
+
if (masked === 3 /* Single */ && idx >= tx.outputs.length) {
|
|
2169
|
+
throw err(
|
|
2170
|
+
"out-of-range",
|
|
2171
|
+
"sighash",
|
|
2172
|
+
`SigHashSingle input ${idx} has no corresponding output`
|
|
2173
|
+
);
|
|
2174
|
+
}
|
|
2175
|
+
if (idx < 0 || idx >= tx.inputs.length) {
|
|
2176
|
+
throw err("out-of-range", "sighash", `input index ${idx} out of range`);
|
|
2177
|
+
}
|
|
2178
|
+
const inputs = anyoneCanPay ? [tx.inputs[idx]] : tx.inputs;
|
|
2179
|
+
const signInIdx = anyoneCanPay ? 0 : idx;
|
|
2180
|
+
const prefixIsInputIndependent = masked === 1 /* All */ && !anyoneCanPay;
|
|
2181
|
+
let prefixHash;
|
|
2182
|
+
if (cachedPrefix !== void 0 && prefixIsInputIndependent) {
|
|
2183
|
+
if (cachedPrefix.length !== 32) {
|
|
2184
|
+
throw err("bad-length", "sighash", `cachedPrefix must be 32 bytes, got ${cachedPrefix.length}`);
|
|
2185
|
+
}
|
|
2186
|
+
prefixHash = cachedPrefix;
|
|
2187
|
+
} else {
|
|
2188
|
+
const pw = new Writer();
|
|
2189
|
+
pw.u32(packVersion(tx.version, SIG_HASH_SERIALIZE_PREFIX));
|
|
2190
|
+
pw.varInt(inputs.length);
|
|
2191
|
+
for (let i = 0; i < inputs.length; i++) {
|
|
2192
|
+
const input = inputs[i];
|
|
2193
|
+
const op = input.previousOutPoint;
|
|
2194
|
+
pw.bytes(op.hash).u32(op.index).u8(op.tree);
|
|
2195
|
+
let sequence = input.sequence;
|
|
2196
|
+
if ((masked === 2 /* None */ || masked === 3 /* Single */) && i !== signInIdx) {
|
|
2197
|
+
sequence = 0;
|
|
2198
|
+
}
|
|
2199
|
+
pw.u32(sequence);
|
|
2200
|
+
}
|
|
2201
|
+
let outputs = tx.outputs;
|
|
2202
|
+
if (masked === 2 /* None */) outputs = [];
|
|
2203
|
+
else if (masked === 3 /* Single */) outputs = tx.outputs.slice(0, idx + 1);
|
|
2204
|
+
pw.varInt(outputs.length);
|
|
2205
|
+
for (let i = 0; i < outputs.length; i++) {
|
|
2206
|
+
const out = outputs[i];
|
|
2207
|
+
if (masked === 3 /* Single */ && i !== idx) {
|
|
2208
|
+
pw.i64(-1n).u16(out.version).varInt(0);
|
|
2209
|
+
} else {
|
|
2210
|
+
pw.i64(out.value).u16(out.version).varBytes(out.pkScript);
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
pw.u32(tx.lockTime).u32(tx.expiry);
|
|
2214
|
+
prefixHash = blake256(pw.finish());
|
|
2215
|
+
}
|
|
2216
|
+
const ww = new Writer();
|
|
2217
|
+
ww.u32(packVersion(tx.version, SIG_HASH_SERIALIZE_WITNESS));
|
|
2218
|
+
ww.varInt(inputs.length);
|
|
2219
|
+
for (let i = 0; i < inputs.length; i++) {
|
|
2220
|
+
if (i === signInIdx) ww.varBytes(subScript);
|
|
2221
|
+
else ww.varInt(0);
|
|
2222
|
+
}
|
|
2223
|
+
const witnessHash = blake256(ww.finish());
|
|
2224
|
+
const fw = new Writer();
|
|
2225
|
+
fw.u32(hashType >>> 0).bytes(prefixHash).bytes(witnessHash);
|
|
2226
|
+
return blake256(fw.finish());
|
|
2227
|
+
}
|
|
2228
|
+
function assertHash32(hash, who) {
|
|
2229
|
+
if (!isBytes(hash)) {
|
|
2230
|
+
throw err("invalid-argument", who, "signature hash must be a Uint8Array");
|
|
2231
|
+
}
|
|
2232
|
+
if (hash.length !== 32) {
|
|
2233
|
+
throw err("bad-length", who, `signature hash must be 32 bytes, got ${hash.length}`);
|
|
2234
|
+
}
|
|
2235
|
+
}
|
|
2236
|
+
function signHash(hash, privateKey) {
|
|
2237
|
+
assertHash32(hash, "signHash");
|
|
2238
|
+
assertPrivateKey(privateKey, "signHash");
|
|
2239
|
+
const sig = secp256k1.secp256k1.sign(hash, privateKey, { lowS: true });
|
|
2240
|
+
return sig.toDERRawBytes();
|
|
2241
|
+
}
|
|
2242
|
+
function verifyHash(hash, derSignature, publicKey) {
|
|
2243
|
+
assertHash32(hash, "verifyHash");
|
|
2244
|
+
try {
|
|
2245
|
+
const sig = secp256k1.secp256k1.Signature.fromDER(derSignature);
|
|
2246
|
+
const canonical = sig.toDERRawBytes();
|
|
2247
|
+
if (canonical.length !== derSignature.length) return false;
|
|
2248
|
+
for (let i = 0; i < canonical.length; i++) {
|
|
2249
|
+
if (canonical[i] !== derSignature[i]) return false;
|
|
2250
|
+
}
|
|
2251
|
+
if (sig.hasHighS()) return false;
|
|
2252
|
+
return secp256k1.secp256k1.verify(sig.toCompactRawBytes(), hash, publicKey, { lowS: true });
|
|
2253
|
+
} catch {
|
|
2254
|
+
return false;
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
function rawTxInSignature(tx, idx, subScript, hashType, privateKey, cachedPrefix) {
|
|
2258
|
+
assertSignableSigHashType(hashType);
|
|
2259
|
+
const hash = calcSignatureHash(subScript, hashType, tx, idx, cachedPrefix);
|
|
2260
|
+
const der = signHash(hash, privateKey);
|
|
2261
|
+
const out = new Uint8Array(der.length + 1);
|
|
2262
|
+
out.set(der);
|
|
2263
|
+
out[der.length] = hashType & 255;
|
|
2264
|
+
return out;
|
|
2265
|
+
}
|
|
2266
|
+
function signatureScript(tx, idx, subScript, hashType, privateKey, compressed = true, cachedPrefix) {
|
|
2267
|
+
const rawSig = rawTxInSignature(tx, idx, subScript, hashType, privateKey, cachedPrefix);
|
|
2268
|
+
const pubKey = publicKeyFromPrivate(privateKey, compressed);
|
|
2269
|
+
const a = pushData(rawSig);
|
|
2270
|
+
const b = pushData(pubKey);
|
|
2271
|
+
const out = new Uint8Array(a.length + b.length);
|
|
2272
|
+
out.set(a);
|
|
2273
|
+
out.set(b, a.length);
|
|
2274
|
+
return out;
|
|
2275
|
+
}
|
|
2276
|
+
function signP2PKHInput(tx, idx, subScript, privateKey, hashType = 1 /* All */, compressed = true) {
|
|
2277
|
+
tx.inputs[idx].signatureScript = signatureScript(
|
|
2278
|
+
tx,
|
|
2279
|
+
idx,
|
|
2280
|
+
subScript,
|
|
2281
|
+
hashType,
|
|
2282
|
+
privateKey,
|
|
2283
|
+
compressed
|
|
2284
|
+
);
|
|
2285
|
+
return tx;
|
|
2286
|
+
}
|
|
2287
|
+
function signP2PKHInputs(tx, toSign, hashType = 1 /* All */) {
|
|
2288
|
+
assertSignableSigHashType(hashType);
|
|
2289
|
+
const cachedPrefix = sigHashPrefixAll(tx);
|
|
2290
|
+
for (const { idx, subScript, privateKey, compressed = true } of toSign) {
|
|
2291
|
+
tx.inputs[idx].signatureScript = signatureScript(
|
|
2292
|
+
tx,
|
|
2293
|
+
idx,
|
|
2294
|
+
subScript,
|
|
2295
|
+
hashType,
|
|
2296
|
+
privateKey,
|
|
2297
|
+
compressed,
|
|
2298
|
+
cachedPrefix
|
|
2299
|
+
);
|
|
2300
|
+
}
|
|
2301
|
+
return tx;
|
|
2302
|
+
}
|
|
2303
|
+
|
|
2304
|
+
// src/amount.ts
|
|
2305
|
+
var ATOMS_PER_COIN = 100000000n;
|
|
2306
|
+
var COIN_DECIMALS = 8;
|
|
2307
|
+
function dcrToAtoms(dcr) {
|
|
2308
|
+
const s = dcr.trim();
|
|
2309
|
+
if (!/^-?\d+(\.\d+)?$/.test(s)) throw err("invalid-amount", "dcrToAtoms", `cannot parse ${shown(dcr)}`);
|
|
2310
|
+
const negative = s.startsWith("-");
|
|
2311
|
+
const body = negative ? s.slice(1) : s;
|
|
2312
|
+
const [intPart = "0", fracPart = ""] = body.split(".");
|
|
2313
|
+
if (fracPart.length > COIN_DECIMALS) {
|
|
2314
|
+
throw err("invalid-amount", "dcrToAtoms", `more than ${COIN_DECIMALS} decimal places`);
|
|
2315
|
+
}
|
|
2316
|
+
const frac = (fracPart + "00000000").slice(0, COIN_DECIMALS);
|
|
2317
|
+
const atoms = BigInt(intPart) * ATOMS_PER_COIN + BigInt(frac);
|
|
2318
|
+
return negative ? -atoms : atoms;
|
|
2319
|
+
}
|
|
2320
|
+
function atomsToDcr(atoms) {
|
|
2321
|
+
const negative = atoms < 0n;
|
|
2322
|
+
const a = negative ? -atoms : atoms;
|
|
2323
|
+
const intPart = a / ATOMS_PER_COIN;
|
|
2324
|
+
const frac = (a % ATOMS_PER_COIN).toString().padStart(COIN_DECIMALS, "0");
|
|
2325
|
+
return `${negative ? "-" : ""}${intPart.toString()}.${frac}`;
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2328
|
+
exports.ATOMS_PER_COIN = ATOMS_PER_COIN;
|
|
2329
|
+
exports.BLAKE256_BLOCK_LENGTH = BLAKE256_BLOCK_LENGTH;
|
|
2330
|
+
exports.BLAKE256_DIGEST_LENGTH = BLAKE256_DIGEST_LENGTH;
|
|
2331
|
+
exports.Blake256 = Blake256;
|
|
2332
|
+
exports.COIN_DECIMALS = COIN_DECIMALS;
|
|
2333
|
+
exports.CURVE_ORDER = CURVE_ORDER;
|
|
2334
|
+
exports.DEFAULT_TX_VERSION = DEFAULT_TX_VERSION;
|
|
2335
|
+
exports.DcrError = DcrError;
|
|
2336
|
+
exports.ExtendedKey = ExtendedKey;
|
|
2337
|
+
exports.HARDENED_OFFSET = HARDENED_OFFSET;
|
|
2338
|
+
exports.MAX_ADDRESS_LENGTH = MAX_ADDRESS_LENGTH;
|
|
2339
|
+
exports.MAX_EXTENDED_KEY_LENGTH = MAX_EXTENDED_KEY_LENGTH;
|
|
2340
|
+
exports.MAX_SCRIPT_ELEMENT_SIZE = MAX_SCRIPT_ELEMENT_SIZE;
|
|
2341
|
+
exports.MAX_SEQUENCE = MAX_SEQUENCE;
|
|
2342
|
+
exports.MAX_WIF_LENGTH = MAX_WIF_LENGTH;
|
|
2343
|
+
exports.NULL_BLOCK_HEIGHT = NULL_BLOCK_HEIGHT;
|
|
2344
|
+
exports.NULL_BLOCK_INDEX = NULL_BLOCK_INDEX;
|
|
2345
|
+
exports.NULL_VALUE_IN = NULL_VALUE_IN;
|
|
2346
|
+
exports.OP = OP;
|
|
2347
|
+
exports.Reader = Reader;
|
|
2348
|
+
exports.SigHashType = SigHashType;
|
|
2349
|
+
exports.SignatureType = SignatureType;
|
|
2350
|
+
exports.Transaction = Transaction;
|
|
2351
|
+
exports.TxSerializeType = TxSerializeType;
|
|
2352
|
+
exports.TxTree = TxTree;
|
|
2353
|
+
exports.Writer = Writer;
|
|
2354
|
+
exports.addressFromPubKey = addressFromPubKey;
|
|
2355
|
+
exports.addressFromScript = addressFromScript;
|
|
2356
|
+
exports.addressToScript = addressToScript;
|
|
2357
|
+
exports.assertCompressedPubKey = assertCompressedPubKey;
|
|
2358
|
+
exports.assertPrivateKey = assertPrivateKey;
|
|
2359
|
+
exports.assertPubKey = assertPubKey;
|
|
2360
|
+
exports.assertSignableSigHashType = assertSignableSigHashType;
|
|
2361
|
+
exports.atomsToDcr = atomsToDcr;
|
|
2362
|
+
exports.base58Decode = base58Decode;
|
|
2363
|
+
exports.base58Encode = base58Encode;
|
|
2364
|
+
exports.blake256 = blake256;
|
|
2365
|
+
exports.calcSignatureHash = calcSignatureHash;
|
|
2366
|
+
exports.checkDecode = checkDecode;
|
|
2367
|
+
exports.checkEncode = checkEncode;
|
|
2368
|
+
exports.classifyScript = classifyScript;
|
|
2369
|
+
exports.copyOf = copyOf;
|
|
2370
|
+
exports.dcrToAtoms = dcrToAtoms;
|
|
2371
|
+
exports.decodeAddress = decodeAddress;
|
|
2372
|
+
exports.decodeWif = decodeWif;
|
|
2373
|
+
exports.encodeWif = encodeWif;
|
|
2374
|
+
exports.englishWordlist = englishWordlist;
|
|
2375
|
+
exports.entropyToMnemonic = entropyToMnemonic;
|
|
2376
|
+
exports.extractHash160 = extractHash160;
|
|
2377
|
+
exports.generateMnemonic = generateMnemonic;
|
|
2378
|
+
exports.hardened = hardened;
|
|
2379
|
+
exports.hasErrorCode = hasErrorCode;
|
|
2380
|
+
exports.hash160 = hash160;
|
|
2381
|
+
exports.hash256 = hash256;
|
|
2382
|
+
exports.isDcrError = isDcrError;
|
|
2383
|
+
exports.isPayToPubKeyHash = isPayToPubKeyHash;
|
|
2384
|
+
exports.isPayToScriptHash = isPayToScriptHash;
|
|
2385
|
+
exports.isSignableSigHashType = isSignableSigHashType;
|
|
2386
|
+
exports.isValidAddress = isValidAddress;
|
|
2387
|
+
exports.isValidEd25519PublicKey = isValidEd25519PublicKey;
|
|
2388
|
+
exports.isValidPrivateKey = isValidPrivateKey;
|
|
2389
|
+
exports.isValidPublicKey = isValidPublicKey;
|
|
2390
|
+
exports.mainnet = mainnet;
|
|
2391
|
+
exports.maxBase58Length = maxBase58Length;
|
|
2392
|
+
exports.mnemonicToEntropy = mnemonicToEntropy;
|
|
2393
|
+
exports.mnemonicToMasterKey = mnemonicToMasterKey;
|
|
2394
|
+
exports.mnemonicToSeed = mnemonicToSeed;
|
|
2395
|
+
exports.networks = networks;
|
|
2396
|
+
exports.outPointFromTxid = outPointFromTxid;
|
|
2397
|
+
exports.payToPubKeyAltScript = payToPubKeyAltScript;
|
|
2398
|
+
exports.payToPubKeyHashAltScript = payToPubKeyHashAltScript;
|
|
2399
|
+
exports.payToPubKeyHashScript = payToPubKeyHashScript;
|
|
2400
|
+
exports.payToPubKeyScript = payToPubKeyScript;
|
|
2401
|
+
exports.payToScriptHashScript = payToScriptHashScript;
|
|
2402
|
+
exports.pubKeyAddress = pubKeyAddress;
|
|
2403
|
+
exports.pubKeyEd25519Address = pubKeyEd25519Address;
|
|
2404
|
+
exports.pubKeyHashAddress = pubKeyHashAddress;
|
|
2405
|
+
exports.pubKeyHashEd25519Address = pubKeyHashEd25519Address;
|
|
2406
|
+
exports.pubKeyHashSchnorrAddress = pubKeyHashSchnorrAddress;
|
|
2407
|
+
exports.pubKeySchnorrAddress = pubKeySchnorrAddress;
|
|
2408
|
+
exports.publicKeyFromPrivate = publicKeyFromPrivate;
|
|
2409
|
+
exports.pushData = pushData;
|
|
2410
|
+
exports.rawTxInSignature = rawTxInSignature;
|
|
2411
|
+
exports.regnet = regnet;
|
|
2412
|
+
exports.scriptHashAddress = scriptHashAddress;
|
|
2413
|
+
exports.scriptParses = scriptParses;
|
|
2414
|
+
exports.sigHashPrefixAll = sigHashPrefixAll;
|
|
2415
|
+
exports.signHash = signHash;
|
|
2416
|
+
exports.signP2PKHInput = signP2PKHInput;
|
|
2417
|
+
exports.signP2PKHInputs = signP2PKHInputs;
|
|
2418
|
+
exports.signatureScript = signatureScript;
|
|
2419
|
+
exports.simnet = simnet;
|
|
2420
|
+
exports.testnet3 = testnet3;
|
|
2421
|
+
exports.validateMnemonic = validateMnemonic;
|
|
2422
|
+
exports.verifyHash = verifyHash;
|
|
2423
|
+
//# sourceMappingURL=index.cjs.map
|
|
2424
|
+
//# sourceMappingURL=index.cjs.map
|