@qntx/wallet-worker 0.2.0 → 0.3.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/README.md +27 -8
- package/dist/browser-gx857d3g.js +199 -0
- package/dist/browser.mjs +55 -25
- package/dist/browser.mjs.map +1 -1
- package/dist/index-cgstn3zw.js +26 -0
- package/dist/kernel.manifest.json +108 -0
- package/dist/kernel.node.js +7128 -8536
- package/dist/kernel.worker.js +7035 -8310
- package/dist/node-30nrftxx.js +23 -0
- package/dist/node-7sztn879.js +4446 -0
- package/dist/node-nhrchcf5.js +3979 -0
- package/dist/node.d.mts +3 -1
- package/dist/node.mjs +96 -24
- package/dist/node.mjs.map +1 -1
- package/dist/signer-tgawen1v.js +6459 -0
- package/dist/spark.wasm +0 -0
- package/dist/worker-30nrftxx.js +23 -0
- package/dist/worker-7sztn879.js +4446 -0
- package/dist/worker-nhrchcf5.js +3979 -0
- package/package.json +16 -11
|
@@ -0,0 +1,4446 @@
|
|
|
1
|
+
import {
|
|
2
|
+
anumber,
|
|
3
|
+
concatBytes,
|
|
4
|
+
sha256,
|
|
5
|
+
abytes2,
|
|
6
|
+
bytesToNumberBE,
|
|
7
|
+
numberToBytesBE,
|
|
8
|
+
validateObject,
|
|
9
|
+
secp256k1,
|
|
10
|
+
schnorr,
|
|
11
|
+
createBase58check,
|
|
12
|
+
bech32,
|
|
13
|
+
bech32m,
|
|
14
|
+
utf8,
|
|
15
|
+
hex,
|
|
16
|
+
ripemd160
|
|
17
|
+
} from "./worker-nhrchcf5.js";
|
|
18
|
+
|
|
19
|
+
// ../../node_modules/.bun/micro-packed@0.11.1/node_modules/micro-packed/index.js
|
|
20
|
+
var EMPTY = /* @__PURE__ */ Uint8Array.of();
|
|
21
|
+
var NULL = /* @__PURE__ */ Uint8Array.of(0);
|
|
22
|
+
var restrictedKeys = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
23
|
+
var validateFieldName = (name, label) => {
|
|
24
|
+
if (typeof name !== "string")
|
|
25
|
+
throw new Error(`${label} should be string, got ${typeof name}`);
|
|
26
|
+
if (name.includes(".."))
|
|
27
|
+
throw new TypeError(`${label} ${name} cannot contain path parent ..`);
|
|
28
|
+
if (name.includes("/"))
|
|
29
|
+
throw new TypeError(`${label} ${name} cannot contain path separator /`);
|
|
30
|
+
if (restrictedKeys.has(name))
|
|
31
|
+
throw new Error(`${label} ${name} is reserved`);
|
|
32
|
+
};
|
|
33
|
+
function equalBytes(a, b) {
|
|
34
|
+
if (a.length !== b.length)
|
|
35
|
+
return false;
|
|
36
|
+
for (let i = 0;i < a.length; i++)
|
|
37
|
+
if (a[i] !== b[i])
|
|
38
|
+
return false;
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
function createFindBytes(needle) {
|
|
42
|
+
if (needle.length === 1) {
|
|
43
|
+
const byte = needle[0];
|
|
44
|
+
return (data, pos = 0) => {
|
|
45
|
+
const idx = data.indexOf(byte, pos);
|
|
46
|
+
return idx === -1 ? undefined : idx;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const back = new Uint32Array(needle.length);
|
|
50
|
+
for (let i = 1, j = 0;i < needle.length; i++) {
|
|
51
|
+
while (j && needle[i] !== needle[j])
|
|
52
|
+
j = back[j - 1];
|
|
53
|
+
if (needle[i] === needle[j])
|
|
54
|
+
back[i] = ++j;
|
|
55
|
+
}
|
|
56
|
+
return (data, pos = 0) => {
|
|
57
|
+
for (let i = pos, j = 0;i < data.length; i++) {
|
|
58
|
+
while (j && data[i] !== needle[j])
|
|
59
|
+
j = back[j - 1];
|
|
60
|
+
if (data[i] !== needle[j])
|
|
61
|
+
continue;
|
|
62
|
+
if (++j === needle.length)
|
|
63
|
+
return i - needle.length + 1;
|
|
64
|
+
}
|
|
65
|
+
return;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
var findBytes = (needle, data, pos = 0) => createFindBytes(needle)(data, pos);
|
|
69
|
+
function equal(a, b) {
|
|
70
|
+
const aBytes = isBytes(a);
|
|
71
|
+
const bBytes = isBytes(b);
|
|
72
|
+
if (aBytes || bBytes)
|
|
73
|
+
return aBytes && bBytes && equalBytes(a, b);
|
|
74
|
+
return a === b;
|
|
75
|
+
}
|
|
76
|
+
function isBytes(a) {
|
|
77
|
+
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1;
|
|
78
|
+
}
|
|
79
|
+
function concatBytes2(...arrays) {
|
|
80
|
+
let sum = 0;
|
|
81
|
+
for (let i = 0;i < arrays.length; i++) {
|
|
82
|
+
const a = arrays[i];
|
|
83
|
+
if (!isBytes(a))
|
|
84
|
+
throw new Error("Uint8Array expected");
|
|
85
|
+
sum += a.length;
|
|
86
|
+
}
|
|
87
|
+
const res = new Uint8Array(sum);
|
|
88
|
+
for (let i = 0, pad = 0;i < arrays.length; i++) {
|
|
89
|
+
const a = arrays[i];
|
|
90
|
+
res.set(a, pad);
|
|
91
|
+
pad += a.length;
|
|
92
|
+
}
|
|
93
|
+
return res;
|
|
94
|
+
}
|
|
95
|
+
var createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
96
|
+
var _0n = /* @__PURE__ */ BigInt(0);
|
|
97
|
+
var _1n = /* @__PURE__ */ BigInt(1);
|
|
98
|
+
var _2n = /* @__PURE__ */ BigInt(2);
|
|
99
|
+
var _8n = /* @__PURE__ */ BigInt(8);
|
|
100
|
+
var _10n = /* @__PURE__ */ BigInt(10);
|
|
101
|
+
var _255n = /* @__PURE__ */ BigInt(255);
|
|
102
|
+
function isPlainObject(obj) {
|
|
103
|
+
return Object.prototype.toString.call(obj) === "[object Object]";
|
|
104
|
+
}
|
|
105
|
+
function isNum(num) {
|
|
106
|
+
return Number.isSafeInteger(num);
|
|
107
|
+
}
|
|
108
|
+
var hasOwn = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
|
|
109
|
+
var utils = /* @__PURE__ */ Object.freeze({
|
|
110
|
+
equalBytes,
|
|
111
|
+
isBytes,
|
|
112
|
+
isCoder,
|
|
113
|
+
checkBounds,
|
|
114
|
+
concatBytes: concatBytes2,
|
|
115
|
+
createView,
|
|
116
|
+
isPlainObject
|
|
117
|
+
});
|
|
118
|
+
var lengthCoder = (len) => {
|
|
119
|
+
if (len !== null && typeof len !== "string" && !isCoder(len) && !isBytes(len) && !isNum(len)) {
|
|
120
|
+
throw new TypeError(`lengthCoder: expected null | number | Uint8Array | CoderType, got ${len} (${typeof len})`);
|
|
121
|
+
}
|
|
122
|
+
if (typeof len === "number" && len < 0)
|
|
123
|
+
throw new Error(`lengthCoder: wrong length=${len}`);
|
|
124
|
+
if (isBytes(len) && !len.length)
|
|
125
|
+
throw new Error("lengthCoder: empty terminator");
|
|
126
|
+
return {
|
|
127
|
+
encodeStream(w, value) {
|
|
128
|
+
if (len === null)
|
|
129
|
+
return;
|
|
130
|
+
if (isCoder(len))
|
|
131
|
+
return len.encodeStream(w, value);
|
|
132
|
+
let byteLen;
|
|
133
|
+
if (typeof len === "number")
|
|
134
|
+
byteLen = len;
|
|
135
|
+
else if (typeof len === "string")
|
|
136
|
+
byteLen = Path.resolve(w.stack, len);
|
|
137
|
+
if (typeof byteLen === "bigint")
|
|
138
|
+
byteLen = Number(byteLen);
|
|
139
|
+
if (!isNum(byteLen) || byteLen < 0 || byteLen !== value)
|
|
140
|
+
throw w.err(`Wrong length: ${byteLen} len=${len} exp=${value} (${typeof value})`);
|
|
141
|
+
},
|
|
142
|
+
decodeStream(r) {
|
|
143
|
+
let byteLen;
|
|
144
|
+
if (isCoder(len))
|
|
145
|
+
byteLen = len.decodeStream(r);
|
|
146
|
+
else if (typeof len === "number")
|
|
147
|
+
byteLen = len;
|
|
148
|
+
else if (typeof len === "string")
|
|
149
|
+
byteLen = Path.resolve(r.stack, len);
|
|
150
|
+
if (typeof byteLen === "bigint")
|
|
151
|
+
byteLen = Number(byteLen);
|
|
152
|
+
else if (typeof byteLen !== "number")
|
|
153
|
+
throw r.err(`Wrong length: ${byteLen}`);
|
|
154
|
+
if (!isNum(byteLen) || byteLen < 0)
|
|
155
|
+
throw r.err(`Wrong length: ${byteLen}`);
|
|
156
|
+
return byteLen;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
var Bitset = /* @__PURE__ */ Object.freeze({
|
|
161
|
+
BITS: 32,
|
|
162
|
+
FULL_MASK: -1 >>> 0,
|
|
163
|
+
len: (len) => {
|
|
164
|
+
if (!isNum(len) || len < 0)
|
|
165
|
+
throw new Error(`wrong len=${len}`);
|
|
166
|
+
return Math.ceil(len / 32);
|
|
167
|
+
},
|
|
168
|
+
create: (len) => new Uint32Array(Bitset.len(len)),
|
|
169
|
+
clean: (bs) => bs.fill(0),
|
|
170
|
+
debug: (bs) => Array.from(bs).map((i) => (i >>> 0).toString(2).padStart(32, "0")),
|
|
171
|
+
checkLen: (bs, len) => {
|
|
172
|
+
if (Bitset.len(len) === bs.length)
|
|
173
|
+
return;
|
|
174
|
+
throw new Error(`wrong length=${bs.length}. Expected: ${Bitset.len(len)}`);
|
|
175
|
+
},
|
|
176
|
+
chunkLen: (bsLen, pos, len) => {
|
|
177
|
+
if (!isNum(bsLen) || bsLen < 0)
|
|
178
|
+
throw new Error(`wrong bsLen=${bsLen}`);
|
|
179
|
+
if (!isNum(pos) || pos < 0)
|
|
180
|
+
throw new Error(`wrong pos=${pos}`);
|
|
181
|
+
if (!isNum(len) || len < 0)
|
|
182
|
+
throw new Error(`wrong len=${len}`);
|
|
183
|
+
if (pos > bsLen - len)
|
|
184
|
+
throw new Error(`wrong range=${pos}/${len} of ${bsLen}`);
|
|
185
|
+
},
|
|
186
|
+
set: (bs, chunk, value, allowRewrite = true) => {
|
|
187
|
+
if (!isNum(chunk) || chunk < 0 || chunk >= bs.length)
|
|
188
|
+
return false;
|
|
189
|
+
if (!allowRewrite && (bs[chunk] & value) !== 0)
|
|
190
|
+
return false;
|
|
191
|
+
bs[chunk] |= value;
|
|
192
|
+
return true;
|
|
193
|
+
},
|
|
194
|
+
pos: (pos, i) => ({
|
|
195
|
+
chunk: Math.floor((pos + i) / 32),
|
|
196
|
+
mask: 1 << 32 - (pos + i) % 32 - 1
|
|
197
|
+
}),
|
|
198
|
+
indices: (bs, len, invert = false) => {
|
|
199
|
+
Bitset.checkLen(bs, len);
|
|
200
|
+
const { FULL_MASK, BITS } = Bitset;
|
|
201
|
+
const left = BITS - len % BITS;
|
|
202
|
+
const lastMask = left ? FULL_MASK >>> left << left : FULL_MASK;
|
|
203
|
+
const res = [];
|
|
204
|
+
for (let i = 0;i < bs.length; i++) {
|
|
205
|
+
let c = bs[i];
|
|
206
|
+
if (invert)
|
|
207
|
+
c = ~c;
|
|
208
|
+
if (i === bs.length - 1)
|
|
209
|
+
c &= lastMask;
|
|
210
|
+
if (c === 0)
|
|
211
|
+
continue;
|
|
212
|
+
for (let j = 0;j < BITS; j++) {
|
|
213
|
+
const m = 1 << BITS - j - 1;
|
|
214
|
+
if (c & m)
|
|
215
|
+
res.push(i * BITS + j);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return res;
|
|
219
|
+
},
|
|
220
|
+
range: (arr) => {
|
|
221
|
+
const res = [];
|
|
222
|
+
let cur;
|
|
223
|
+
for (const i of arr) {
|
|
224
|
+
if (cur === undefined || i !== cur.pos + cur.length)
|
|
225
|
+
res.push(cur = { pos: i, length: 1 });
|
|
226
|
+
else
|
|
227
|
+
cur.length += 1;
|
|
228
|
+
}
|
|
229
|
+
return res;
|
|
230
|
+
},
|
|
231
|
+
rangeDebug: (bs, len, invert = false) => `[${Bitset.range(Bitset.indices(bs, len, invert)).map((i) => `(${i.pos}/${i.length})`).join(", ")}]`,
|
|
232
|
+
setRange: (bs, bsLen, pos, len, allowRewrite = true) => {
|
|
233
|
+
Bitset.chunkLen(bsLen, pos, len);
|
|
234
|
+
if (len === 0)
|
|
235
|
+
return true;
|
|
236
|
+
const { FULL_MASK, BITS } = Bitset;
|
|
237
|
+
const first = pos % BITS ? Math.floor(pos / BITS) : undefined;
|
|
238
|
+
const lastPos = pos + len;
|
|
239
|
+
const last = lastPos % BITS ? Math.floor(lastPos / BITS) : undefined;
|
|
240
|
+
const canSet = (chunk, value) => chunk >= 0 && chunk < bs.length && (bs[chunk] & value) === 0;
|
|
241
|
+
if (!allowRewrite) {
|
|
242
|
+
if (first !== undefined && first === last) {
|
|
243
|
+
if (!canSet(first, FULL_MASK >>> BITS - len << BITS - len - pos))
|
|
244
|
+
return false;
|
|
245
|
+
} else {
|
|
246
|
+
if (first !== undefined && !canSet(first, FULL_MASK >>> pos % BITS))
|
|
247
|
+
return false;
|
|
248
|
+
const start = first !== undefined ? first + 1 : pos / BITS;
|
|
249
|
+
const end = last !== undefined ? last : lastPos / BITS;
|
|
250
|
+
for (let i = start;i < end; i++)
|
|
251
|
+
if (!canSet(i, FULL_MASK))
|
|
252
|
+
return false;
|
|
253
|
+
if (last !== undefined && first !== last) {
|
|
254
|
+
if (!canSet(last, FULL_MASK << BITS - lastPos % BITS))
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (first !== undefined && first === last)
|
|
260
|
+
return Bitset.set(bs, first, FULL_MASK >>> BITS - len << BITS - len - pos, allowRewrite);
|
|
261
|
+
if (first !== undefined) {
|
|
262
|
+
if (!Bitset.set(bs, first, FULL_MASK >>> pos % BITS, allowRewrite))
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
const start = first !== undefined ? first + 1 : pos / BITS;
|
|
266
|
+
const end = last !== undefined ? last : lastPos / BITS;
|
|
267
|
+
for (let i = start;i < end; i++)
|
|
268
|
+
if (!Bitset.set(bs, i, FULL_MASK, allowRewrite))
|
|
269
|
+
return false;
|
|
270
|
+
if (last !== undefined && first !== last) {
|
|
271
|
+
if (!Bitset.set(bs, last, FULL_MASK << BITS - lastPos % BITS, allowRewrite))
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
var Path = /* @__PURE__ */ Object.freeze({
|
|
278
|
+
pushObj: (stack, obj, objFn) => {
|
|
279
|
+
stack.push({ obj });
|
|
280
|
+
objFn();
|
|
281
|
+
stack.pop();
|
|
282
|
+
},
|
|
283
|
+
path: (stack) => {
|
|
284
|
+
const res = [];
|
|
285
|
+
for (const i of stack)
|
|
286
|
+
if (i.field !== undefined)
|
|
287
|
+
res.push(i.field === "" ? '""' : `${i.field}`);
|
|
288
|
+
return res.join("/");
|
|
289
|
+
},
|
|
290
|
+
err: (name, stack, msg) => {
|
|
291
|
+
const text = `${name}(${Path.path(stack)}): ${typeof msg === "string" ? msg : msg.message}`;
|
|
292
|
+
const err = msg instanceof TypeError ? new TypeError(text) : msg instanceof RangeError ? new RangeError(text) : new Error(text);
|
|
293
|
+
if (msg instanceof Error && msg.stack) {
|
|
294
|
+
const from = `${msg.name}: ${msg.message}`;
|
|
295
|
+
const to = `${err.name}: ${err.message}`;
|
|
296
|
+
err.stack = msg.stack.startsWith(from) ? `${to}${msg.stack.slice(from.length)}` : msg.stack;
|
|
297
|
+
}
|
|
298
|
+
return err;
|
|
299
|
+
},
|
|
300
|
+
resolve: (stack, path) => {
|
|
301
|
+
const parts = path.split("/");
|
|
302
|
+
const objPath = stack.map((i) => i.obj);
|
|
303
|
+
let i = 0;
|
|
304
|
+
for (;i < parts.length; i++) {
|
|
305
|
+
if (parts[i] === "..")
|
|
306
|
+
objPath.pop();
|
|
307
|
+
else
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
let cur = objPath.pop();
|
|
311
|
+
for (;i < parts.length; i++) {
|
|
312
|
+
if (!cur || cur[parts[i]] === undefined)
|
|
313
|
+
return;
|
|
314
|
+
cur = cur[parts[i]];
|
|
315
|
+
}
|
|
316
|
+
return cur;
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
class _Reader {
|
|
321
|
+
pos = 0;
|
|
322
|
+
data;
|
|
323
|
+
opts;
|
|
324
|
+
stack;
|
|
325
|
+
parent;
|
|
326
|
+
parentOffset;
|
|
327
|
+
bitBuf = 0;
|
|
328
|
+
bitPos = 0;
|
|
329
|
+
bs;
|
|
330
|
+
view;
|
|
331
|
+
constructor(data, opts = {}, stack = [], parent = undefined, parentOffset = 0) {
|
|
332
|
+
if (!isBytes(data))
|
|
333
|
+
throw new TypeError(`Reader: expected Uint8Array, got ${typeof data}`);
|
|
334
|
+
if (!isPlainObject(opts))
|
|
335
|
+
throw new TypeError(`ReaderOpts: expected plain object, got ${opts}`);
|
|
336
|
+
if (opts.allowUnreadBytes !== undefined && typeof opts.allowUnreadBytes !== "boolean")
|
|
337
|
+
throw new TypeError(`ReaderOpts.allowUnreadBytes: expected boolean, got ${typeof opts.allowUnreadBytes}`);
|
|
338
|
+
if (opts.allowMultipleReads !== undefined && typeof opts.allowMultipleReads !== "boolean")
|
|
339
|
+
throw new TypeError(`ReaderOpts.allowMultipleReads: expected boolean, got ${typeof opts.allowMultipleReads}`);
|
|
340
|
+
this.data = data;
|
|
341
|
+
this.opts = opts;
|
|
342
|
+
this.stack = stack;
|
|
343
|
+
this.parent = parent;
|
|
344
|
+
this.parentOffset = parentOffset;
|
|
345
|
+
this.view = createView(data);
|
|
346
|
+
}
|
|
347
|
+
_enablePointers() {
|
|
348
|
+
if (this.parent)
|
|
349
|
+
return this.parent._enablePointers();
|
|
350
|
+
if (this.bs)
|
|
351
|
+
return;
|
|
352
|
+
this.bs = Bitset.create(this.data.length);
|
|
353
|
+
Bitset.setRange(this.bs, this.data.length, 0, this.pos, this.opts.allowMultipleReads);
|
|
354
|
+
}
|
|
355
|
+
markBytesBS(pos, len) {
|
|
356
|
+
if (this.parent)
|
|
357
|
+
return this.parent.markBytesBS(this.parentOffset + pos, len);
|
|
358
|
+
if (!len)
|
|
359
|
+
return true;
|
|
360
|
+
if (!this.bs)
|
|
361
|
+
return true;
|
|
362
|
+
return Bitset.setRange(this.bs, this.data.length, pos, len, false);
|
|
363
|
+
}
|
|
364
|
+
markBytes(len) {
|
|
365
|
+
const pos = this.pos;
|
|
366
|
+
const res = this.markBytesBS(pos, len);
|
|
367
|
+
if (!this.opts.allowMultipleReads && !res)
|
|
368
|
+
throw this.err(`multiple read pos=${pos} len=${len}`);
|
|
369
|
+
this.pos += len;
|
|
370
|
+
return res;
|
|
371
|
+
}
|
|
372
|
+
pushObj(obj, objFn) {
|
|
373
|
+
return Path.pushObj(this.stack, obj, objFn);
|
|
374
|
+
}
|
|
375
|
+
enterField(field) {
|
|
376
|
+
const last = this.stack[this.stack.length - 1];
|
|
377
|
+
if (last === undefined || last.field !== undefined)
|
|
378
|
+
throw this.err(`enterField: invalid stack state, field=${field}`);
|
|
379
|
+
last.field = field;
|
|
380
|
+
}
|
|
381
|
+
exitField() {
|
|
382
|
+
this.stack[this.stack.length - 1].field = undefined;
|
|
383
|
+
}
|
|
384
|
+
readView(n, fn) {
|
|
385
|
+
if (!isNum(n) || n < 0)
|
|
386
|
+
throw this.err(`readView: wrong length=${n}`);
|
|
387
|
+
if (this.pos + n > this.data.length)
|
|
388
|
+
throw this.err("readView: Unexpected end of buffer");
|
|
389
|
+
const res = fn(this.view, this.pos);
|
|
390
|
+
this.markBytes(n);
|
|
391
|
+
return res;
|
|
392
|
+
}
|
|
393
|
+
absBytes(n) {
|
|
394
|
+
if (!isNum(n) || n < 0 || n > this.data.length)
|
|
395
|
+
throw new Error("Unexpected end of buffer");
|
|
396
|
+
return this.data.subarray(n);
|
|
397
|
+
}
|
|
398
|
+
finish() {
|
|
399
|
+
if (this.opts.allowUnreadBytes)
|
|
400
|
+
return;
|
|
401
|
+
if (this.bitPos) {
|
|
402
|
+
throw this.err(`${this.bitPos} bits left after unpack: ${hex.encode(this.data.subarray(this.pos))}`);
|
|
403
|
+
}
|
|
404
|
+
if (this.bs && !this.parent) {
|
|
405
|
+
const notRead = Bitset.indices(this.bs, this.data.length, true);
|
|
406
|
+
if (notRead.length) {
|
|
407
|
+
const formatted = Bitset.range(notRead).map(({ pos, length }) => `(${pos}/${length})[${hex.encode(this.data.subarray(pos, pos + length))}]`).join(", ");
|
|
408
|
+
throw this.err(`unread byte ranges: ${formatted} (total=${this.data.length})`);
|
|
409
|
+
} else
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (!this.isEnd()) {
|
|
413
|
+
throw this.err(`${this.leftBytes} bytes ${this.bitPos} bits left after unpack: ${hex.encode(this.data.subarray(this.pos))}`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
err(msg) {
|
|
417
|
+
return Path.err("Reader", this.stack, msg);
|
|
418
|
+
}
|
|
419
|
+
offsetReader(n) {
|
|
420
|
+
if (!isNum(n) || n < 0 || n > this.data.length)
|
|
421
|
+
throw this.err("offsetReader: Unexpected end of buffer");
|
|
422
|
+
return new _Reader(this.absBytes(n), this.opts, this.stack, this, n);
|
|
423
|
+
}
|
|
424
|
+
bytes(n, peek = false) {
|
|
425
|
+
if (this.bitPos)
|
|
426
|
+
throw this.err("readBytes: bitPos not empty");
|
|
427
|
+
if (!isNum(n) || n < 0)
|
|
428
|
+
throw this.err(`readBytes: wrong length=${n}`);
|
|
429
|
+
if (this.pos + n > this.data.length)
|
|
430
|
+
throw this.err("readBytes: Unexpected end of buffer");
|
|
431
|
+
const slice = this.data.subarray(this.pos, this.pos + n);
|
|
432
|
+
if (!peek)
|
|
433
|
+
this.markBytes(n);
|
|
434
|
+
return slice;
|
|
435
|
+
}
|
|
436
|
+
byte(peek = false) {
|
|
437
|
+
if (this.bitPos)
|
|
438
|
+
throw this.err("readByte: bitPos not empty");
|
|
439
|
+
if (this.pos + 1 > this.data.length)
|
|
440
|
+
throw this.err("readByte: Unexpected end of buffer");
|
|
441
|
+
const data = this.data[this.pos];
|
|
442
|
+
if (!peek)
|
|
443
|
+
this.markBytes(1);
|
|
444
|
+
return data;
|
|
445
|
+
}
|
|
446
|
+
get leftBytes() {
|
|
447
|
+
return this.data.length - this.pos;
|
|
448
|
+
}
|
|
449
|
+
get totalBytes() {
|
|
450
|
+
return this.data.length;
|
|
451
|
+
}
|
|
452
|
+
isEnd() {
|
|
453
|
+
return this.pos >= this.data.length && !this.bitPos;
|
|
454
|
+
}
|
|
455
|
+
progress() {
|
|
456
|
+
return this.pos * 8 - this.bitPos;
|
|
457
|
+
}
|
|
458
|
+
bits(bits) {
|
|
459
|
+
if (!isNum(bits) || bits < 0)
|
|
460
|
+
throw this.err(`BitReader: wrong length=${bits}`);
|
|
461
|
+
if (bits > 32)
|
|
462
|
+
throw this.err("BitReader: cannot read more than 32 bits in single call");
|
|
463
|
+
let out = 0;
|
|
464
|
+
while (bits) {
|
|
465
|
+
if (!this.bitPos) {
|
|
466
|
+
this.bitBuf = this.byte();
|
|
467
|
+
this.bitPos = 8;
|
|
468
|
+
}
|
|
469
|
+
const take = Math.min(bits, this.bitPos);
|
|
470
|
+
this.bitPos -= take;
|
|
471
|
+
out = out << take | this.bitBuf >> this.bitPos & 2 ** take - 1;
|
|
472
|
+
this.bitBuf &= 2 ** this.bitPos - 1;
|
|
473
|
+
bits -= take;
|
|
474
|
+
}
|
|
475
|
+
return out >>> 0;
|
|
476
|
+
}
|
|
477
|
+
find(needle, pos = this.pos) {
|
|
478
|
+
if (!isBytes(needle))
|
|
479
|
+
throw this.err(`find: needle is not bytes! ${needle}`);
|
|
480
|
+
if (this.bitPos)
|
|
481
|
+
throw this.err("find: bitPos not empty");
|
|
482
|
+
if (!needle.length)
|
|
483
|
+
throw this.err(`find: needle is empty`);
|
|
484
|
+
if (!isNum(pos) || pos < 0)
|
|
485
|
+
throw this.err(`find: wrong pos=${pos}`);
|
|
486
|
+
return findBytes(needle, this.data, pos);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
class _Writer {
|
|
491
|
+
pos = 0;
|
|
492
|
+
stack;
|
|
493
|
+
buffers = [];
|
|
494
|
+
chunks = [];
|
|
495
|
+
chunk;
|
|
496
|
+
chunkView;
|
|
497
|
+
chunkPos = 0;
|
|
498
|
+
run;
|
|
499
|
+
nextChunkSize = 0;
|
|
500
|
+
ptrs = [];
|
|
501
|
+
bitBuf = 0;
|
|
502
|
+
bitPos = 0;
|
|
503
|
+
finished = false;
|
|
504
|
+
constructor(stack = []) {
|
|
505
|
+
this.stack = stack;
|
|
506
|
+
}
|
|
507
|
+
carve(len) {
|
|
508
|
+
if (this.chunk === undefined || this.chunk.length - this.chunkPos < len) {
|
|
509
|
+
const size = Math.max(len, this.nextChunkSize, 64);
|
|
510
|
+
this.nextChunkSize = Math.min(size * 8, 4096);
|
|
511
|
+
this.chunk = new Uint8Array(size);
|
|
512
|
+
this.chunkView = undefined;
|
|
513
|
+
this.chunkPos = 0;
|
|
514
|
+
this.run = undefined;
|
|
515
|
+
this.chunks.push(this.chunk);
|
|
516
|
+
}
|
|
517
|
+
const pos = this.chunkPos;
|
|
518
|
+
if (this.run === undefined) {
|
|
519
|
+
this.run = { chunk: this.chunk, start: pos, end: pos + len };
|
|
520
|
+
this.buffers.push(this.run);
|
|
521
|
+
} else
|
|
522
|
+
this.run.end += len;
|
|
523
|
+
this.chunkPos = pos + len;
|
|
524
|
+
this.pos += len;
|
|
525
|
+
return pos;
|
|
526
|
+
}
|
|
527
|
+
pushObj(obj, objFn) {
|
|
528
|
+
return Path.pushObj(this.stack, obj, objFn);
|
|
529
|
+
}
|
|
530
|
+
enterField(field) {
|
|
531
|
+
const last = this.stack[this.stack.length - 1];
|
|
532
|
+
if (last === undefined || last.field !== undefined)
|
|
533
|
+
throw this.err(`enterField: invalid stack state, field=${field}`);
|
|
534
|
+
last.field = field;
|
|
535
|
+
}
|
|
536
|
+
exitField() {
|
|
537
|
+
this.stack[this.stack.length - 1].field = undefined;
|
|
538
|
+
}
|
|
539
|
+
writeView(len, fn) {
|
|
540
|
+
if (this.finished)
|
|
541
|
+
throw this.err("buffer: finished");
|
|
542
|
+
if (!isNum(len) || len < 0 || len > 8)
|
|
543
|
+
throw new Error(`wrong writeView length=${len}`);
|
|
544
|
+
if (this.bitPos)
|
|
545
|
+
throw this.err("writeBytes: ends with non-empty bit buffer");
|
|
546
|
+
const pos = this.carve(len);
|
|
547
|
+
if (this.chunkView === undefined)
|
|
548
|
+
this.chunkView = createView(this.chunk);
|
|
549
|
+
fn(this.chunkView, pos);
|
|
550
|
+
}
|
|
551
|
+
err(msg) {
|
|
552
|
+
return Path.err("Writer", this.stack, msg);
|
|
553
|
+
}
|
|
554
|
+
bytes(b) {
|
|
555
|
+
if (this.finished)
|
|
556
|
+
throw this.err("buffer: finished");
|
|
557
|
+
if (this.bitPos)
|
|
558
|
+
throw this.err("writeBytes: ends with non-empty bit buffer");
|
|
559
|
+
if (!isBytes(b))
|
|
560
|
+
throw this.err(`writeBytes: expected Uint8Array, got ${typeof b}`);
|
|
561
|
+
this.buffers.push(b);
|
|
562
|
+
this.run = undefined;
|
|
563
|
+
this.pos += b.length;
|
|
564
|
+
}
|
|
565
|
+
byte(b) {
|
|
566
|
+
if (this.finished)
|
|
567
|
+
throw this.err("buffer: finished");
|
|
568
|
+
if (this.bitPos)
|
|
569
|
+
throw this.err("writeByte: ends with non-empty bit buffer");
|
|
570
|
+
if (!isNum(b) || b < 0 || b > 255)
|
|
571
|
+
throw this.err(`writeByte: wrong value=${b}`);
|
|
572
|
+
const pos = this.carve(1);
|
|
573
|
+
this.chunk[pos] = b;
|
|
574
|
+
}
|
|
575
|
+
finish(clean = true) {
|
|
576
|
+
if (this.finished)
|
|
577
|
+
throw this.err("buffer: finished");
|
|
578
|
+
if (this.bitPos)
|
|
579
|
+
throw this.err("buffer: ends with non-empty bit buffer");
|
|
580
|
+
const buffers = this.buffers;
|
|
581
|
+
let sum = 0;
|
|
582
|
+
for (let i = 0;i < buffers.length; i++) {
|
|
583
|
+
const b = buffers[i];
|
|
584
|
+
sum += isBytes(b) ? b.length : b.end - b.start;
|
|
585
|
+
}
|
|
586
|
+
for (let i = 0;i < this.ptrs.length; i++)
|
|
587
|
+
sum += this.ptrs[i].buffer.length;
|
|
588
|
+
const buf = new Uint8Array(sum);
|
|
589
|
+
let pad = 0;
|
|
590
|
+
for (let i = 0;i < buffers.length; i++) {
|
|
591
|
+
const b = buffers[i];
|
|
592
|
+
if (isBytes(b)) {
|
|
593
|
+
buf.set(b, pad);
|
|
594
|
+
pad += b.length;
|
|
595
|
+
} else {
|
|
596
|
+
buf.set(b.chunk.subarray(b.start, b.end), pad);
|
|
597
|
+
pad += b.end - b.start;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
for (let i = 0;i < this.ptrs.length; i++) {
|
|
601
|
+
buf.set(this.ptrs[i].buffer, pad);
|
|
602
|
+
pad += this.ptrs[i].buffer.length;
|
|
603
|
+
}
|
|
604
|
+
for (let pos = this.pos, i = 0;i < this.ptrs.length; i++) {
|
|
605
|
+
const ptr = this.ptrs[i];
|
|
606
|
+
buf.set(ptr.ptr.encode(pos), ptr.pos);
|
|
607
|
+
pos += ptr.buffer.length;
|
|
608
|
+
}
|
|
609
|
+
if (clean) {
|
|
610
|
+
for (const c of this.chunks)
|
|
611
|
+
c.fill(0);
|
|
612
|
+
this.chunks = [];
|
|
613
|
+
this.chunk = undefined;
|
|
614
|
+
this.chunkView = undefined;
|
|
615
|
+
this.chunkPos = 0;
|
|
616
|
+
this.run = undefined;
|
|
617
|
+
this.buffers = [];
|
|
618
|
+
for (const p of this.ptrs)
|
|
619
|
+
p.buffer.fill(0);
|
|
620
|
+
this.ptrs = [];
|
|
621
|
+
this.finished = true;
|
|
622
|
+
this.bitBuf = 0;
|
|
623
|
+
}
|
|
624
|
+
return buf;
|
|
625
|
+
}
|
|
626
|
+
bits(value, bits) {
|
|
627
|
+
if (this.finished)
|
|
628
|
+
throw this.err("buffer: finished");
|
|
629
|
+
if (!isNum(bits) || bits < 0)
|
|
630
|
+
throw this.err(`writeBits: wrong length=${bits}`);
|
|
631
|
+
if (bits > 32)
|
|
632
|
+
throw this.err("writeBits: cannot write more than 32 bits in single call");
|
|
633
|
+
if (!isNum(value) || value < 0)
|
|
634
|
+
throw this.err(`writeBits: wrong value=${value}`);
|
|
635
|
+
if (value >= 2 ** bits)
|
|
636
|
+
throw this.err(`writeBits: value (${value}) >= 2**bits (${bits})`);
|
|
637
|
+
while (bits) {
|
|
638
|
+
const take = Math.min(bits, 8 - this.bitPos);
|
|
639
|
+
this.bitBuf = this.bitBuf << take | value >> bits - take;
|
|
640
|
+
this.bitPos += take;
|
|
641
|
+
bits -= take;
|
|
642
|
+
value &= 2 ** bits - 1;
|
|
643
|
+
if (this.bitPos === 8) {
|
|
644
|
+
this.bitPos = 0;
|
|
645
|
+
const pos = this.carve(1);
|
|
646
|
+
this.chunk[pos] = this.bitBuf;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
var swapEndianness = (b) => Uint8Array.from(b).reverse();
|
|
652
|
+
function checkMinimalBigintBytes(value, le, signed, err) {
|
|
653
|
+
if (!value.length)
|
|
654
|
+
return;
|
|
655
|
+
const b = le ? swapEndianness(value) : value;
|
|
656
|
+
const fail = () => {
|
|
657
|
+
throw err("bigint: non-minimal encoding");
|
|
658
|
+
};
|
|
659
|
+
if (!signed) {
|
|
660
|
+
if (b[0] === 0)
|
|
661
|
+
fail();
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
if (b[0] === 0 && (b.length === 1 || (b[1] & 128) === 0))
|
|
665
|
+
fail();
|
|
666
|
+
if (b.length > 1 && b[0] === 255 && (b[1] & 128) !== 0)
|
|
667
|
+
fail();
|
|
668
|
+
}
|
|
669
|
+
function checkBounds(value, bits, signed) {
|
|
670
|
+
if (signed) {
|
|
671
|
+
if (bits <= _0n)
|
|
672
|
+
throw new Error(`checkBounds: signed bits must be positive, got ${bits}`);
|
|
673
|
+
const signBit = _2n ** (bits - _1n);
|
|
674
|
+
if (value < -signBit || value >= signBit)
|
|
675
|
+
throw new Error(`value out of signed bounds. Expected ${-signBit} <= ${value} < ${signBit}`);
|
|
676
|
+
} else {
|
|
677
|
+
const max = _2n ** bits;
|
|
678
|
+
if (_0n > value || value >= max)
|
|
679
|
+
throw new Error(`value out of unsigned bounds. Expected 0 <= ${value} < ${max}`);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
function _wrap(inner) {
|
|
683
|
+
const _inner = inner;
|
|
684
|
+
return {
|
|
685
|
+
encodeStream: _inner.encodeStream,
|
|
686
|
+
decodeStream: _inner.decodeStream,
|
|
687
|
+
size: _inner.size,
|
|
688
|
+
encode: (value) => {
|
|
689
|
+
const w = new _Writer;
|
|
690
|
+
_inner.encodeStream(w, value);
|
|
691
|
+
return w.finish();
|
|
692
|
+
},
|
|
693
|
+
decode: (data, opts = {}) => {
|
|
694
|
+
if (!isBytes(data))
|
|
695
|
+
throw new TypeError(`decode: expected Uint8Array, got ${typeof data}`);
|
|
696
|
+
const r = new _Reader(data, opts);
|
|
697
|
+
const res = _inner.decodeStream(r);
|
|
698
|
+
r.finish();
|
|
699
|
+
return res;
|
|
700
|
+
}
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
function validate(inner, fn) {
|
|
704
|
+
if (!isCoder(inner))
|
|
705
|
+
throw new TypeError(`validate: invalid inner value ${inner}`);
|
|
706
|
+
if (typeof fn !== "function")
|
|
707
|
+
throw new TypeError("validate: fn should be function");
|
|
708
|
+
return _wrap({
|
|
709
|
+
size: inner.size,
|
|
710
|
+
encodeStream: (w, value) => {
|
|
711
|
+
let res;
|
|
712
|
+
try {
|
|
713
|
+
res = fn(value);
|
|
714
|
+
} catch (e) {
|
|
715
|
+
throw w.err(e);
|
|
716
|
+
}
|
|
717
|
+
inner.encodeStream(w, res);
|
|
718
|
+
},
|
|
719
|
+
decodeStream: (r) => {
|
|
720
|
+
const res = inner.decodeStream(r);
|
|
721
|
+
try {
|
|
722
|
+
return fn(res);
|
|
723
|
+
} catch (e) {
|
|
724
|
+
throw r.err(e);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
var wrap = (inner) => {
|
|
730
|
+
const _inner = inner;
|
|
731
|
+
if (!isPlainObject(_inner))
|
|
732
|
+
throw new TypeError(`wrap: invalid inner value ${_inner}`);
|
|
733
|
+
if (typeof _inner.encodeStream !== "function")
|
|
734
|
+
throw new TypeError("wrap: encodeStream should be function");
|
|
735
|
+
if (typeof _inner.decodeStream !== "function")
|
|
736
|
+
throw new TypeError("wrap: decodeStream should be function");
|
|
737
|
+
if (_inner.size !== undefined && (!isNum(_inner.size) || _inner.size < 0))
|
|
738
|
+
throw new TypeError(`wrap: invalid size ${_inner.size}`);
|
|
739
|
+
if (_inner.validate !== undefined && typeof _inner.validate !== "function")
|
|
740
|
+
throw new TypeError("wrap: validate should be function");
|
|
741
|
+
const res = _wrap(_inner);
|
|
742
|
+
return _inner.validate !== undefined ? validate(res, _inner.validate) : res;
|
|
743
|
+
};
|
|
744
|
+
var isBaseCoder = (elm) => isPlainObject(elm) && typeof elm.decode === "function" && typeof elm.encode === "function";
|
|
745
|
+
function isCoder(elm) {
|
|
746
|
+
return isPlainObject(elm) && isBaseCoder(elm) && typeof elm.encodeStream === "function" && typeof elm.decodeStream === "function" && (elm.size === undefined || isNum(elm.size) && elm.size >= 0);
|
|
747
|
+
}
|
|
748
|
+
function dict() {
|
|
749
|
+
return {
|
|
750
|
+
encode: (from) => {
|
|
751
|
+
if (!Array.isArray(from))
|
|
752
|
+
throw new Error("array expected");
|
|
753
|
+
const to = {};
|
|
754
|
+
const seen = new Set;
|
|
755
|
+
for (const item of from) {
|
|
756
|
+
if (!Array.isArray(item) || item.length !== 2)
|
|
757
|
+
throw new Error(`array of two elements expected`);
|
|
758
|
+
const name = item[0];
|
|
759
|
+
const value = item[1];
|
|
760
|
+
validateFieldName(name, "dict: key");
|
|
761
|
+
if (seen.has(name))
|
|
762
|
+
throw new Error(`key(${name}) appears twice in struct`);
|
|
763
|
+
seen.add(name);
|
|
764
|
+
to[name] = value;
|
|
765
|
+
}
|
|
766
|
+
return to;
|
|
767
|
+
},
|
|
768
|
+
decode: (to) => {
|
|
769
|
+
if (!isPlainObject(to))
|
|
770
|
+
throw new Error(`expected plain object, got ${to}`);
|
|
771
|
+
for (const name in to)
|
|
772
|
+
validateFieldName(name, "dict: key");
|
|
773
|
+
return Object.entries(to);
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
var numberBigint = /* @__PURE__ */ Object.freeze({
|
|
778
|
+
encode: (from) => {
|
|
779
|
+
if (typeof from !== "bigint")
|
|
780
|
+
throw new Error(`expected bigint, got ${typeof from}`);
|
|
781
|
+
if (from > BigInt(Number.MAX_SAFE_INTEGER))
|
|
782
|
+
throw new Error(`element bigger than MAX_SAFE_INTEGER=${from}`);
|
|
783
|
+
if (from < BigInt(Number.MIN_SAFE_INTEGER))
|
|
784
|
+
throw new Error(`element smaller than MIN_SAFE_INTEGER=${from}`);
|
|
785
|
+
return Number(from);
|
|
786
|
+
},
|
|
787
|
+
decode: (to) => {
|
|
788
|
+
if (!isNum(to))
|
|
789
|
+
throw new Error("element is not a safe integer");
|
|
790
|
+
return BigInt(to);
|
|
791
|
+
}
|
|
792
|
+
});
|
|
793
|
+
function tsEnum(e) {
|
|
794
|
+
if (!isPlainObject(e))
|
|
795
|
+
throw new Error("plain object expected");
|
|
796
|
+
return {
|
|
797
|
+
encode: (from) => {
|
|
798
|
+
if (!isNum(from) || !(from in e))
|
|
799
|
+
throw new Error(`wrong value ${from}`);
|
|
800
|
+
return e[from];
|
|
801
|
+
},
|
|
802
|
+
decode: (to) => {
|
|
803
|
+
if (typeof to !== "string")
|
|
804
|
+
throw new Error(`wrong value ${typeof to}`);
|
|
805
|
+
const value = e[to];
|
|
806
|
+
if (!hasOwn(e, to) || !isNum(value))
|
|
807
|
+
throw new Error(`wrong value ${to}`);
|
|
808
|
+
return value;
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
function decimal(precision, round = false) {
|
|
813
|
+
if (!isNum(precision) || precision < 0)
|
|
814
|
+
throw new Error(`decimal/precision: wrong value ${precision}`);
|
|
815
|
+
if (typeof round !== "boolean")
|
|
816
|
+
throw new Error(`decimal/round: expected boolean, got ${typeof round}`);
|
|
817
|
+
const decimalMask = _10n ** BigInt(precision);
|
|
818
|
+
return {
|
|
819
|
+
encode: (from) => {
|
|
820
|
+
if (typeof from !== "bigint")
|
|
821
|
+
throw new Error(`expected bigint, got ${typeof from}`);
|
|
822
|
+
let s = (from < _0n ? -from : from).toString(10);
|
|
823
|
+
let sep = s.length - precision;
|
|
824
|
+
if (sep < 0) {
|
|
825
|
+
s = s.padStart(s.length - sep, "0");
|
|
826
|
+
sep = 0;
|
|
827
|
+
}
|
|
828
|
+
let i = s.length - 1;
|
|
829
|
+
for (;i >= sep && s[i] === "0"; i--)
|
|
830
|
+
;
|
|
831
|
+
let int = s.slice(0, sep);
|
|
832
|
+
let frac = s.slice(sep, i + 1);
|
|
833
|
+
if (!int)
|
|
834
|
+
int = "0";
|
|
835
|
+
if (from < _0n)
|
|
836
|
+
int = "-" + int;
|
|
837
|
+
if (!frac)
|
|
838
|
+
return int;
|
|
839
|
+
return `${int}.${frac}`;
|
|
840
|
+
},
|
|
841
|
+
decode: (to) => {
|
|
842
|
+
if (typeof to !== "string")
|
|
843
|
+
throw new Error(`expected string, got ${typeof to}`);
|
|
844
|
+
let neg = false;
|
|
845
|
+
if (to.startsWith("-")) {
|
|
846
|
+
neg = true;
|
|
847
|
+
to = to.slice(1);
|
|
848
|
+
}
|
|
849
|
+
if (!/^(0|[1-9]\d*)(\.\d+)?$/.test(to))
|
|
850
|
+
throw new Error(`wrong string value=${to}`);
|
|
851
|
+
let sep = to.indexOf(".");
|
|
852
|
+
sep = sep === -1 ? to.length : sep;
|
|
853
|
+
const intS = to.slice(0, sep);
|
|
854
|
+
const fracS = to.slice(sep + 1).replace(/0+$/, "");
|
|
855
|
+
const int = BigInt(intS) * decimalMask;
|
|
856
|
+
if (!round && fracS.length > precision) {
|
|
857
|
+
throw new Error(`fractional part cannot be represented with this precision (num=${to}, prec=${precision})`);
|
|
858
|
+
}
|
|
859
|
+
const fracLen = Math.min(fracS.length, precision);
|
|
860
|
+
const frac = BigInt(fracS.slice(0, fracLen)) * _10n ** BigInt(precision - fracLen);
|
|
861
|
+
const value = int + frac;
|
|
862
|
+
if (neg && value === _0n)
|
|
863
|
+
throw new Error(`negative zero is not allowed`);
|
|
864
|
+
return neg ? -value : value;
|
|
865
|
+
}
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
function match(lst) {
|
|
869
|
+
if (!Array.isArray(lst))
|
|
870
|
+
throw new Error(`expected array, got ${typeof lst}`);
|
|
871
|
+
for (const i of lst)
|
|
872
|
+
if (!isBaseCoder(i))
|
|
873
|
+
throw new Error(`wrong base coder ${i}`);
|
|
874
|
+
return {
|
|
875
|
+
encode: (from) => {
|
|
876
|
+
for (const c of lst) {
|
|
877
|
+
let elm;
|
|
878
|
+
try {
|
|
879
|
+
elm = c.encode(from);
|
|
880
|
+
} catch {
|
|
881
|
+
continue;
|
|
882
|
+
}
|
|
883
|
+
if (elm !== undefined)
|
|
884
|
+
return elm;
|
|
885
|
+
}
|
|
886
|
+
throw new Error(`match/encode: cannot find match in ${from}`);
|
|
887
|
+
},
|
|
888
|
+
decode: (to) => {
|
|
889
|
+
for (const c of lst) {
|
|
890
|
+
let elm;
|
|
891
|
+
try {
|
|
892
|
+
elm = c.decode(to);
|
|
893
|
+
} catch {
|
|
894
|
+
continue;
|
|
895
|
+
}
|
|
896
|
+
if (elm !== undefined)
|
|
897
|
+
return elm;
|
|
898
|
+
}
|
|
899
|
+
throw new Error(`match/decode: cannot find match in ${to}`);
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
var reverse = (coder) => {
|
|
904
|
+
if (!isBaseCoder(coder))
|
|
905
|
+
throw new Error("BaseCoder expected");
|
|
906
|
+
return { encode: (to) => coder.decode(to), decode: (from) => coder.encode(from) };
|
|
907
|
+
};
|
|
908
|
+
var coders = /* @__PURE__ */ Object.freeze({ dict, numberBigint, tsEnum, decimal, match, reverse });
|
|
909
|
+
var bigint = (size, le = false, signed = false, sized = true, minimal = false) => {
|
|
910
|
+
if (!isNum(size) || size <= 0)
|
|
911
|
+
throw new Error(`bigint/size: wrong value ${size}`);
|
|
912
|
+
if (typeof le !== "boolean")
|
|
913
|
+
throw new Error(`bigint/le: expected boolean, got ${typeof le}`);
|
|
914
|
+
if (typeof signed !== "boolean")
|
|
915
|
+
throw new Error(`bigint/signed: expected boolean, got ${typeof signed}`);
|
|
916
|
+
if (typeof sized !== "boolean")
|
|
917
|
+
throw new Error(`bigint/sized: expected boolean, got ${typeof sized}`);
|
|
918
|
+
if (typeof minimal !== "boolean")
|
|
919
|
+
throw new Error(`bigint/minimal: expected boolean, got ${typeof minimal}`);
|
|
920
|
+
const bLen = BigInt(size);
|
|
921
|
+
const signBit = _2n ** (_8n * bLen - _1n);
|
|
922
|
+
return wrap({
|
|
923
|
+
size: sized ? size : undefined,
|
|
924
|
+
encodeStream: (w, value) => {
|
|
925
|
+
const zero = value === _0n;
|
|
926
|
+
if (signed && value < 0)
|
|
927
|
+
value = value | signBit;
|
|
928
|
+
let res = new Uint8Array(size);
|
|
929
|
+
for (let i = size - 1;i >= 0; i--) {
|
|
930
|
+
res[i] = Number(value & _255n);
|
|
931
|
+
value >>= _8n;
|
|
932
|
+
}
|
|
933
|
+
if (!sized) {
|
|
934
|
+
let pos = 0;
|
|
935
|
+
if (signed) {
|
|
936
|
+
for (;pos < res.length - 1; pos++) {
|
|
937
|
+
const next = res[pos + 1];
|
|
938
|
+
if (res[pos] === 0 && (next & 128) === 0)
|
|
939
|
+
continue;
|
|
940
|
+
if (res[pos] === 255 && (next & 128) !== 0)
|
|
941
|
+
continue;
|
|
942
|
+
break;
|
|
943
|
+
}
|
|
944
|
+
res = zero ? res.subarray(res.length) : res.subarray(pos);
|
|
945
|
+
} else {
|
|
946
|
+
for (;pos < res.length; pos++)
|
|
947
|
+
if (res[pos] !== 0)
|
|
948
|
+
break;
|
|
949
|
+
res = res.subarray(pos);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
w.bytes(le ? res.reverse() : res);
|
|
953
|
+
},
|
|
954
|
+
decodeStream: (r) => {
|
|
955
|
+
const value = r.bytes(sized ? size : Math.min(size, r.leftBytes));
|
|
956
|
+
if (!sized && minimal)
|
|
957
|
+
checkMinimalBigintBytes(value, le, signed, (msg) => r.err(msg));
|
|
958
|
+
let res = _0n;
|
|
959
|
+
if (le)
|
|
960
|
+
for (let i = value.length - 1;i >= 0; i--)
|
|
961
|
+
res = res << _8n | BigInt(value[i]);
|
|
962
|
+
else
|
|
963
|
+
for (let i = 0;i < value.length; i++)
|
|
964
|
+
res = res << _8n | BigInt(value[i]);
|
|
965
|
+
const sBit = sized || !value.length ? signBit : _2n ** (_8n * BigInt(value.length) - _1n);
|
|
966
|
+
if (signed && res & sBit)
|
|
967
|
+
res = (res ^ sBit) - sBit;
|
|
968
|
+
return res;
|
|
969
|
+
},
|
|
970
|
+
validate: (value) => {
|
|
971
|
+
if (typeof value !== "bigint")
|
|
972
|
+
throw new Error(`bigint: invalid value: ${value}`);
|
|
973
|
+
checkBounds(value, _8n * bLen, !!signed);
|
|
974
|
+
return value;
|
|
975
|
+
}
|
|
976
|
+
});
|
|
977
|
+
};
|
|
978
|
+
var U256LE = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ bigint(32, true));
|
|
979
|
+
var U64LE = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ bigint(8, true));
|
|
980
|
+
var I64LE = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ bigint(8, true, true));
|
|
981
|
+
var view = (len, opts) => wrap({
|
|
982
|
+
size: len,
|
|
983
|
+
encodeStream: (w, value) => w.writeView(len, (view, pos) => opts.write(view, pos, value)),
|
|
984
|
+
decodeStream: (r) => r.readView(len, opts.read),
|
|
985
|
+
validate: (value) => {
|
|
986
|
+
if (typeof value !== "number")
|
|
987
|
+
throw new TypeError(`viewCoder: expected number, got ${typeof value}`);
|
|
988
|
+
if (opts.validate)
|
|
989
|
+
opts.validate(value);
|
|
990
|
+
return value;
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
var intView = (len, signed, opts) => {
|
|
994
|
+
const bits = len * 8;
|
|
995
|
+
const signBit = 2 ** (bits - 1);
|
|
996
|
+
const validateSigned = (value) => {
|
|
997
|
+
if (!isNum(value))
|
|
998
|
+
throw new TypeError(`sintView: value is not safe integer: ${value}`);
|
|
999
|
+
if (value < -signBit || value >= signBit) {
|
|
1000
|
+
throw new RangeError(`sintView: value out of bounds. Expected ${-signBit} <= ${value} < ${signBit}`);
|
|
1001
|
+
}
|
|
1002
|
+
};
|
|
1003
|
+
const maxVal = 2 ** bits;
|
|
1004
|
+
const validateUnsigned = (value) => {
|
|
1005
|
+
if (!isNum(value))
|
|
1006
|
+
throw new TypeError(`uintView: value is not safe integer: ${value}`);
|
|
1007
|
+
if (0 > value || value >= maxVal) {
|
|
1008
|
+
throw new RangeError(`uintView: value out of bounds. Expected 0 <= ${value} < ${maxVal}`);
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
1011
|
+
return view(len, {
|
|
1012
|
+
write: opts.write,
|
|
1013
|
+
read: opts.read,
|
|
1014
|
+
validate: signed ? validateSigned : validateUnsigned
|
|
1015
|
+
});
|
|
1016
|
+
};
|
|
1017
|
+
var U32LE = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ intView(4, false, {
|
|
1018
|
+
read: (view, pos) => view.getUint32(pos, true),
|
|
1019
|
+
write: (view, pos, value) => view.setUint32(pos, value, true)
|
|
1020
|
+
}));
|
|
1021
|
+
var U32BE = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ intView(4, false, {
|
|
1022
|
+
read: (view, pos) => view.getUint32(pos, false),
|
|
1023
|
+
write: (view, pos, value) => view.setUint32(pos, value, false)
|
|
1024
|
+
}));
|
|
1025
|
+
var I32LE = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ intView(4, true, {
|
|
1026
|
+
read: (view, pos) => view.getInt32(pos, true),
|
|
1027
|
+
write: (view, pos, value) => view.setInt32(pos, value, true)
|
|
1028
|
+
}));
|
|
1029
|
+
var U16LE = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ intView(2, false, {
|
|
1030
|
+
read: (view, pos) => view.getUint16(pos, true),
|
|
1031
|
+
write: (view, pos, value) => view.setUint16(pos, value, true)
|
|
1032
|
+
}));
|
|
1033
|
+
var U8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ intView(1, false, {
|
|
1034
|
+
read: (view, pos) => view.getUint8(pos),
|
|
1035
|
+
write: (view, pos, value) => view.setUint8(pos, value)
|
|
1036
|
+
}));
|
|
1037
|
+
var createBytes = (len, le = false) => {
|
|
1038
|
+
if (typeof le !== "boolean")
|
|
1039
|
+
throw new TypeError(`bytes/le: expected boolean, got ${typeof le}`);
|
|
1040
|
+
const _length = lengthCoder(len);
|
|
1041
|
+
const _isb = isBytes(len);
|
|
1042
|
+
const terminator = _isb ? Uint8Array.from(len) : undefined;
|
|
1043
|
+
const findTerminator = terminator && terminator.length ? createFindBytes(terminator) : undefined;
|
|
1044
|
+
return wrap({
|
|
1045
|
+
size: typeof len === "number" ? len : undefined,
|
|
1046
|
+
encodeStream: (w, value) => {
|
|
1047
|
+
if (!_isb)
|
|
1048
|
+
_length.encodeStream(w, value.length);
|
|
1049
|
+
w.bytes(le ? swapEndianness(value) : value);
|
|
1050
|
+
if (terminator)
|
|
1051
|
+
w.bytes(terminator);
|
|
1052
|
+
},
|
|
1053
|
+
decodeStream: (r) => {
|
|
1054
|
+
let bytes;
|
|
1055
|
+
if (terminator) {
|
|
1056
|
+
const tPos = r.find(terminator);
|
|
1057
|
+
if (tPos === undefined)
|
|
1058
|
+
throw r.err(`bytes: cannot find terminator`);
|
|
1059
|
+
bytes = r.bytes(tPos - r.pos);
|
|
1060
|
+
r.bytes(terminator.length);
|
|
1061
|
+
} else {
|
|
1062
|
+
bytes = r.bytes(len === null ? r.leftBytes : _length.decodeStream(r));
|
|
1063
|
+
}
|
|
1064
|
+
return le ? swapEndianness(bytes) : bytes;
|
|
1065
|
+
},
|
|
1066
|
+
validate: (value) => {
|
|
1067
|
+
if (!isBytes(value))
|
|
1068
|
+
throw new TypeError(`bytes: invalid value ${value}`);
|
|
1069
|
+
if (findTerminator) {
|
|
1070
|
+
const data = le ? swapEndianness(value) : value;
|
|
1071
|
+
if (findTerminator(data) !== undefined)
|
|
1072
|
+
throw new Error("bytes: value contains terminator");
|
|
1073
|
+
}
|
|
1074
|
+
return value;
|
|
1075
|
+
}
|
|
1076
|
+
});
|
|
1077
|
+
};
|
|
1078
|
+
function prefix(len, inner) {
|
|
1079
|
+
if (!isCoder(inner))
|
|
1080
|
+
throw new TypeError(`prefix: invalid inner value ${inner}`);
|
|
1081
|
+
return apply(createBytes(len), reverse(inner));
|
|
1082
|
+
}
|
|
1083
|
+
var string = (len, le = false) => validate(apply(createBytes(len, le), utf8), (value) => {
|
|
1084
|
+
if (typeof value !== "string")
|
|
1085
|
+
throw new Error(`expected string, got ${typeof value}`);
|
|
1086
|
+
return value;
|
|
1087
|
+
});
|
|
1088
|
+
function apply(inner, base) {
|
|
1089
|
+
if (!isCoder(inner))
|
|
1090
|
+
throw new TypeError(`apply: invalid inner value ${inner}`);
|
|
1091
|
+
if (!isBaseCoder(base))
|
|
1092
|
+
throw new TypeError(`apply: invalid base value ${base}`);
|
|
1093
|
+
return wrap({
|
|
1094
|
+
size: inner.size,
|
|
1095
|
+
encodeStream: (w, value) => {
|
|
1096
|
+
let innerValue;
|
|
1097
|
+
try {
|
|
1098
|
+
innerValue = base.decode(value);
|
|
1099
|
+
} catch (e) {
|
|
1100
|
+
throw w.err("" + e);
|
|
1101
|
+
}
|
|
1102
|
+
return inner.encodeStream(w, innerValue);
|
|
1103
|
+
},
|
|
1104
|
+
decodeStream: (r) => {
|
|
1105
|
+
const innerValue = inner.decodeStream(r);
|
|
1106
|
+
try {
|
|
1107
|
+
return base.encode(innerValue);
|
|
1108
|
+
} catch (e) {
|
|
1109
|
+
throw r.err("" + e);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
});
|
|
1113
|
+
}
|
|
1114
|
+
var flag = (flagValue, xor = false) => {
|
|
1115
|
+
if (!isBytes(flagValue))
|
|
1116
|
+
throw new TypeError(`flag/flagValue: expected Uint8Array, got ${typeof flagValue}`);
|
|
1117
|
+
if (flagValue.length === 0)
|
|
1118
|
+
throw new Error("flag/flagValue: empty marker");
|
|
1119
|
+
if (typeof xor !== "boolean")
|
|
1120
|
+
throw new TypeError(`flag/xor: expected boolean, got ${typeof xor}`);
|
|
1121
|
+
const marker = Uint8Array.from(flagValue);
|
|
1122
|
+
return wrap({
|
|
1123
|
+
size: undefined,
|
|
1124
|
+
encodeStream: (w, value) => {
|
|
1125
|
+
if (!!value !== xor)
|
|
1126
|
+
w.bytes(marker);
|
|
1127
|
+
},
|
|
1128
|
+
decodeStream: (r) => {
|
|
1129
|
+
let hasFlag = r.leftBytes >= marker.length;
|
|
1130
|
+
if (hasFlag) {
|
|
1131
|
+
hasFlag = equalBytes(r.bytes(marker.length, true), marker);
|
|
1132
|
+
if (hasFlag)
|
|
1133
|
+
r.bytes(marker.length);
|
|
1134
|
+
}
|
|
1135
|
+
return hasFlag !== xor;
|
|
1136
|
+
},
|
|
1137
|
+
validate: (value) => {
|
|
1138
|
+
if (value !== undefined && typeof value !== "boolean")
|
|
1139
|
+
throw new Error(`flag: expected boolean value or undefined, got ${typeof value}`);
|
|
1140
|
+
return value;
|
|
1141
|
+
}
|
|
1142
|
+
});
|
|
1143
|
+
};
|
|
1144
|
+
function validateDefaultSlot(r, value, def) {
|
|
1145
|
+
const valueObj = value !== null && typeof value === "object" && !isBytes(value);
|
|
1146
|
+
const defObj = def !== null && typeof def === "object" && !isBytes(def);
|
|
1147
|
+
const nan = typeof value === "number" && typeof def === "number" && Number.isNaN(value) && Number.isNaN(def);
|
|
1148
|
+
if ((!valueObj || !defObj) && !equal(value, def) && !nan)
|
|
1149
|
+
throw r.err(`default: invalid value ${value} !== ${def}`);
|
|
1150
|
+
}
|
|
1151
|
+
function flagged(path, inner, def) {
|
|
1152
|
+
if (typeof path !== "string" && !isCoder(path))
|
|
1153
|
+
throw new TypeError(`flagged: wrong path=${path}`);
|
|
1154
|
+
if (!isCoder(inner))
|
|
1155
|
+
throw new TypeError(`flagged: invalid inner value ${inner}`);
|
|
1156
|
+
const hasDef = def !== undefined;
|
|
1157
|
+
return wrap({
|
|
1158
|
+
encodeStream: (w, value) => {
|
|
1159
|
+
if (typeof path === "string") {
|
|
1160
|
+
if (Path.resolve(w.stack, path))
|
|
1161
|
+
inner.encodeStream(w, value);
|
|
1162
|
+
else if (hasDef)
|
|
1163
|
+
inner.encodeStream(w, def);
|
|
1164
|
+
} else {
|
|
1165
|
+
const present = value !== undefined;
|
|
1166
|
+
path.encodeStream(w, present);
|
|
1167
|
+
if (present)
|
|
1168
|
+
inner.encodeStream(w, value);
|
|
1169
|
+
else if (hasDef)
|
|
1170
|
+
inner.encodeStream(w, def);
|
|
1171
|
+
}
|
|
1172
|
+
},
|
|
1173
|
+
decodeStream: (r) => {
|
|
1174
|
+
let hasFlag = false;
|
|
1175
|
+
if (typeof path === "string")
|
|
1176
|
+
hasFlag = !!Path.resolve(r.stack, path);
|
|
1177
|
+
else
|
|
1178
|
+
hasFlag = path.decodeStream(r);
|
|
1179
|
+
if (hasFlag)
|
|
1180
|
+
return inner.decodeStream(r);
|
|
1181
|
+
else if (hasDef)
|
|
1182
|
+
validateDefaultSlot(r, inner.decodeStream(r), def);
|
|
1183
|
+
return;
|
|
1184
|
+
}
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
function magic(inner, constant, check = true) {
|
|
1188
|
+
if (!isCoder(inner))
|
|
1189
|
+
throw new TypeError(`magic: invalid inner value ${inner}`);
|
|
1190
|
+
if (typeof check !== "boolean")
|
|
1191
|
+
throw new TypeError(`magic: expected boolean, got ${typeof check}`);
|
|
1192
|
+
return wrap({
|
|
1193
|
+
size: inner.size,
|
|
1194
|
+
encodeStream: (w, _value) => inner.encodeStream(w, constant),
|
|
1195
|
+
decodeStream: (r) => {
|
|
1196
|
+
const value = inner.decodeStream(r);
|
|
1197
|
+
const valueObj = value !== null && typeof value === "object" && !isBytes(value);
|
|
1198
|
+
const constantObj = constant !== null && typeof constant === "object" && !isBytes(constant);
|
|
1199
|
+
const canCompare = !valueObj || !constantObj;
|
|
1200
|
+
if (check && canCompare && !equal(value, constant)) {
|
|
1201
|
+
throw r.err(`magic: invalid value: ${value} !== ${constant}`);
|
|
1202
|
+
}
|
|
1203
|
+
return;
|
|
1204
|
+
},
|
|
1205
|
+
validate: (value) => {
|
|
1206
|
+
if (value !== undefined)
|
|
1207
|
+
throw new Error(`magic: wrong value=${typeof value}`);
|
|
1208
|
+
return value;
|
|
1209
|
+
}
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
function sizeof(fields) {
|
|
1213
|
+
let size = 0;
|
|
1214
|
+
for (const f of fields) {
|
|
1215
|
+
if (f.size === undefined)
|
|
1216
|
+
return;
|
|
1217
|
+
if (!isNum(f.size))
|
|
1218
|
+
throw new Error(`sizeof: wrong element size=${f.size}`);
|
|
1219
|
+
size += f.size;
|
|
1220
|
+
}
|
|
1221
|
+
return size;
|
|
1222
|
+
}
|
|
1223
|
+
function struct(fields) {
|
|
1224
|
+
if (!isPlainObject(fields))
|
|
1225
|
+
throw new TypeError(`struct: expected plain object, got ${fields}`);
|
|
1226
|
+
const coders = [];
|
|
1227
|
+
for (const name in fields) {
|
|
1228
|
+
validateFieldName(name, "struct: field");
|
|
1229
|
+
if (!isCoder(fields[name]))
|
|
1230
|
+
throw new TypeError(`struct: field ${name} is not CoderType`);
|
|
1231
|
+
coders.push(fields[name]);
|
|
1232
|
+
}
|
|
1233
|
+
return wrap({
|
|
1234
|
+
size: sizeof(coders),
|
|
1235
|
+
encodeStream: (w, value) => {
|
|
1236
|
+
const _w = w;
|
|
1237
|
+
_w.pushObj(value, () => {
|
|
1238
|
+
for (const name in fields) {
|
|
1239
|
+
_w.enterField(name);
|
|
1240
|
+
fields[name].encodeStream(w, value[name]);
|
|
1241
|
+
_w.exitField();
|
|
1242
|
+
}
|
|
1243
|
+
});
|
|
1244
|
+
},
|
|
1245
|
+
decodeStream: (r) => {
|
|
1246
|
+
const res = {};
|
|
1247
|
+
const _r = r;
|
|
1248
|
+
_r.pushObj(res, () => {
|
|
1249
|
+
for (const name in fields) {
|
|
1250
|
+
_r.enterField(name);
|
|
1251
|
+
res[name] = fields[name].decodeStream(r);
|
|
1252
|
+
_r.exitField();
|
|
1253
|
+
}
|
|
1254
|
+
});
|
|
1255
|
+
return res;
|
|
1256
|
+
},
|
|
1257
|
+
validate: (value) => {
|
|
1258
|
+
if (typeof value !== "object" || value === null)
|
|
1259
|
+
throw new Error(`struct: invalid value ${value}`);
|
|
1260
|
+
return value;
|
|
1261
|
+
}
|
|
1262
|
+
});
|
|
1263
|
+
}
|
|
1264
|
+
function array(len, inner) {
|
|
1265
|
+
if (!isCoder(inner))
|
|
1266
|
+
throw new TypeError(`array: invalid inner value ${inner}`);
|
|
1267
|
+
const terminator = isBytes(len) ? Uint8Array.from(len) : undefined;
|
|
1268
|
+
const _length = lengthCoder(typeof len === "string" ? `../${len}` : terminator || len);
|
|
1269
|
+
if (len === null && inner.size === 0)
|
|
1270
|
+
throw new Error("array: null length cannot use zero-size inner");
|
|
1271
|
+
if ((isCoder(len) || typeof len === "string") && inner.size === 0)
|
|
1272
|
+
throw new Error("array: dynamic length cannot use zero-size inner");
|
|
1273
|
+
return wrap({
|
|
1274
|
+
size: typeof len === "number" && inner.size !== undefined ? len * inner.size : undefined,
|
|
1275
|
+
encodeStream: (w, value) => {
|
|
1276
|
+
const _w = w;
|
|
1277
|
+
_w.pushObj(value, () => {
|
|
1278
|
+
if (!terminator)
|
|
1279
|
+
_length.encodeStream(w, value.length);
|
|
1280
|
+
for (let i = 0;i < value.length; i++) {
|
|
1281
|
+
_w.enterField(i);
|
|
1282
|
+
const elm = value[i];
|
|
1283
|
+
const startPos = _w.pos;
|
|
1284
|
+
inner.encodeStream(w, elm);
|
|
1285
|
+
if (terminator && terminator.length <= _w.pos - startPos) {
|
|
1286
|
+
const data = _w.finish(false).subarray(startPos, _w.pos);
|
|
1287
|
+
if (equalBytes(data.subarray(0, terminator.length), terminator))
|
|
1288
|
+
throw _w.err(`array: inner element encoding same as separator. elm=${elm} data=${data}`);
|
|
1289
|
+
}
|
|
1290
|
+
_w.exitField();
|
|
1291
|
+
}
|
|
1292
|
+
});
|
|
1293
|
+
if (terminator)
|
|
1294
|
+
w.bytes(terminator);
|
|
1295
|
+
},
|
|
1296
|
+
decodeStream: (r) => {
|
|
1297
|
+
const res = [];
|
|
1298
|
+
const _r = r;
|
|
1299
|
+
_r.pushObj(res, () => {
|
|
1300
|
+
if (len === null) {
|
|
1301
|
+
for (let i = 0;!r.isEnd(); i++) {
|
|
1302
|
+
_r.enterField(i);
|
|
1303
|
+
const progress = _r.progress();
|
|
1304
|
+
res.push(inner.decodeStream(r));
|
|
1305
|
+
if (_r.progress() === progress)
|
|
1306
|
+
throw r.err("array: inner decoder did not consume input");
|
|
1307
|
+
_r.exitField();
|
|
1308
|
+
if (inner.size && r.leftBytes < inner.size)
|
|
1309
|
+
break;
|
|
1310
|
+
}
|
|
1311
|
+
} else if (terminator) {
|
|
1312
|
+
for (let i = 0;; i++) {
|
|
1313
|
+
if (equalBytes(r.bytes(terminator.length, true), terminator)) {
|
|
1314
|
+
r.bytes(terminator.length);
|
|
1315
|
+
break;
|
|
1316
|
+
}
|
|
1317
|
+
_r.enterField(i);
|
|
1318
|
+
const progress = _r.progress();
|
|
1319
|
+
res.push(inner.decodeStream(r));
|
|
1320
|
+
if (_r.progress() === progress)
|
|
1321
|
+
throw r.err("array: inner decoder did not consume input");
|
|
1322
|
+
_r.exitField();
|
|
1323
|
+
}
|
|
1324
|
+
} else {
|
|
1325
|
+
_r.enterField("arrayLen");
|
|
1326
|
+
const length = _length.decodeStream(r);
|
|
1327
|
+
_r.exitField();
|
|
1328
|
+
if (inner.size && length * inner.size > r.leftBytes)
|
|
1329
|
+
throw r.err(`array: length=${length} elements of size=${inner.size} exceed ${r.leftBytes} bytes left`);
|
|
1330
|
+
for (let i = 0;i < length; i++) {
|
|
1331
|
+
_r.enterField(i);
|
|
1332
|
+
res.push(inner.decodeStream(r));
|
|
1333
|
+
_r.exitField();
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
});
|
|
1337
|
+
return res;
|
|
1338
|
+
},
|
|
1339
|
+
validate: (value) => {
|
|
1340
|
+
if (!Array.isArray(value))
|
|
1341
|
+
throw new Error(`array: invalid value ${value}`);
|
|
1342
|
+
return value;
|
|
1343
|
+
}
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
// ../../node_modules/.bun/@scure+btc-signer@2.4.1/node_modules/@scure/btc-signer/utils.js
|
|
1347
|
+
function abigint(n, title = "value") {
|
|
1348
|
+
if (typeof n !== "bigint")
|
|
1349
|
+
throw new TypeError(`"${title}" expected bigint, got type=${typeof n}`);
|
|
1350
|
+
if (n < _0n2)
|
|
1351
|
+
throw new RangeError(`"${title}" expected non-negative bigint, got ${n}`);
|
|
1352
|
+
return n;
|
|
1353
|
+
}
|
|
1354
|
+
function aarray(item, title, inner = () => {}) {
|
|
1355
|
+
if (!Array.isArray(item))
|
|
1356
|
+
throw new TypeError(`"${title}" expected array, got type=${typeof item}`);
|
|
1357
|
+
for (let i = 0;i < item.length; i++)
|
|
1358
|
+
inner(item[i], `${title}[${i}]`);
|
|
1359
|
+
return item;
|
|
1360
|
+
}
|
|
1361
|
+
function astring(value, title = "") {
|
|
1362
|
+
if (typeof value !== "string") {
|
|
1363
|
+
const prefix = title && `"${title}" `;
|
|
1364
|
+
throw new TypeError(prefix + "expected string, got type=" + typeof value);
|
|
1365
|
+
}
|
|
1366
|
+
return value;
|
|
1367
|
+
}
|
|
1368
|
+
function validateObject2(object, fields = {}, optFields = {}, _title = "object") {
|
|
1369
|
+
return validateObject(object, fields, optFields);
|
|
1370
|
+
}
|
|
1371
|
+
var Point = /* @__PURE__ */ (() => secp256k1.Point)();
|
|
1372
|
+
var Fn = /* @__PURE__ */ (() => Point.Fn)();
|
|
1373
|
+
var CURVE_ORDER = /* @__PURE__ */ (() => Point.Fn.ORDER)();
|
|
1374
|
+
var _0n2 = /* @__PURE__ */ BigInt(0);
|
|
1375
|
+
var _2n2 = /* @__PURE__ */ BigInt(2);
|
|
1376
|
+
var hasEven = (y) => y % _2n2 === _0n2;
|
|
1377
|
+
var isBytes2 = /* @__PURE__ */ (() => utils.isBytes)();
|
|
1378
|
+
var concatBytes3 = /* @__PURE__ */ (() => utils.concatBytes)();
|
|
1379
|
+
var equalBytes2 = /* @__PURE__ */ (() => utils.equalBytes)();
|
|
1380
|
+
var sha2562 = /* @__PURE__ */ (() => sha256)();
|
|
1381
|
+
var hash160 = (msg) => ripemd160(sha2562(msg));
|
|
1382
|
+
var sha256x2 = (...msgs) => sha2562(sha2562(concatBytes3(...msgs)));
|
|
1383
|
+
var pubSchnorr = (priv) => schnorr.getPublicKey(priv);
|
|
1384
|
+
var pubECDSA = (privateKey, isCompressed) => secp256k1.getPublicKey(privateKey, isCompressed);
|
|
1385
|
+
var LOW_R_BOUND = /* @__PURE__ */ (() => CURVE_ORDER / _2n2)();
|
|
1386
|
+
var hasLowR = (sig) => sig.r < LOW_R_BOUND;
|
|
1387
|
+
function signECDSA(hash, privateKey, lowR = false) {
|
|
1388
|
+
abytes2(hash, 32, "hash");
|
|
1389
|
+
let sig = secp256k1.Signature.fromBytes(secp256k1.sign(hash, privateKey, { prehash: false }));
|
|
1390
|
+
if (lowR && !hasLowR(sig)) {
|
|
1391
|
+
const extraEntropy = new Uint8Array(32);
|
|
1392
|
+
let counter = 0;
|
|
1393
|
+
while (!hasLowR(sig)) {
|
|
1394
|
+
extraEntropy.set(U32LE.encode(counter++));
|
|
1395
|
+
sig = secp256k1.Signature.fromBytes(secp256k1.sign(hash, privateKey, { prehash: false, extraEntropy }));
|
|
1396
|
+
if (counter > 4294967295)
|
|
1397
|
+
throw new Error("lowR counter overflow: report the error");
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
return sig.toBytes("der");
|
|
1401
|
+
}
|
|
1402
|
+
var signSchnorr = (message, secretKey, auxRand) => schnorr.sign(message, secretKey, auxRand);
|
|
1403
|
+
var tagSchnorr = (tag, ...messages) => schnorr.utils.taggedHash(tag, ...messages);
|
|
1404
|
+
var PubT = /* @__PURE__ */ (() => Object.freeze({
|
|
1405
|
+
ecdsa: 0,
|
|
1406
|
+
schnorr: 1
|
|
1407
|
+
}))();
|
|
1408
|
+
function validatePubkey(pub, type) {
|
|
1409
|
+
const len = pub.length;
|
|
1410
|
+
if (type === PubT.ecdsa) {
|
|
1411
|
+
if (len === 32)
|
|
1412
|
+
throw new RangeError("Expected non-Schnorr key");
|
|
1413
|
+
Point.fromBytes(pub);
|
|
1414
|
+
return pub;
|
|
1415
|
+
} else if (type === PubT.schnorr) {
|
|
1416
|
+
if (len !== 32)
|
|
1417
|
+
throw new RangeError("Expected 32-byte Schnorr key");
|
|
1418
|
+
schnorr.utils.lift_x(bytesToNumberBE(pub));
|
|
1419
|
+
return pub;
|
|
1420
|
+
} else {
|
|
1421
|
+
throw new TypeError("Unknown key type");
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
function tapTweak(a, b) {
|
|
1425
|
+
const u = schnorr.utils;
|
|
1426
|
+
const t = u.taggedHash("TapTweak", a, b);
|
|
1427
|
+
const tn = bytesToNumberBE(t);
|
|
1428
|
+
if (tn >= CURVE_ORDER)
|
|
1429
|
+
throw new Error("tweak higher than curve order");
|
|
1430
|
+
return tn;
|
|
1431
|
+
}
|
|
1432
|
+
function taprootTweakPrivKey(privKey, merkleRoot = Uint8Array.of()) {
|
|
1433
|
+
const u = schnorr.utils;
|
|
1434
|
+
abytes2(privKey, 32, "privKey");
|
|
1435
|
+
const seckey0 = bytesToNumberBE(privKey);
|
|
1436
|
+
const P = Point.BASE.multiply(seckey0);
|
|
1437
|
+
const seckey = hasEven(P.y) ? seckey0 : Fn.neg(seckey0);
|
|
1438
|
+
const xP = u.pointToBytes(P);
|
|
1439
|
+
const t = tapTweak(xP, merkleRoot);
|
|
1440
|
+
return numberToBytesBE(Fn.add(seckey, t), 32);
|
|
1441
|
+
}
|
|
1442
|
+
function taprootTweakPubkey(pubKey, h) {
|
|
1443
|
+
const u = schnorr.utils;
|
|
1444
|
+
abytes2(pubKey, 32, "pubKey");
|
|
1445
|
+
const t = tapTweak(pubKey, h);
|
|
1446
|
+
const P = u.lift_x(bytesToNumberBE(pubKey));
|
|
1447
|
+
const Q = P.add(Point.BASE.multiply(t));
|
|
1448
|
+
const parity = hasEven(Q.y) ? 0 : 1;
|
|
1449
|
+
return [u.pointToBytes(Q), parity];
|
|
1450
|
+
}
|
|
1451
|
+
var INTERNAL_TAPROOT_NUMS = /* @__PURE__ */ (() => sha2562(Point.BASE.toBytes(false)))();
|
|
1452
|
+
function taprootNumsKey() {
|
|
1453
|
+
return Uint8Array.from(INTERNAL_TAPROOT_NUMS);
|
|
1454
|
+
}
|
|
1455
|
+
var NETWORK2 = /* @__PURE__ */ Object.freeze({
|
|
1456
|
+
bech32: "bc",
|
|
1457
|
+
pubKeyHash: 0,
|
|
1458
|
+
scriptHash: 5,
|
|
1459
|
+
wif: 128
|
|
1460
|
+
});
|
|
1461
|
+
var TEST_NETWORK2 = /* @__PURE__ */ Object.freeze({
|
|
1462
|
+
bech32: "tb",
|
|
1463
|
+
pubKeyHash: 111,
|
|
1464
|
+
scriptHash: 196,
|
|
1465
|
+
wif: 239
|
|
1466
|
+
});
|
|
1467
|
+
function compareBytes(a, b) {
|
|
1468
|
+
if (!isBytes2(a) || !isBytes2(b))
|
|
1469
|
+
throw new TypeError(`cmp: wrong type a=${typeof a} b=${typeof b}`);
|
|
1470
|
+
const len = Math.min(a.length, b.length);
|
|
1471
|
+
for (let i = 0;i < len; i++)
|
|
1472
|
+
if (a[i] != b[i])
|
|
1473
|
+
return Math.sign(a[i] - b[i]);
|
|
1474
|
+
return Math.sign(a.length - b.length);
|
|
1475
|
+
}
|
|
1476
|
+
function reverseObject(obj) {
|
|
1477
|
+
const res = Object.create(null);
|
|
1478
|
+
for (const k in obj) {
|
|
1479
|
+
if (res[obj[k]] !== undefined)
|
|
1480
|
+
throw new Error("duplicate key");
|
|
1481
|
+
res[obj[k]] = k;
|
|
1482
|
+
}
|
|
1483
|
+
return res;
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
// ../../node_modules/.bun/@scure+btc-signer@2.4.1/node_modules/@scure/btc-signer/script.js
|
|
1487
|
+
var _0n3 = /* @__PURE__ */ BigInt(0);
|
|
1488
|
+
var _1n2 = /* @__PURE__ */ BigInt(1);
|
|
1489
|
+
var _2n3 = /* @__PURE__ */ BigInt(2);
|
|
1490
|
+
var _8n2 = /* @__PURE__ */ BigInt(8);
|
|
1491
|
+
var U8_MAX = /* @__PURE__ */ BigInt(255);
|
|
1492
|
+
var COMPACT_DIRECT_MAX = /* @__PURE__ */ BigInt(252);
|
|
1493
|
+
var OP = /* @__PURE__ */ Object.freeze({
|
|
1494
|
+
OP_0: 0,
|
|
1495
|
+
PUSHDATA1: 76,
|
|
1496
|
+
PUSHDATA2: 77,
|
|
1497
|
+
PUSHDATA4: 78,
|
|
1498
|
+
"1NEGATE": 79,
|
|
1499
|
+
RESERVED: 80,
|
|
1500
|
+
OP_1: 81,
|
|
1501
|
+
OP_2: 82,
|
|
1502
|
+
OP_3: 83,
|
|
1503
|
+
OP_4: 84,
|
|
1504
|
+
OP_5: 85,
|
|
1505
|
+
OP_6: 86,
|
|
1506
|
+
OP_7: 87,
|
|
1507
|
+
OP_8: 88,
|
|
1508
|
+
OP_9: 89,
|
|
1509
|
+
OP_10: 90,
|
|
1510
|
+
OP_11: 91,
|
|
1511
|
+
OP_12: 92,
|
|
1512
|
+
OP_13: 93,
|
|
1513
|
+
OP_14: 94,
|
|
1514
|
+
OP_15: 95,
|
|
1515
|
+
OP_16: 96,
|
|
1516
|
+
NOP: 97,
|
|
1517
|
+
VER: 98,
|
|
1518
|
+
IF: 99,
|
|
1519
|
+
NOTIF: 100,
|
|
1520
|
+
VERIF: 101,
|
|
1521
|
+
VERNOTIF: 102,
|
|
1522
|
+
ELSE: 103,
|
|
1523
|
+
ENDIF: 104,
|
|
1524
|
+
VERIFY: 105,
|
|
1525
|
+
RETURN: 106,
|
|
1526
|
+
TOALTSTACK: 107,
|
|
1527
|
+
FROMALTSTACK: 108,
|
|
1528
|
+
"2DROP": 109,
|
|
1529
|
+
"2DUP": 110,
|
|
1530
|
+
"3DUP": 111,
|
|
1531
|
+
"2OVER": 112,
|
|
1532
|
+
"2ROT": 113,
|
|
1533
|
+
"2SWAP": 114,
|
|
1534
|
+
IFDUP: 115,
|
|
1535
|
+
DEPTH: 116,
|
|
1536
|
+
DROP: 117,
|
|
1537
|
+
DUP: 118,
|
|
1538
|
+
NIP: 119,
|
|
1539
|
+
OVER: 120,
|
|
1540
|
+
PICK: 121,
|
|
1541
|
+
ROLL: 122,
|
|
1542
|
+
ROT: 123,
|
|
1543
|
+
SWAP: 124,
|
|
1544
|
+
TUCK: 125,
|
|
1545
|
+
CAT: 126,
|
|
1546
|
+
SUBSTR: 127,
|
|
1547
|
+
LEFT: 128,
|
|
1548
|
+
RIGHT: 129,
|
|
1549
|
+
SIZE: 130,
|
|
1550
|
+
INVERT: 131,
|
|
1551
|
+
AND: 132,
|
|
1552
|
+
OR: 133,
|
|
1553
|
+
XOR: 134,
|
|
1554
|
+
EQUAL: 135,
|
|
1555
|
+
EQUALVERIFY: 136,
|
|
1556
|
+
RESERVED1: 137,
|
|
1557
|
+
RESERVED2: 138,
|
|
1558
|
+
"1ADD": 139,
|
|
1559
|
+
"1SUB": 140,
|
|
1560
|
+
"2MUL": 141,
|
|
1561
|
+
"2DIV": 142,
|
|
1562
|
+
NEGATE: 143,
|
|
1563
|
+
ABS: 144,
|
|
1564
|
+
NOT: 145,
|
|
1565
|
+
"0NOTEQUAL": 146,
|
|
1566
|
+
ADD: 147,
|
|
1567
|
+
SUB: 148,
|
|
1568
|
+
MUL: 149,
|
|
1569
|
+
DIV: 150,
|
|
1570
|
+
MOD: 151,
|
|
1571
|
+
LSHIFT: 152,
|
|
1572
|
+
RSHIFT: 153,
|
|
1573
|
+
BOOLAND: 154,
|
|
1574
|
+
BOOLOR: 155,
|
|
1575
|
+
NUMEQUAL: 156,
|
|
1576
|
+
NUMEQUALVERIFY: 157,
|
|
1577
|
+
NUMNOTEQUAL: 158,
|
|
1578
|
+
LESSTHAN: 159,
|
|
1579
|
+
GREATERTHAN: 160,
|
|
1580
|
+
LESSTHANOREQUAL: 161,
|
|
1581
|
+
GREATERTHANOREQUAL: 162,
|
|
1582
|
+
MIN: 163,
|
|
1583
|
+
MAX: 164,
|
|
1584
|
+
WITHIN: 165,
|
|
1585
|
+
RIPEMD160: 166,
|
|
1586
|
+
SHA1: 167,
|
|
1587
|
+
SHA256: 168,
|
|
1588
|
+
HASH160: 169,
|
|
1589
|
+
HASH256: 170,
|
|
1590
|
+
CODESEPARATOR: 171,
|
|
1591
|
+
CHECKSIG: 172,
|
|
1592
|
+
CHECKSIGVERIFY: 173,
|
|
1593
|
+
CHECKMULTISIG: 174,
|
|
1594
|
+
CHECKMULTISIGVERIFY: 175,
|
|
1595
|
+
NOP1: 176,
|
|
1596
|
+
CHECKLOCKTIMEVERIFY: 177,
|
|
1597
|
+
CHECKSEQUENCEVERIFY: 178,
|
|
1598
|
+
NOP4: 179,
|
|
1599
|
+
NOP5: 180,
|
|
1600
|
+
NOP6: 181,
|
|
1601
|
+
NOP7: 182,
|
|
1602
|
+
NOP8: 183,
|
|
1603
|
+
NOP9: 184,
|
|
1604
|
+
NOP10: 185,
|
|
1605
|
+
CHECKSIGADD: 186,
|
|
1606
|
+
INVALID: 255
|
|
1607
|
+
});
|
|
1608
|
+
var OPNames = /* @__PURE__ */ (() => Object.freeze(reverseObject(OP)))();
|
|
1609
|
+
function ScriptNum2(bytesLimit = 6, forceMinimal = false) {
|
|
1610
|
+
return wrap({
|
|
1611
|
+
encodeStream: (w, value) => {
|
|
1612
|
+
if (value === _0n3)
|
|
1613
|
+
return;
|
|
1614
|
+
const neg = value < 0;
|
|
1615
|
+
const val = BigInt(value);
|
|
1616
|
+
const nums = [];
|
|
1617
|
+
for (let abs = neg ? -val : val;abs; abs >>= _8n2)
|
|
1618
|
+
nums.push(Number(abs & U8_MAX));
|
|
1619
|
+
if (nums[nums.length - 1] >= 128)
|
|
1620
|
+
nums.push(neg ? 128 : 0);
|
|
1621
|
+
else if (neg)
|
|
1622
|
+
nums[nums.length - 1] |= 128;
|
|
1623
|
+
w.bytes(new Uint8Array(nums));
|
|
1624
|
+
},
|
|
1625
|
+
decodeStream: (r) => {
|
|
1626
|
+
const len = r.leftBytes;
|
|
1627
|
+
if (len > bytesLimit)
|
|
1628
|
+
throw new Error(`ScriptNum: number (${len}) bigger than limit=${bytesLimit}`);
|
|
1629
|
+
if (len === 0)
|
|
1630
|
+
return _0n3;
|
|
1631
|
+
const data = r.bytes(len);
|
|
1632
|
+
if (forceMinimal) {
|
|
1633
|
+
if ((data[len - 1] & 127) === 0) {
|
|
1634
|
+
if (len <= 1 || (data[len - 2] & 128) === 0)
|
|
1635
|
+
throw new Error("Non-minimally encoded ScriptNum");
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
let res = _0n3;
|
|
1639
|
+
for (let i = 0;i < len; ++i)
|
|
1640
|
+
res |= BigInt(data[i]) << _8n2 * BigInt(i);
|
|
1641
|
+
if (data[len - 1] >= 128) {
|
|
1642
|
+
res &= _2n3 ** BigInt(len * 8) - _1n2 >> _1n2;
|
|
1643
|
+
res = -res;
|
|
1644
|
+
}
|
|
1645
|
+
return res;
|
|
1646
|
+
}
|
|
1647
|
+
});
|
|
1648
|
+
}
|
|
1649
|
+
function OpToNum(op, bytesLimit = 4, forceMinimal = true) {
|
|
1650
|
+
if (typeof op === "number")
|
|
1651
|
+
return op;
|
|
1652
|
+
if (isBytes2(op)) {
|
|
1653
|
+
try {
|
|
1654
|
+
const val = ScriptNum2(bytesLimit, forceMinimal).decode(op);
|
|
1655
|
+
if (val > Number.MAX_SAFE_INTEGER || val < -Number.MAX_SAFE_INTEGER)
|
|
1656
|
+
return;
|
|
1657
|
+
return Number(val);
|
|
1658
|
+
} catch (e) {
|
|
1659
|
+
return;
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
return;
|
|
1663
|
+
}
|
|
1664
|
+
var scriptPushLen = (op, read) => {
|
|
1665
|
+
if (!(OP.OP_0 < op && op <= OP.PUSHDATA4))
|
|
1666
|
+
return;
|
|
1667
|
+
if (op < OP.PUSHDATA1)
|
|
1668
|
+
return op;
|
|
1669
|
+
if (op === OP.PUSHDATA1)
|
|
1670
|
+
return read(1);
|
|
1671
|
+
if (op === OP.PUSHDATA2)
|
|
1672
|
+
return read(2);
|
|
1673
|
+
if (op === OP.PUSHDATA4)
|
|
1674
|
+
return read(4);
|
|
1675
|
+
throw new Error("Should be not possible");
|
|
1676
|
+
};
|
|
1677
|
+
var Script2 = /* @__PURE__ */ (() => Object.freeze(wrap({
|
|
1678
|
+
encodeStream: (w, value) => {
|
|
1679
|
+
aarray(value, "value");
|
|
1680
|
+
for (let o of value) {
|
|
1681
|
+
if (typeof o === "string") {
|
|
1682
|
+
const op = OP[o];
|
|
1683
|
+
if (typeof op !== "number")
|
|
1684
|
+
throw new Error(`Unknown opcode=${o}`);
|
|
1685
|
+
w.byte(op);
|
|
1686
|
+
continue;
|
|
1687
|
+
} else if (typeof o === "number") {
|
|
1688
|
+
if (o === 0) {
|
|
1689
|
+
w.byte(0);
|
|
1690
|
+
continue;
|
|
1691
|
+
} else if (o === -1) {
|
|
1692
|
+
w.byte(OP["1NEGATE"]);
|
|
1693
|
+
continue;
|
|
1694
|
+
} else if (1 <= o && o <= 16) {
|
|
1695
|
+
w.byte(OP.OP_1 - 1 + o);
|
|
1696
|
+
continue;
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
if (typeof o === "number")
|
|
1700
|
+
o = ScriptNum2().encode(BigInt(o));
|
|
1701
|
+
abytes2(o, undefined, "value");
|
|
1702
|
+
const len = o.length;
|
|
1703
|
+
if (len < OP.PUSHDATA1)
|
|
1704
|
+
w.byte(len);
|
|
1705
|
+
else if (len <= 255) {
|
|
1706
|
+
w.byte(OP.PUSHDATA1);
|
|
1707
|
+
w.byte(len);
|
|
1708
|
+
} else if (len <= 65535) {
|
|
1709
|
+
w.byte(OP.PUSHDATA2);
|
|
1710
|
+
w.bytes(U16LE.encode(len));
|
|
1711
|
+
} else {
|
|
1712
|
+
w.byte(OP.PUSHDATA4);
|
|
1713
|
+
w.bytes(U32LE.encode(len));
|
|
1714
|
+
}
|
|
1715
|
+
w.bytes(o);
|
|
1716
|
+
}
|
|
1717
|
+
},
|
|
1718
|
+
decodeStream: (r) => {
|
|
1719
|
+
const out = [];
|
|
1720
|
+
while (!r.isEnd()) {
|
|
1721
|
+
const cur = r.byte();
|
|
1722
|
+
const len = scriptPushLen(cur, (bytes) => {
|
|
1723
|
+
if (bytes === 1)
|
|
1724
|
+
return U8.decodeStream(r);
|
|
1725
|
+
if (bytes === 2)
|
|
1726
|
+
return U16LE.decodeStream(r);
|
|
1727
|
+
return U32LE.decodeStream(r);
|
|
1728
|
+
});
|
|
1729
|
+
if (len !== undefined) {
|
|
1730
|
+
out.push(r.bytes(len));
|
|
1731
|
+
} else if (cur === 0) {
|
|
1732
|
+
out.push(0);
|
|
1733
|
+
} else if (OP.OP_1 <= cur && cur <= OP.OP_16) {
|
|
1734
|
+
out.push(cur - (OP.OP_1 - 1));
|
|
1735
|
+
} else {
|
|
1736
|
+
const op = OPNames[cur];
|
|
1737
|
+
if (op === undefined)
|
|
1738
|
+
throw new Error(`Unknown opcode=${cur.toString(16)}`);
|
|
1739
|
+
out.push(op);
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
return out;
|
|
1743
|
+
}
|
|
1744
|
+
})))();
|
|
1745
|
+
var CompactSize = /* @__PURE__ */ (() => {
|
|
1746
|
+
const limits = {
|
|
1747
|
+
253: [253, 2, BigInt(253), BigInt(65535)],
|
|
1748
|
+
254: [254, 4, BigInt(65536), BigInt(4294967295)],
|
|
1749
|
+
255: [255, 8, BigInt(4294967296), BigInt("0xffffffffffffffff")]
|
|
1750
|
+
};
|
|
1751
|
+
const limitsList = Object.values(limits);
|
|
1752
|
+
return Object.freeze(wrap({
|
|
1753
|
+
encodeStream: (w, value) => {
|
|
1754
|
+
if (typeof value === "number")
|
|
1755
|
+
value = BigInt(value);
|
|
1756
|
+
if (_0n3 <= value && value <= COMPACT_DIRECT_MAX)
|
|
1757
|
+
return w.byte(Number(value));
|
|
1758
|
+
for (const [flag, bytes, start, stop] of limitsList) {
|
|
1759
|
+
if (start > value || value > stop)
|
|
1760
|
+
continue;
|
|
1761
|
+
w.byte(flag);
|
|
1762
|
+
for (let i = 0;i < bytes; i++)
|
|
1763
|
+
w.byte(Number(value >> _8n2 * BigInt(i) & U8_MAX));
|
|
1764
|
+
return;
|
|
1765
|
+
}
|
|
1766
|
+
throw w.err(`VarInt too big: ${value}`);
|
|
1767
|
+
},
|
|
1768
|
+
decodeStream: (r) => {
|
|
1769
|
+
const b0 = r.byte();
|
|
1770
|
+
if (b0 <= 252)
|
|
1771
|
+
return BigInt(b0);
|
|
1772
|
+
const [_, bytes, start] = limits[b0];
|
|
1773
|
+
let num = _0n3;
|
|
1774
|
+
for (let i = 0;i < bytes; i++)
|
|
1775
|
+
num |= BigInt(r.byte()) << _8n2 * BigInt(i);
|
|
1776
|
+
if (num < start)
|
|
1777
|
+
throw r.err(`Wrong CompactSize(${8 * bytes})`);
|
|
1778
|
+
return num;
|
|
1779
|
+
}
|
|
1780
|
+
}));
|
|
1781
|
+
})();
|
|
1782
|
+
var CompactSizeLen = /* @__PURE__ */ (() => Object.freeze(apply(CompactSize, coders.numberBigint)))();
|
|
1783
|
+
var _VarBytes = /* @__PURE__ */ (() => Object.freeze(createBytes(CompactSize)))();
|
|
1784
|
+
var VarBytes = _VarBytes;
|
|
1785
|
+
var _RawWitness = /* @__PURE__ */ (() => Object.freeze(array(CompactSizeLen, _VarBytes)))();
|
|
1786
|
+
var RawWitness = _RawWitness;
|
|
1787
|
+
var BTCArray = (t) => array(CompactSize, t);
|
|
1788
|
+
var RawInput = /* @__PURE__ */ (() => Object.freeze(struct({
|
|
1789
|
+
txid: createBytes(32, true),
|
|
1790
|
+
index: U32LE,
|
|
1791
|
+
finalScriptSig: _VarBytes,
|
|
1792
|
+
sequence: U32LE
|
|
1793
|
+
})))();
|
|
1794
|
+
var RawOutput = /* @__PURE__ */ (() => Object.freeze(struct({ amount: U64LE, script: _VarBytes })))();
|
|
1795
|
+
var _RawTx = /* @__PURE__ */ (() => struct({
|
|
1796
|
+
version: I32LE,
|
|
1797
|
+
segwitFlag: flag(new Uint8Array([0, 1])),
|
|
1798
|
+
inputs: BTCArray(RawInput),
|
|
1799
|
+
outputs: BTCArray(RawOutput),
|
|
1800
|
+
witnesses: flagged("segwitFlag", array("inputs/length", _RawWitness)),
|
|
1801
|
+
lockTime: U32LE
|
|
1802
|
+
}))();
|
|
1803
|
+
function validateRawTx(tx) {
|
|
1804
|
+
if (tx.segwitFlag && tx.witnesses && tx.witnesses.every((w) => !w.length))
|
|
1805
|
+
throw new Error("Segwit flag with only empty witness fields");
|
|
1806
|
+
return tx;
|
|
1807
|
+
}
|
|
1808
|
+
var RawTx = /* @__PURE__ */ (() => Object.freeze(validate(_RawTx, validateRawTx)))();
|
|
1809
|
+
var RawOldTx = /* @__PURE__ */ (() => Object.freeze(struct({
|
|
1810
|
+
version: I32LE,
|
|
1811
|
+
inputs: BTCArray(RawInput),
|
|
1812
|
+
outputs: BTCArray(RawOutput),
|
|
1813
|
+
lockTime: U32LE
|
|
1814
|
+
})))();
|
|
1815
|
+
|
|
1816
|
+
// ../../node_modules/.bun/@scure+btc-signer@2.4.1/node_modules/@scure/btc-signer/psbt.js
|
|
1817
|
+
var unknowns = (mode, name) => {
|
|
1818
|
+
if (mode === true)
|
|
1819
|
+
return "ignore";
|
|
1820
|
+
if (mode === false)
|
|
1821
|
+
return "strip";
|
|
1822
|
+
if (mode === "ignore" || mode === "strip" || mode === "strict")
|
|
1823
|
+
return mode;
|
|
1824
|
+
throw new Error(`PSBT: invalid ${name} policy=${mode}`);
|
|
1825
|
+
};
|
|
1826
|
+
var _0n4 = /* @__PURE__ */ BigInt(0);
|
|
1827
|
+
var _1n3 = /* @__PURE__ */ BigInt(1);
|
|
1828
|
+
var PubKeyECDSA = /* @__PURE__ */ (() => validate(createBytes(null), (pub) => validatePubkey(pub, PubT.ecdsa)))();
|
|
1829
|
+
var PubKeyECDSACompressed = /* @__PURE__ */ (() => validate(createBytes(33), (pub) => validatePubkey(pub, PubT.ecdsa)))();
|
|
1830
|
+
var PubKeySchnorr = /* @__PURE__ */ (() => validate(createBytes(32), (pub) => validatePubkey(pub, PubT.schnorr)))();
|
|
1831
|
+
var SignatureSchnorr = /* @__PURE__ */ (() => validate(createBytes(null), (sig) => {
|
|
1832
|
+
if (sig.length !== 64 && sig.length !== 65)
|
|
1833
|
+
throw new Error("Schnorr signature should be 64 or 65 bytes long");
|
|
1834
|
+
return sig;
|
|
1835
|
+
}))();
|
|
1836
|
+
var RawWitnessWire = RawWitness;
|
|
1837
|
+
var BIP32Der = /* @__PURE__ */ (() => struct({
|
|
1838
|
+
fingerprint: U32BE,
|
|
1839
|
+
path: array(null, U32LE)
|
|
1840
|
+
}))();
|
|
1841
|
+
var TaprootBIP32Der = /* @__PURE__ */ (() => struct({
|
|
1842
|
+
hashes: array(CompactSizeLen, createBytes(32)),
|
|
1843
|
+
der: BIP32Der
|
|
1844
|
+
}))();
|
|
1845
|
+
var GlobalXPUB = /* @__PURE__ */ (() => validate(struct({
|
|
1846
|
+
version: U32BE,
|
|
1847
|
+
depth: U8,
|
|
1848
|
+
parentFingerprint: U32BE,
|
|
1849
|
+
childNumber: U32BE,
|
|
1850
|
+
chainCode: createBytes(32),
|
|
1851
|
+
publicKey: PubKeyECDSACompressed
|
|
1852
|
+
}), (xpub) => {
|
|
1853
|
+
if (xpub.depth === 0 && xpub.parentFingerprint !== 0)
|
|
1854
|
+
throw new Error("GlobalXPUB: depth=0 requires parentFingerprint=0");
|
|
1855
|
+
if (xpub.depth === 0 && xpub.childNumber !== 0)
|
|
1856
|
+
throw new Error("GlobalXPUB: depth=0 requires childNumber=0");
|
|
1857
|
+
return xpub;
|
|
1858
|
+
}))();
|
|
1859
|
+
var tapScriptSigKey = /* @__PURE__ */ (() => struct({ pubKey: PubKeySchnorr, leafHash: createBytes(32) }))();
|
|
1860
|
+
var _TaprootControlBlock = /* @__PURE__ */ (() => struct({
|
|
1861
|
+
version: U8,
|
|
1862
|
+
internalKey: createBytes(32),
|
|
1863
|
+
merklePath: array(null, createBytes(32))
|
|
1864
|
+
}))();
|
|
1865
|
+
var TaprootControlBlock2 = /* @__PURE__ */ (() => Object.freeze(validate(_TaprootControlBlock, (cb) => {
|
|
1866
|
+
if (cb.merklePath.length > 128)
|
|
1867
|
+
throw new Error("TaprootControlBlock: merklePath should be of length 0..128 (inclusive)");
|
|
1868
|
+
return cb;
|
|
1869
|
+
})))();
|
|
1870
|
+
var tapTree = /* @__PURE__ */ (() => validate(array(null, struct({
|
|
1871
|
+
depth: U8,
|
|
1872
|
+
version: U8,
|
|
1873
|
+
script: VarBytes
|
|
1874
|
+
})), (tree) => {
|
|
1875
|
+
if (tree.length < 1)
|
|
1876
|
+
throw new Error("tapTree: expected at least one tuple");
|
|
1877
|
+
let path = Array(tree[0].depth).fill(0);
|
|
1878
|
+
let maxDepth = tree[0].depth;
|
|
1879
|
+
for (let i = 1;i < tree.length; i++) {
|
|
1880
|
+
const { depth } = tree[i];
|
|
1881
|
+
if (depth > maxDepth)
|
|
1882
|
+
maxDepth = depth;
|
|
1883
|
+
let j = path.length - 1;
|
|
1884
|
+
while (j >= 0 && path[j] === 1)
|
|
1885
|
+
j--;
|
|
1886
|
+
if (j < 0)
|
|
1887
|
+
throw new Error("tapTree: tuples must be in DFS order");
|
|
1888
|
+
const next = path.slice(0, j);
|
|
1889
|
+
next.push(1);
|
|
1890
|
+
if (depth < next.length)
|
|
1891
|
+
throw new Error("tapTree: tuples must be in DFS order");
|
|
1892
|
+
while (next.length < depth)
|
|
1893
|
+
next.push(0);
|
|
1894
|
+
path = next;
|
|
1895
|
+
}
|
|
1896
|
+
let leaves = _0n4;
|
|
1897
|
+
for (let i = 0;i < tree.length; i++)
|
|
1898
|
+
leaves += _1n3 << BigInt(maxDepth - tree[i].depth);
|
|
1899
|
+
if (leaves !== _1n3 << BigInt(maxDepth))
|
|
1900
|
+
throw new Error("tapTree: tuples must describe a complete binary tree");
|
|
1901
|
+
return tree;
|
|
1902
|
+
}))();
|
|
1903
|
+
var BytesInf = /* @__PURE__ */ createBytes(null);
|
|
1904
|
+
var ProprietaryKey = /* @__PURE__ */ (() => {
|
|
1905
|
+
const suffix = struct({
|
|
1906
|
+
identifier: createBytes(CompactSizeLen),
|
|
1907
|
+
subtype: CompactSizeLen,
|
|
1908
|
+
data: BytesInf
|
|
1909
|
+
});
|
|
1910
|
+
return validate(BytesInf, (key) => {
|
|
1911
|
+
try {
|
|
1912
|
+
suffix.decode(key);
|
|
1913
|
+
} catch (error) {
|
|
1914
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1915
|
+
throw new Error(`Proprietary key: expected BIP174 identifier and subtype, got ${message}`);
|
|
1916
|
+
}
|
|
1917
|
+
return key;
|
|
1918
|
+
});
|
|
1919
|
+
})();
|
|
1920
|
+
var Bytes20 = /* @__PURE__ */ createBytes(20);
|
|
1921
|
+
var Bytes32 = /* @__PURE__ */ createBytes(32);
|
|
1922
|
+
var Bytes64 = /* @__PURE__ */ createBytes(64);
|
|
1923
|
+
var Bytes66 = /* @__PURE__ */ createBytes(66);
|
|
1924
|
+
var MuSig2Participants = /* @__PURE__ */ (() => array(null, PubKeyECDSACompressed))();
|
|
1925
|
+
var MuSig2Key = /* @__PURE__ */ (() => apply(BytesInf, {
|
|
1926
|
+
decode: (key) => {
|
|
1927
|
+
const _key = key;
|
|
1928
|
+
return concatBytes(PubKeyECDSACompressed.encode(_key.participantPubkey), PubKeyECDSACompressed.encode(_key.aggregatePubkey), _key.leafHash === undefined ? EMPTY : Bytes32.encode(_key.leafHash));
|
|
1929
|
+
},
|
|
1930
|
+
encode: (raw) => {
|
|
1931
|
+
const _raw = raw;
|
|
1932
|
+
if (_raw.length !== 66 && _raw.length !== 98)
|
|
1933
|
+
throw new Error(`MuSig2 key: expected 66 or 98 bytes, got ${_raw.length}`);
|
|
1934
|
+
const key = {
|
|
1935
|
+
participantPubkey: PubKeyECDSACompressed.decode(_raw.subarray(0, 33)),
|
|
1936
|
+
aggregatePubkey: PubKeyECDSACompressed.decode(_raw.subarray(33, 66))
|
|
1937
|
+
};
|
|
1938
|
+
if (_raw.length === 98)
|
|
1939
|
+
key.leafHash = Bytes32.decode(_raw.subarray(66));
|
|
1940
|
+
return key;
|
|
1941
|
+
}
|
|
1942
|
+
}))();
|
|
1943
|
+
var SilentPaymentInfo = /* @__PURE__ */ (() => struct({ scanKey: PubKeyECDSACompressed, spendKey: PubKeyECDSACompressed }))();
|
|
1944
|
+
var DNSSECProof = /* @__PURE__ */ (() => struct({ name: createBytes(U8), proof: BytesInf }))();
|
|
1945
|
+
var PSBTInfo = (type, kc, vc, reqInc, allowInc, silentIgnore) => /* @__PURE__ */ Object.freeze([
|
|
1946
|
+
type,
|
|
1947
|
+
kc && typeof kc === "object" ? Object.freeze(kc) : kc,
|
|
1948
|
+
vc && typeof vc === "object" ? Object.freeze(vc) : vc,
|
|
1949
|
+
Object.freeze([...reqInc]),
|
|
1950
|
+
Object.freeze([...allowInc]),
|
|
1951
|
+
silentIgnore
|
|
1952
|
+
]);
|
|
1953
|
+
var PSBTGlobal = /* @__PURE__ */ (() => Object.freeze({
|
|
1954
|
+
unsignedTx: PSBTInfo(0, false, RawOldTx, [0], [0], false),
|
|
1955
|
+
xpub: PSBTInfo(1, GlobalXPUB, BIP32Der, [], [0, 2], false),
|
|
1956
|
+
txVersion: PSBTInfo(2, false, U32LE, [2], [2], false),
|
|
1957
|
+
fallbackLocktime: PSBTInfo(3, false, U32LE, [], [2], false),
|
|
1958
|
+
inputCount: PSBTInfo(4, false, CompactSizeLen, [2], [2], false),
|
|
1959
|
+
outputCount: PSBTInfo(5, false, CompactSizeLen, [2], [2], false),
|
|
1960
|
+
txModifiable: PSBTInfo(6, false, U8, [], [2], false),
|
|
1961
|
+
spEcdhShare: PSBTInfo(7, PubKeyECDSACompressed, PubKeyECDSACompressed, [], [2], false),
|
|
1962
|
+
spDleq: PSBTInfo(8, PubKeyECDSACompressed, Bytes64, [], [2], false),
|
|
1963
|
+
genericSignedMessage: PSBTInfo(9, false, BytesInf, [], [0, 2], false),
|
|
1964
|
+
version: PSBTInfo(251, false, U32LE, [], [0, 2], false),
|
|
1965
|
+
proprietary: PSBTInfo(252, ProprietaryKey, BytesInf, [], [0, 2], false)
|
|
1966
|
+
}))();
|
|
1967
|
+
var PSBTInput = /* @__PURE__ */ (() => Object.freeze({
|
|
1968
|
+
nonWitnessUtxo: PSBTInfo(0, false, RawTx, [], [0, 2], false),
|
|
1969
|
+
witnessUtxo: PSBTInfo(1, false, RawOutput, [], [0, 2], false),
|
|
1970
|
+
partialSig: PSBTInfo(2, PubKeyECDSA, BytesInf, [], [0, 2], false),
|
|
1971
|
+
sighashType: PSBTInfo(3, false, U32LE, [], [0, 2], false),
|
|
1972
|
+
redeemScript: PSBTInfo(4, false, BytesInf, [], [0, 2], false),
|
|
1973
|
+
witnessScript: PSBTInfo(5, false, BytesInf, [], [0, 2], false),
|
|
1974
|
+
bip32Derivation: PSBTInfo(6, PubKeyECDSA, BIP32Der, [], [0, 2], false),
|
|
1975
|
+
finalScriptSig: PSBTInfo(7, false, BytesInf, [], [0, 2], false),
|
|
1976
|
+
finalScriptWitness: PSBTInfo(8, false, RawWitnessWire, [], [0, 2], false),
|
|
1977
|
+
porCommitment: PSBTInfo(9, false, BytesInf, [], [0, 2], false),
|
|
1978
|
+
ripemd160: PSBTInfo(10, Bytes20, BytesInf, [], [0, 2], false),
|
|
1979
|
+
sha256: PSBTInfo(11, Bytes32, BytesInf, [], [0, 2], false),
|
|
1980
|
+
hash160: PSBTInfo(12, Bytes20, BytesInf, [], [0, 2], false),
|
|
1981
|
+
hash256: PSBTInfo(13, Bytes32, BytesInf, [], [0, 2], false),
|
|
1982
|
+
txid: PSBTInfo(14, false, createBytes(32, true), [2], [2], true),
|
|
1983
|
+
index: PSBTInfo(15, false, U32LE, [2], [2], true),
|
|
1984
|
+
sequence: PSBTInfo(16, false, U32LE, [], [2], true),
|
|
1985
|
+
requiredTimeLocktime: PSBTInfo(17, false, U32LE, [], [2], false),
|
|
1986
|
+
requiredHeightLocktime: PSBTInfo(18, false, U32LE, [], [2], false),
|
|
1987
|
+
tapKeySig: PSBTInfo(19, false, SignatureSchnorr, [], [0, 2], false),
|
|
1988
|
+
tapScriptSig: PSBTInfo(20, tapScriptSigKey, SignatureSchnorr, [], [0, 2], false),
|
|
1989
|
+
tapLeafScript: PSBTInfo(21, TaprootControlBlock2, BytesInf, [], [0, 2], false),
|
|
1990
|
+
tapBip32Derivation: PSBTInfo(22, PubKeySchnorr, TaprootBIP32Der, [], [0, 2], false),
|
|
1991
|
+
tapInternalKey: PSBTInfo(23, false, PubKeySchnorr, [], [0, 2], false),
|
|
1992
|
+
tapMerkleRoot: PSBTInfo(24, false, Bytes32, [], [0, 2], false),
|
|
1993
|
+
p2cKeyTweak: PSBTInfo(25, PubKeyECDSACompressed, Bytes32, [], [0, 2], false),
|
|
1994
|
+
musig2ParticipantPubkeys: PSBTInfo(26, PubKeyECDSACompressed, MuSig2Participants, [], [0, 2], false),
|
|
1995
|
+
musig2PubNonce: PSBTInfo(27, MuSig2Key, Bytes66, [], [0, 2], false),
|
|
1996
|
+
musig2PartialSig: PSBTInfo(28, MuSig2Key, Bytes32, [], [0, 2], false),
|
|
1997
|
+
spEcdhShare: PSBTInfo(29, PubKeyECDSACompressed, PubKeyECDSACompressed, [], [2], false),
|
|
1998
|
+
spDleq: PSBTInfo(30, PubKeyECDSACompressed, Bytes64, [], [2], false),
|
|
1999
|
+
spSpendBip32Derivation: PSBTInfo(31, PubKeyECDSACompressed, BIP32Der, [], [2], false),
|
|
2000
|
+
spTweak: PSBTInfo(32, false, Bytes32, [], [2], false),
|
|
2001
|
+
proprietary: PSBTInfo(252, ProprietaryKey, BytesInf, [], [0, 2], false)
|
|
2002
|
+
}))();
|
|
2003
|
+
var PSBTInputFinalKeys = /* @__PURE__ */ Object.freeze([
|
|
2004
|
+
"txid",
|
|
2005
|
+
"sequence",
|
|
2006
|
+
"index",
|
|
2007
|
+
"witnessUtxo",
|
|
2008
|
+
"nonWitnessUtxo",
|
|
2009
|
+
"requiredTimeLocktime",
|
|
2010
|
+
"requiredHeightLocktime",
|
|
2011
|
+
"finalScriptSig",
|
|
2012
|
+
"finalScriptWitness",
|
|
2013
|
+
"unknown"
|
|
2014
|
+
]);
|
|
2015
|
+
var PSBTInputSignatureKeys = /* @__PURE__ */ Object.freeze([
|
|
2016
|
+
"partialSig",
|
|
2017
|
+
"finalScriptSig",
|
|
2018
|
+
"finalScriptWitness",
|
|
2019
|
+
"tapKeySig",
|
|
2020
|
+
"tapScriptSig"
|
|
2021
|
+
]);
|
|
2022
|
+
var PSBTOutput = /* @__PURE__ */ (() => Object.freeze({
|
|
2023
|
+
redeemScript: PSBTInfo(0, false, BytesInf, [], [0, 2], false),
|
|
2024
|
+
witnessScript: PSBTInfo(1, false, BytesInf, [], [0, 2], false),
|
|
2025
|
+
bip32Derivation: PSBTInfo(2, PubKeyECDSA, BIP32Der, [], [0, 2], false),
|
|
2026
|
+
amount: PSBTInfo(3, false, I64LE, [2], [2], true),
|
|
2027
|
+
script: PSBTInfo(4, false, BytesInf, [2], [2], true),
|
|
2028
|
+
tapInternalKey: PSBTInfo(5, false, PubKeySchnorr, [], [0, 2], false),
|
|
2029
|
+
tapTree: PSBTInfo(6, false, tapTree, [], [0, 2], false),
|
|
2030
|
+
tapBip32Derivation: PSBTInfo(7, PubKeySchnorr, TaprootBIP32Der, [], [0, 2], false),
|
|
2031
|
+
musig2ParticipantPubkeys: PSBTInfo(8, PubKeyECDSACompressed, MuSig2Participants, [], [0, 2], false),
|
|
2032
|
+
spV0Info: PSBTInfo(9, false, SilentPaymentInfo, [], [2], false),
|
|
2033
|
+
spV0Label: PSBTInfo(10, false, U32LE, [], [2], false),
|
|
2034
|
+
dnssecProof: PSBTInfo(53, false, DNSSECProof, [], [0, 2], false),
|
|
2035
|
+
proprietary: PSBTInfo(252, ProprietaryKey, BytesInf, [], [0, 2], false)
|
|
2036
|
+
}))();
|
|
2037
|
+
var PSBTOutputUnsignedKeys = /* @__PURE__ */ Object.freeze([]);
|
|
2038
|
+
var PSBTKeyPair = /* @__PURE__ */ (() => array(NULL, struct({
|
|
2039
|
+
key: prefix(CompactSizeLen, struct({ type: CompactSizeLen, key: createBytes(null) })),
|
|
2040
|
+
value: createBytes(CompactSizeLen)
|
|
2041
|
+
})))();
|
|
2042
|
+
function PSBTKeyInfo(info) {
|
|
2043
|
+
const [type, kc, vc, reqInc, allowInc, silentIgnore] = info;
|
|
2044
|
+
return { type, kc, vc, reqInc, allowInc, silentIgnore };
|
|
2045
|
+
}
|
|
2046
|
+
var PSBTUnknownKey = /* @__PURE__ */ (() => struct({ type: CompactSizeLen, key: createBytes(null) }))();
|
|
2047
|
+
function PSBTKeyMap(psbtEnum) {
|
|
2048
|
+
const byType = {};
|
|
2049
|
+
for (const k in psbtEnum) {
|
|
2050
|
+
const [num, kc, vc] = psbtEnum[k];
|
|
2051
|
+
byType[num] = [k, kc, vc];
|
|
2052
|
+
}
|
|
2053
|
+
return wrap({
|
|
2054
|
+
encodeStream: (w, value) => {
|
|
2055
|
+
const _value = value;
|
|
2056
|
+
let out = [];
|
|
2057
|
+
const seen = {};
|
|
2058
|
+
const add = (key, value) => {
|
|
2059
|
+
const _value = value;
|
|
2060
|
+
const kStr = hex.encode(PSBTUnknownKey.encode(key));
|
|
2061
|
+
if (seen[kStr])
|
|
2062
|
+
throw new Error(`PSBT: duplicate key=${kStr}`);
|
|
2063
|
+
seen[kStr] = true;
|
|
2064
|
+
out.push({ key, value: _value });
|
|
2065
|
+
};
|
|
2066
|
+
for (const name in psbtEnum) {
|
|
2067
|
+
const val = _value[name];
|
|
2068
|
+
if (val === undefined)
|
|
2069
|
+
continue;
|
|
2070
|
+
const [type, kc, vc] = psbtEnum[name];
|
|
2071
|
+
if (!kc) {
|
|
2072
|
+
add({ type, key: EMPTY }, vc.encode(val));
|
|
2073
|
+
} else {
|
|
2074
|
+
const kv = val.map(([k, v]) => [
|
|
2075
|
+
kc.encode(k),
|
|
2076
|
+
vc.encode(v)
|
|
2077
|
+
]);
|
|
2078
|
+
kv.sort((a, b) => compareBytes(a[0], b[0]));
|
|
2079
|
+
for (const [key, value] of kv)
|
|
2080
|
+
add({ key, type }, value);
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
if (_value.unknown) {
|
|
2084
|
+
_value.unknown.sort((a, b) => compareBytes(a[0].key, b[0].key));
|
|
2085
|
+
for (const [k, v] of _value.unknown)
|
|
2086
|
+
add(k, v);
|
|
2087
|
+
}
|
|
2088
|
+
PSBTKeyPair.encodeStream(w, out);
|
|
2089
|
+
},
|
|
2090
|
+
decodeStream: (r) => {
|
|
2091
|
+
const raw = PSBTKeyPair.decodeStream(r);
|
|
2092
|
+
const out = {};
|
|
2093
|
+
const noKey = {};
|
|
2094
|
+
const seen = {};
|
|
2095
|
+
for (const elm of raw) {
|
|
2096
|
+
const kStr = hex.encode(PSBTUnknownKey.encode(elm.key));
|
|
2097
|
+
if (seen[kStr])
|
|
2098
|
+
throw new Error(`PSBT: duplicate key=${kStr}`);
|
|
2099
|
+
seen[kStr] = true;
|
|
2100
|
+
let name = "unknown";
|
|
2101
|
+
let key = elm.key.key;
|
|
2102
|
+
let value = elm.value;
|
|
2103
|
+
if (byType[elm.key.type]) {
|
|
2104
|
+
const [_name, kc, vc] = byType[elm.key.type];
|
|
2105
|
+
name = _name;
|
|
2106
|
+
if (!kc && key.length) {
|
|
2107
|
+
throw new Error(`PSBT: Non-empty key for ${name} (key=${hex.encode(key)} value=${hex.encode(value)}`);
|
|
2108
|
+
}
|
|
2109
|
+
key = kc ? kc.decode(key) : undefined;
|
|
2110
|
+
value = vc.decode(value);
|
|
2111
|
+
if (!kc) {
|
|
2112
|
+
if (out[name])
|
|
2113
|
+
throw new Error(`PSBT: Same keys: ${name} (key=${key} value=${value})`);
|
|
2114
|
+
out[name] = value;
|
|
2115
|
+
noKey[name] = true;
|
|
2116
|
+
continue;
|
|
2117
|
+
}
|
|
2118
|
+
} else {
|
|
2119
|
+
key = { type: elm.key.type, key: elm.key.key };
|
|
2120
|
+
}
|
|
2121
|
+
if (noKey[name])
|
|
2122
|
+
throw new Error(`PSBT: Key type with empty key and no key=${name} val=${value}`);
|
|
2123
|
+
if (!out[name])
|
|
2124
|
+
out[name] = [];
|
|
2125
|
+
out[name].push([key, value]);
|
|
2126
|
+
}
|
|
2127
|
+
return out;
|
|
2128
|
+
}
|
|
2129
|
+
});
|
|
2130
|
+
}
|
|
2131
|
+
var PSBTInputCoder = /* @__PURE__ */ (() => Object.freeze(validate(PSBTKeyMap(PSBTInput), (i) => {
|
|
2132
|
+
if (i.finalScriptWitness && !i.finalScriptWitness.length)
|
|
2133
|
+
throw new Error("validateInput: empty finalScriptWitness");
|
|
2134
|
+
if (i.partialSig && !i.partialSig.length)
|
|
2135
|
+
throw new Error("Empty partialSig");
|
|
2136
|
+
if (i.partialSig)
|
|
2137
|
+
for (const [k] of i.partialSig)
|
|
2138
|
+
validatePubkey(k, PubT.ecdsa);
|
|
2139
|
+
if (i.bip32Derivation)
|
|
2140
|
+
for (const [k] of i.bip32Derivation)
|
|
2141
|
+
validatePubkey(k, PubT.ecdsa);
|
|
2142
|
+
if (i.requiredTimeLocktime !== undefined && i.requiredTimeLocktime < 500000000)
|
|
2143
|
+
throw new Error(`validateInput: wrong timeLocktime=${i.requiredTimeLocktime}`);
|
|
2144
|
+
if (i.requiredHeightLocktime !== undefined && (i.requiredHeightLocktime <= 0 || i.requiredHeightLocktime >= 500000000))
|
|
2145
|
+
throw new Error(`validateInput: wrong heighLocktime=${i.requiredHeightLocktime}`);
|
|
2146
|
+
if (i.tapLeafScript) {
|
|
2147
|
+
for (const [k, v] of i.tapLeafScript) {
|
|
2148
|
+
if ((k.version & 254) !== v[v.length - 1])
|
|
2149
|
+
throw new Error("validateInput: tapLeafScript version mimatch");
|
|
2150
|
+
if (v[v.length - 1] & 1)
|
|
2151
|
+
throw new Error("validateInput: tapLeafScript version has parity bit!");
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
return i;
|
|
2155
|
+
})))();
|
|
2156
|
+
var PSBTOutputCoder = /* @__PURE__ */ (() => Object.freeze(validate(PSBTKeyMap(PSBTOutput), (o) => {
|
|
2157
|
+
if (o.amount !== undefined && o.amount < _0n4)
|
|
2158
|
+
throw new Error(`validateOutput: wrong amount=${o.amount}`);
|
|
2159
|
+
if (o.bip32Derivation)
|
|
2160
|
+
for (const [k] of o.bip32Derivation)
|
|
2161
|
+
validatePubkey(k, PubT.ecdsa);
|
|
2162
|
+
return o;
|
|
2163
|
+
})))();
|
|
2164
|
+
var PSBTGlobalCoder = /* @__PURE__ */ (() => validate(PSBTKeyMap(PSBTGlobal), (g) => {
|
|
2165
|
+
const version = g.version || 0;
|
|
2166
|
+
if (version === 0) {
|
|
2167
|
+
if (!g.unsignedTx)
|
|
2168
|
+
throw new Error("PSBTv0: missing unsignedTx");
|
|
2169
|
+
for (const inp of g.unsignedTx.inputs)
|
|
2170
|
+
if (inp.finalScriptSig && inp.finalScriptSig.length)
|
|
2171
|
+
throw new Error("PSBTv0: input scriptSig found in unsignedTx");
|
|
2172
|
+
}
|
|
2173
|
+
for (const [xpub, der] of g.xpub || []) {
|
|
2174
|
+
if (xpub.depth !== der.path.length)
|
|
2175
|
+
throw new Error(`PSBT_GLOBAL_XPUB: xpub depth=${xpub.depth} must match derivation path length=${der.path.length}`);
|
|
2176
|
+
}
|
|
2177
|
+
return g;
|
|
2178
|
+
}))();
|
|
2179
|
+
var _RawPSBTV0 = /* @__PURE__ */ (() => Object.freeze(struct({
|
|
2180
|
+
magic: magic(string(new Uint8Array([255])), "psbt"),
|
|
2181
|
+
global: PSBTGlobalCoder,
|
|
2182
|
+
inputs: array("global/unsignedTx/inputs/length", PSBTInputCoder),
|
|
2183
|
+
outputs: array(null, PSBTOutputCoder)
|
|
2184
|
+
})))();
|
|
2185
|
+
var _RawPSBTV2 = /* @__PURE__ */ (() => Object.freeze(struct({
|
|
2186
|
+
magic: magic(string(new Uint8Array([255])), "psbt"),
|
|
2187
|
+
global: PSBTGlobalCoder,
|
|
2188
|
+
inputs: array("global/inputCount", PSBTInputCoder),
|
|
2189
|
+
outputs: array("global/outputCount", PSBTOutputCoder)
|
|
2190
|
+
})))();
|
|
2191
|
+
function validatePSBTFields(version, info, lst) {
|
|
2192
|
+
const _lst = lst;
|
|
2193
|
+
for (const k in _lst) {
|
|
2194
|
+
if (k === "unknown")
|
|
2195
|
+
continue;
|
|
2196
|
+
if (!info[k])
|
|
2197
|
+
continue;
|
|
2198
|
+
const { allowInc } = PSBTKeyInfo(info[k]);
|
|
2199
|
+
if (!allowInc.includes(version))
|
|
2200
|
+
throw new Error(`PSBTv${version}: field ${k} is not allowed`);
|
|
2201
|
+
}
|
|
2202
|
+
for (const k in info) {
|
|
2203
|
+
const { reqInc } = PSBTKeyInfo(info[k]);
|
|
2204
|
+
if (reqInc.includes(version) && _lst[k] === undefined)
|
|
2205
|
+
throw new Error(`PSBTv${version}: missing required field ${k}`);
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
function cleanPSBTFields(version, info, lst) {
|
|
2209
|
+
anumber(version, "version");
|
|
2210
|
+
validateObject2(info, {}, {}, "info");
|
|
2211
|
+
validateObject2(lst, {}, {}, "lst");
|
|
2212
|
+
const _lst = lst;
|
|
2213
|
+
const out = {};
|
|
2214
|
+
for (const _k in _lst) {
|
|
2215
|
+
const k = _k;
|
|
2216
|
+
if (k !== "unknown") {
|
|
2217
|
+
if (!info[k])
|
|
2218
|
+
continue;
|
|
2219
|
+
const { allowInc, silentIgnore } = PSBTKeyInfo(info[k]);
|
|
2220
|
+
if (!allowInc.includes(version)) {
|
|
2221
|
+
if (silentIgnore)
|
|
2222
|
+
continue;
|
|
2223
|
+
throw new Error(`Failed to serialize in PSBTv${version}: ${k} but versions allows inclusion=${allowInc}`);
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
out[k] = _lst[k];
|
|
2227
|
+
}
|
|
2228
|
+
return out;
|
|
2229
|
+
}
|
|
2230
|
+
function validatePSBT(tx) {
|
|
2231
|
+
const version = tx && tx.global && tx.global.version || 0;
|
|
2232
|
+
validatePSBTFields(version, PSBTGlobal, tx.global);
|
|
2233
|
+
for (const i of tx.inputs)
|
|
2234
|
+
validatePSBTFields(version, PSBTInput, i);
|
|
2235
|
+
for (const o of tx.outputs)
|
|
2236
|
+
validatePSBTFields(version, PSBTOutput, o);
|
|
2237
|
+
const inputCount = !version ? tx.global.unsignedTx.inputs.length : tx.global.inputCount;
|
|
2238
|
+
if (tx.inputs.length !== inputCount)
|
|
2239
|
+
throw new Error(`Wrong number of input maps=${tx.inputs.length}, expected=${inputCount}`);
|
|
2240
|
+
const outputCount = !version ? tx.global.unsignedTx.outputs.length : tx.global.outputCount;
|
|
2241
|
+
if (tx.outputs.length < outputCount)
|
|
2242
|
+
throw new Error("Not outputs inputs");
|
|
2243
|
+
const hasBip174InputMap = version === 0 && inputCount === 0 && Object.keys(tx.outputs[0] || {}).length === 0 && (outputCount > 0 && tx.outputs.length === outputCount + 1 || outputCount === 0 && tx.outputs.length === 2 && Object.keys(tx.outputs[1]).length === 0);
|
|
2244
|
+
if (hasBip174InputMap)
|
|
2245
|
+
return tx;
|
|
2246
|
+
const outputsLeft = tx.outputs.slice(outputCount);
|
|
2247
|
+
if (outputsLeft.length > 1 || outputsLeft.length && (version !== 0 || Object.keys(outputsLeft[0]).length))
|
|
2248
|
+
throw new Error(`Unexpected outputs left in tx=${outputsLeft}`);
|
|
2249
|
+
return tx;
|
|
2250
|
+
}
|
|
2251
|
+
function mergeKeyMap(psbtEnum, val, cur, allowedFields, unknown = "strip", proprietary = "strip") {
|
|
2252
|
+
validateObject2(psbtEnum, {}, {}, "psbtEnum");
|
|
2253
|
+
validateObject2(val, {}, {}, "val");
|
|
2254
|
+
if (cur !== undefined)
|
|
2255
|
+
validateObject2(cur, {}, {}, "cur");
|
|
2256
|
+
if (allowedFields !== undefined)
|
|
2257
|
+
aarray(allowedFields, "allowedFields");
|
|
2258
|
+
const _val = val;
|
|
2259
|
+
const _cur = cur;
|
|
2260
|
+
const _allowedFields = allowedFields;
|
|
2261
|
+
const unknownMode = unknowns(unknown, "unknown");
|
|
2262
|
+
const proprietaryMode = unknowns(proprietary, "proprietary");
|
|
2263
|
+
for (const [name, mode] of [
|
|
2264
|
+
["unknown", unknownMode],
|
|
2265
|
+
["proprietary", proprietaryMode]
|
|
2266
|
+
]) {
|
|
2267
|
+
if (mode !== "strict")
|
|
2268
|
+
continue;
|
|
2269
|
+
if (_val[name]?.length || _cur?.[name]?.length)
|
|
2270
|
+
throw new Error(`PSBT: ${name} PSBT field is not allowed in strict mode`);
|
|
2271
|
+
}
|
|
2272
|
+
const res = { ..._cur, ..._val };
|
|
2273
|
+
for (const k in psbtEnum) {
|
|
2274
|
+
const key = k;
|
|
2275
|
+
if (k === "proprietary" && proprietaryMode !== "ignore")
|
|
2276
|
+
continue;
|
|
2277
|
+
const [_, kC, vC] = psbtEnum[key];
|
|
2278
|
+
const cannotChange = _allowedFields && !_allowedFields.includes(k);
|
|
2279
|
+
if (_val[k] === undefined && k in _val) {
|
|
2280
|
+
if (cannotChange)
|
|
2281
|
+
throw new Error(`Cannot remove signed field=${k}`);
|
|
2282
|
+
delete res[k];
|
|
2283
|
+
} else if (kC) {
|
|
2284
|
+
const oldKV = _cur && _cur[k] ? _cur[k] : [];
|
|
2285
|
+
let newKV = _val[key];
|
|
2286
|
+
if (newKV) {
|
|
2287
|
+
if (!Array.isArray(newKV))
|
|
2288
|
+
throw new Error(`keyMap(${k}): KV pairs should be [k, v][]`);
|
|
2289
|
+
newKV = newKV.map((val) => {
|
|
2290
|
+
if (val.length !== 2)
|
|
2291
|
+
throw new Error(`keyMap(${k}): KV pairs should be [k, v][]`);
|
|
2292
|
+
return [
|
|
2293
|
+
typeof val[0] === "string" ? kC.decode(hex.decode(val[0])) : val[0],
|
|
2294
|
+
typeof val[1] === "string" ? vC.decode(hex.decode(val[1])) : val[1]
|
|
2295
|
+
];
|
|
2296
|
+
});
|
|
2297
|
+
const map = {};
|
|
2298
|
+
const add = (kStr, k, v) => {
|
|
2299
|
+
if (map[kStr] === undefined) {
|
|
2300
|
+
map[kStr] = [k, v];
|
|
2301
|
+
return;
|
|
2302
|
+
}
|
|
2303
|
+
const oldVal = hex.encode(vC.encode(map[kStr][1]));
|
|
2304
|
+
const newVal = hex.encode(vC.encode(v));
|
|
2305
|
+
if (oldVal !== newVal)
|
|
2306
|
+
throw new Error(`keyMap(${key}): same key=${kStr} oldVal=${oldVal} newVal=${newVal}`);
|
|
2307
|
+
};
|
|
2308
|
+
for (const [k, v] of oldKV) {
|
|
2309
|
+
const kStr = hex.encode(kC.encode(k));
|
|
2310
|
+
add(kStr, k, v);
|
|
2311
|
+
}
|
|
2312
|
+
for (const [k, v] of newKV) {
|
|
2313
|
+
const kStr = hex.encode(kC.encode(k));
|
|
2314
|
+
if (v === undefined) {
|
|
2315
|
+
if (cannotChange)
|
|
2316
|
+
throw new Error(`Cannot remove signed field=${key}/${k}`);
|
|
2317
|
+
delete map[kStr];
|
|
2318
|
+
} else {
|
|
2319
|
+
if (cannotChange && map[kStr] === undefined)
|
|
2320
|
+
throw new Error(`Cannot add signed field=${key}/${kStr}`);
|
|
2321
|
+
add(kStr, k, v);
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
res[key] = Object.values(map);
|
|
2325
|
+
}
|
|
2326
|
+
} else {
|
|
2327
|
+
if (typeof res[k] === "string")
|
|
2328
|
+
res[k] = vC.decode(hex.decode(res[k]));
|
|
2329
|
+
if (cannotChange && k in _val) {
|
|
2330
|
+
if (!_cur || _cur[k] === undefined)
|
|
2331
|
+
throw new Error(`Cannot add signed field=${k}`);
|
|
2332
|
+
let current = _cur[k];
|
|
2333
|
+
if (typeof current === "string")
|
|
2334
|
+
current = vC.decode(hex.decode(current));
|
|
2335
|
+
if (!equalBytes2(vC.encode(res[k]), vC.encode(current)))
|
|
2336
|
+
throw new Error(`Cannot change signed field=${k}`);
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
if (unknownMode === "ignore" && _val.unknown) {
|
|
2341
|
+
const map = {};
|
|
2342
|
+
for (const [k, v] of _cur?.unknown || [])
|
|
2343
|
+
map[hex.encode(PSBTUnknownKey.encode(k))] = [k, v];
|
|
2344
|
+
for (const [k, v] of _val.unknown) {
|
|
2345
|
+
const kStr = hex.encode(PSBTUnknownKey.encode(k));
|
|
2346
|
+
if (map[kStr] === undefined) {
|
|
2347
|
+
map[kStr] = [k, v];
|
|
2348
|
+
continue;
|
|
2349
|
+
}
|
|
2350
|
+
const oldVal = hex.encode(BytesInf.encode(map[kStr][1]));
|
|
2351
|
+
const newVal = hex.encode(BytesInf.encode(v));
|
|
2352
|
+
if (oldVal !== newVal)
|
|
2353
|
+
throw new Error(`keyMap(unknown): same key=${kStr} oldVal=${oldVal} newVal=${newVal}`);
|
|
2354
|
+
}
|
|
2355
|
+
res.unknown = Object.values(map);
|
|
2356
|
+
}
|
|
2357
|
+
for (const k in res) {
|
|
2358
|
+
if (!psbtEnum[k]) {
|
|
2359
|
+
if (unknownMode === "ignore" && k === "unknown")
|
|
2360
|
+
continue;
|
|
2361
|
+
delete res[k];
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2364
|
+
if (unknownMode !== "ignore")
|
|
2365
|
+
delete res.unknown;
|
|
2366
|
+
if (proprietaryMode !== "ignore")
|
|
2367
|
+
delete res.proprietary;
|
|
2368
|
+
return res;
|
|
2369
|
+
}
|
|
2370
|
+
function combineKeyMap(psbtEnum, current, other, unknown = "strip", proprietary = "strip") {
|
|
2371
|
+
validateObject2(psbtEnum, {}, {}, "psbtEnum");
|
|
2372
|
+
validateObject2(current, {}, {}, "current");
|
|
2373
|
+
validateObject2(other, {}, {}, "other");
|
|
2374
|
+
const _current = current;
|
|
2375
|
+
const _other = other;
|
|
2376
|
+
for (const k in psbtEnum) {
|
|
2377
|
+
const key = k;
|
|
2378
|
+
const [_, keyCoder, valueCoder] = psbtEnum[key];
|
|
2379
|
+
if (keyCoder || _current[key] === undefined || _other[key] === undefined)
|
|
2380
|
+
continue;
|
|
2381
|
+
let a = _current[key];
|
|
2382
|
+
let b = _other[key];
|
|
2383
|
+
if (typeof a === "string")
|
|
2384
|
+
a = valueCoder.decode(hex.decode(a));
|
|
2385
|
+
if (typeof b === "string")
|
|
2386
|
+
b = valueCoder.decode(hex.decode(b));
|
|
2387
|
+
if (!equalBytes2(valueCoder.encode(a), valueCoder.encode(b)))
|
|
2388
|
+
throw new Error(`Cannot combine conflicting field=${k}`);
|
|
2389
|
+
}
|
|
2390
|
+
return mergeKeyMap(psbtEnum, _other, _current, undefined, unknown, proprietary);
|
|
2391
|
+
}
|
|
2392
|
+
var RawPSBTV0 = /* @__PURE__ */ (() => Object.freeze(validate(_RawPSBTV0, validatePSBT)))();
|
|
2393
|
+
var RawPSBTV2 = /* @__PURE__ */ (() => Object.freeze(validate(_RawPSBTV2, validatePSBT)))();
|
|
2394
|
+
|
|
2395
|
+
// ../../node_modules/.bun/@scure+btc-signer@2.4.1/node_modules/@scure/btc-signer/payment.js
|
|
2396
|
+
var P2A_PROGRAM = /* @__PURE__ */ Uint8Array.from([78, 115]);
|
|
2397
|
+
var OutP2A = {
|
|
2398
|
+
encode(from) {
|
|
2399
|
+
if (from.length !== 2 || from[0] !== 1 || !isBytes2(from[1]) || !equalBytes2(from[1], P2A_PROGRAM))
|
|
2400
|
+
return;
|
|
2401
|
+
return { type: "p2a", script: Script2.encode(from) };
|
|
2402
|
+
},
|
|
2403
|
+
decode: (to) => {
|
|
2404
|
+
if (to.type !== "p2a")
|
|
2405
|
+
return;
|
|
2406
|
+
return [1, Uint8Array.from(P2A_PROGRAM)];
|
|
2407
|
+
}
|
|
2408
|
+
};
|
|
2409
|
+
function isValidPubkey(pub, type) {
|
|
2410
|
+
try {
|
|
2411
|
+
validatePubkey(pub, type);
|
|
2412
|
+
return true;
|
|
2413
|
+
} catch (e) {
|
|
2414
|
+
return false;
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
var OutPK = {
|
|
2418
|
+
encode(from) {
|
|
2419
|
+
if (from.length !== 2 || !isBytes2(from[0]) || !isValidPubkey(from[0], PubT.ecdsa) || from[1] !== "CHECKSIG")
|
|
2420
|
+
return;
|
|
2421
|
+
return { type: "pk", pubkey: from[0] };
|
|
2422
|
+
},
|
|
2423
|
+
decode: (to) => {
|
|
2424
|
+
if (to.type !== "pk")
|
|
2425
|
+
return;
|
|
2426
|
+
return [to.pubkey, "CHECKSIG"];
|
|
2427
|
+
}
|
|
2428
|
+
};
|
|
2429
|
+
var OutPKH = {
|
|
2430
|
+
encode(from) {
|
|
2431
|
+
if (from.length !== 5 || from[0] !== "DUP" || from[1] !== "HASH160" || !isBytes2(from[2]))
|
|
2432
|
+
return;
|
|
2433
|
+
if (from[2].length !== 20)
|
|
2434
|
+
return;
|
|
2435
|
+
if (from[3] !== "EQUALVERIFY" || from[4] !== "CHECKSIG")
|
|
2436
|
+
return;
|
|
2437
|
+
return { type: "pkh", hash: from[2] };
|
|
2438
|
+
},
|
|
2439
|
+
decode: (to) => to.type === "pkh" ? ["DUP", "HASH160", to.hash, "EQUALVERIFY", "CHECKSIG"] : undefined
|
|
2440
|
+
};
|
|
2441
|
+
var OutSH = {
|
|
2442
|
+
encode(from) {
|
|
2443
|
+
if (from.length !== 3 || from[0] !== "HASH160" || !isBytes2(from[1]) || from[2] !== "EQUAL")
|
|
2444
|
+
return;
|
|
2445
|
+
if (from[1].length !== 20)
|
|
2446
|
+
return;
|
|
2447
|
+
return { type: "sh", hash: from[1] };
|
|
2448
|
+
},
|
|
2449
|
+
decode: (to) => to.type === "sh" ? ["HASH160", to.hash, "EQUAL"] : undefined
|
|
2450
|
+
};
|
|
2451
|
+
var OutWSH = {
|
|
2452
|
+
encode(from) {
|
|
2453
|
+
if (from.length !== 2 || from[0] !== 0 || !isBytes2(from[1]))
|
|
2454
|
+
return;
|
|
2455
|
+
if (from[1].length !== 32)
|
|
2456
|
+
return;
|
|
2457
|
+
return { type: "wsh", hash: from[1] };
|
|
2458
|
+
},
|
|
2459
|
+
decode: (to) => to.type === "wsh" ? [0, to.hash] : undefined
|
|
2460
|
+
};
|
|
2461
|
+
var OutWPKH = {
|
|
2462
|
+
encode(from) {
|
|
2463
|
+
if (from.length !== 2 || from[0] !== 0 || !isBytes2(from[1]))
|
|
2464
|
+
return;
|
|
2465
|
+
if (from[1].length !== 20)
|
|
2466
|
+
return;
|
|
2467
|
+
return { type: "wpkh", hash: from[1] };
|
|
2468
|
+
},
|
|
2469
|
+
decode: (to) => to.type === "wpkh" ? [0, to.hash] : undefined
|
|
2470
|
+
};
|
|
2471
|
+
var OutMS = {
|
|
2472
|
+
encode(from) {
|
|
2473
|
+
const last = from.length - 1;
|
|
2474
|
+
if (from[last] !== "CHECKMULTISIG")
|
|
2475
|
+
return;
|
|
2476
|
+
const m = from[0];
|
|
2477
|
+
const n = from[last - 1];
|
|
2478
|
+
if (typeof m !== "number" || typeof n !== "number")
|
|
2479
|
+
return;
|
|
2480
|
+
const pubkeys = from.slice(1, -2);
|
|
2481
|
+
if (n !== pubkeys.length)
|
|
2482
|
+
return;
|
|
2483
|
+
for (const pub of pubkeys)
|
|
2484
|
+
if (!isBytes2(pub) || !isValidPubkey(pub, PubT.ecdsa))
|
|
2485
|
+
return;
|
|
2486
|
+
if (!Number.isSafeInteger(m) || m < 1 || m > n)
|
|
2487
|
+
return;
|
|
2488
|
+
return { type: "ms", m, pubkeys };
|
|
2489
|
+
},
|
|
2490
|
+
decode: (to) => to.type === "ms" ? [to.m, ...to.pubkeys, to.pubkeys.length, "CHECKMULTISIG"] : undefined
|
|
2491
|
+
};
|
|
2492
|
+
var OutTR = {
|
|
2493
|
+
encode(from) {
|
|
2494
|
+
if (from.length !== 2 || from[0] !== 1 || !isBytes2(from[1]) || from[1].length !== 32)
|
|
2495
|
+
return;
|
|
2496
|
+
if (!isValidPubkey(from[1], PubT.schnorr))
|
|
2497
|
+
return;
|
|
2498
|
+
return { type: "tr", pubkey: from[1] };
|
|
2499
|
+
},
|
|
2500
|
+
decode: (to) => to.type === "tr" ? [1, to.pubkey] : undefined
|
|
2501
|
+
};
|
|
2502
|
+
var OutTRNS = {
|
|
2503
|
+
encode(from) {
|
|
2504
|
+
const last = from.length - 1;
|
|
2505
|
+
if (from[last] !== "CHECKSIG")
|
|
2506
|
+
return;
|
|
2507
|
+
const pubkeys = [];
|
|
2508
|
+
for (let i = 0;i < last; i++) {
|
|
2509
|
+
const elm = from[i];
|
|
2510
|
+
if (i & 1) {
|
|
2511
|
+
if (elm !== "CHECKSIGVERIFY" || i === last - 1)
|
|
2512
|
+
return;
|
|
2513
|
+
continue;
|
|
2514
|
+
}
|
|
2515
|
+
if (!isBytes2(elm) || !isValidPubkey(elm, PubT.schnorr))
|
|
2516
|
+
return;
|
|
2517
|
+
pubkeys.push(elm);
|
|
2518
|
+
}
|
|
2519
|
+
if (!pubkeys.length || pubkeys.length > 999)
|
|
2520
|
+
return;
|
|
2521
|
+
return { type: "tr_ns", pubkeys };
|
|
2522
|
+
},
|
|
2523
|
+
decode: (to) => {
|
|
2524
|
+
if (to.type !== "tr_ns")
|
|
2525
|
+
return;
|
|
2526
|
+
const out = [];
|
|
2527
|
+
for (let i = 0;i < to.pubkeys.length - 1; i++)
|
|
2528
|
+
out.push(to.pubkeys[i], "CHECKSIGVERIFY");
|
|
2529
|
+
out.push(to.pubkeys[to.pubkeys.length - 1], "CHECKSIG");
|
|
2530
|
+
return out;
|
|
2531
|
+
}
|
|
2532
|
+
};
|
|
2533
|
+
var OutTRMS = {
|
|
2534
|
+
encode(from) {
|
|
2535
|
+
const last = from.length - 1;
|
|
2536
|
+
if (from[last] !== "NUMEQUAL" || from[1] !== "CHECKSIG")
|
|
2537
|
+
return;
|
|
2538
|
+
const pubkeys = [];
|
|
2539
|
+
const m = OpToNum(from[last - 1]);
|
|
2540
|
+
if (typeof m !== "number")
|
|
2541
|
+
return;
|
|
2542
|
+
for (let i = 0;i < last - 1; i++) {
|
|
2543
|
+
const elm = from[i];
|
|
2544
|
+
if (i & 1) {
|
|
2545
|
+
if (elm !== (i === 1 ? "CHECKSIG" : "CHECKSIGADD"))
|
|
2546
|
+
return;
|
|
2547
|
+
continue;
|
|
2548
|
+
}
|
|
2549
|
+
if (!isBytes2(elm) || !isValidPubkey(elm, PubT.schnorr))
|
|
2550
|
+
return;
|
|
2551
|
+
pubkeys.push(elm);
|
|
2552
|
+
}
|
|
2553
|
+
if (!Number.isSafeInteger(m) || m < 1 || m > pubkeys.length || pubkeys.length > 999)
|
|
2554
|
+
return;
|
|
2555
|
+
return { type: "tr_ms", pubkeys, m };
|
|
2556
|
+
},
|
|
2557
|
+
decode: (to) => {
|
|
2558
|
+
if (to.type !== "tr_ms")
|
|
2559
|
+
return;
|
|
2560
|
+
const out = [to.pubkeys[0], "CHECKSIG"];
|
|
2561
|
+
for (let i = 1;i < to.pubkeys.length; i++)
|
|
2562
|
+
out.push(to.pubkeys[i], "CHECKSIGADD");
|
|
2563
|
+
out.push(to.m, "NUMEQUAL");
|
|
2564
|
+
return out;
|
|
2565
|
+
}
|
|
2566
|
+
};
|
|
2567
|
+
var OutUnknown = {
|
|
2568
|
+
encode(from) {
|
|
2569
|
+
return { type: "unknown", script: Script2.encode(from) };
|
|
2570
|
+
},
|
|
2571
|
+
decode: (to) => to.type === "unknown" ? Script2.decode(to.script) : undefined
|
|
2572
|
+
};
|
|
2573
|
+
var OutScripts = /* @__PURE__ */ (() => [
|
|
2574
|
+
OutP2A,
|
|
2575
|
+
OutPK,
|
|
2576
|
+
OutPKH,
|
|
2577
|
+
OutSH,
|
|
2578
|
+
OutWSH,
|
|
2579
|
+
OutWPKH,
|
|
2580
|
+
OutMS,
|
|
2581
|
+
OutTR,
|
|
2582
|
+
OutTRNS,
|
|
2583
|
+
OutTRMS,
|
|
2584
|
+
OutUnknown
|
|
2585
|
+
])();
|
|
2586
|
+
var _OutScript = /* @__PURE__ */ (() => apply(Script2, coders.match(OutScripts)))();
|
|
2587
|
+
var OutScript2 = /* @__PURE__ */ (() => Object.freeze(validate(_OutScript, (i) => {
|
|
2588
|
+
if (i.type === "pk" && !isValidPubkey(i.pubkey, PubT.ecdsa))
|
|
2589
|
+
throw new Error("OutScript/pk: wrong key");
|
|
2590
|
+
if ((i.type === "pkh" || i.type === "sh" || i.type === "wpkh") && (!isBytes2(i.hash) || i.hash.length !== 20))
|
|
2591
|
+
throw new Error(`OutScript/${i.type}: wrong hash`);
|
|
2592
|
+
if (i.type === "wsh" && (!isBytes2(i.hash) || i.hash.length !== 32))
|
|
2593
|
+
throw new Error(`OutScript/wsh: wrong hash`);
|
|
2594
|
+
if (i.type === "tr" && (!isBytes2(i.pubkey) || !isValidPubkey(i.pubkey, PubT.schnorr)))
|
|
2595
|
+
throw new Error("OutScript/tr: wrong taproot public key");
|
|
2596
|
+
if (i.type === "ms" || i.type === "tr_ns" || i.type === "tr_ms") {
|
|
2597
|
+
if (!Array.isArray(i.pubkeys))
|
|
2598
|
+
throw new Error("OutScript/multisig: wrong pubkeys array");
|
|
2599
|
+
}
|
|
2600
|
+
if (i.type === "ms") {
|
|
2601
|
+
const n = i.pubkeys.length;
|
|
2602
|
+
for (const p of i.pubkeys)
|
|
2603
|
+
if (!isValidPubkey(p, PubT.ecdsa))
|
|
2604
|
+
throw new Error("OutScript/multisig: wrong pubkey");
|
|
2605
|
+
anumber(i.m, "m");
|
|
2606
|
+
if (i.m <= 0 || n > 16 || i.m > n)
|
|
2607
|
+
throw new Error("OutScript/multisig: invalid params");
|
|
2608
|
+
}
|
|
2609
|
+
if (i.type === "tr_ns" || i.type === "tr_ms") {
|
|
2610
|
+
const n = i.pubkeys.length;
|
|
2611
|
+
if (n > 999)
|
|
2612
|
+
throw new Error(`OutScript/${i.type}: invalid params`);
|
|
2613
|
+
for (const p of i.pubkeys)
|
|
2614
|
+
if (!isValidPubkey(p, PubT.schnorr))
|
|
2615
|
+
throw new Error(`OutScript/${i.type}: wrong pubkey`);
|
|
2616
|
+
}
|
|
2617
|
+
if (i.type === "tr_ms") {
|
|
2618
|
+
const n = i.pubkeys.length;
|
|
2619
|
+
anumber(i.m, "m");
|
|
2620
|
+
if (i.m <= 0 || i.m > n)
|
|
2621
|
+
throw new Error("OutScript/tr_ms: invalid params");
|
|
2622
|
+
}
|
|
2623
|
+
return i;
|
|
2624
|
+
})))();
|
|
2625
|
+
var _WitnessOutScript = /* @__PURE__ */ (() => Object.freeze(wrap({
|
|
2626
|
+
encodeStream: (w, value) => OutScript2.encodeStream(w, value),
|
|
2627
|
+
decodeStream: (r) => {
|
|
2628
|
+
const raw = r.bytes(r.leftBytes);
|
|
2629
|
+
const out = OutScript2.decode(raw);
|
|
2630
|
+
if (out && (out.type === "p2a" || out.type === "wpkh" || out.type === "wsh" || out.type === "tr") && !equalBytes2(raw, OutScript2.encode(out)))
|
|
2631
|
+
throw new Error("OutScript: non-canonical witness program");
|
|
2632
|
+
return out;
|
|
2633
|
+
}
|
|
2634
|
+
})))();
|
|
2635
|
+
function checkWSH(s, witnessScript) {
|
|
2636
|
+
if (!equalBytes2(s.hash, sha2562(witnessScript)))
|
|
2637
|
+
throw new Error("checkScript: wsh wrong witnessScript hash");
|
|
2638
|
+
const w = OutScript2.decode(witnessScript);
|
|
2639
|
+
if (w.type === "tr" || w.type === "tr_ns" || w.type === "tr_ms")
|
|
2640
|
+
throw new Error(`checkScript: P2${w.type} cannot be wrapped in P2SH`);
|
|
2641
|
+
if (w.type === "wpkh" || w.type === "wsh" || w.type === "sh")
|
|
2642
|
+
throw new Error(`checkScript: P2${w.type} cannot be wrapped in P2WSH`);
|
|
2643
|
+
}
|
|
2644
|
+
function checkScript(script, redeemScript, witnessScript) {
|
|
2645
|
+
let hasWsh = false;
|
|
2646
|
+
let r = undefined;
|
|
2647
|
+
if (script) {
|
|
2648
|
+
const s = _WitnessOutScript.decode(script);
|
|
2649
|
+
if (s.type === "tr_ns" || s.type === "tr_ms" || s.type === "ms" || s.type == "pk")
|
|
2650
|
+
throw new Error(`checkScript: non-wrapped ${s.type}`);
|
|
2651
|
+
if (redeemScript) {
|
|
2652
|
+
if (s.type !== "sh")
|
|
2653
|
+
throw new Error("checkScript: redeemScript without P2SH");
|
|
2654
|
+
if (!equalBytes2(s.hash, hash160(redeemScript)))
|
|
2655
|
+
throw new Error("checkScript: sh wrong redeemScript hash");
|
|
2656
|
+
r = _WitnessOutScript.decode(redeemScript);
|
|
2657
|
+
if (r?.type === "tr" || r?.type === "tr_ns" || r?.type === "tr_ms")
|
|
2658
|
+
throw new Error(`checkScript: P2${r.type} cannot be wrapped in P2SH`);
|
|
2659
|
+
if (r?.type === "sh")
|
|
2660
|
+
throw new Error("checkScript: P2SH cannot be wrapped in P2SH");
|
|
2661
|
+
}
|
|
2662
|
+
if (s.type === "wsh") {
|
|
2663
|
+
hasWsh = true;
|
|
2664
|
+
if (witnessScript)
|
|
2665
|
+
checkWSH(s, witnessScript);
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
if (redeemScript) {
|
|
2669
|
+
if (r === undefined)
|
|
2670
|
+
r = _WitnessOutScript.decode(redeemScript);
|
|
2671
|
+
if (r?.type === "wsh") {
|
|
2672
|
+
hasWsh = true;
|
|
2673
|
+
if (witnessScript)
|
|
2674
|
+
checkWSH(r, witnessScript);
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
if (witnessScript && !hasWsh)
|
|
2678
|
+
throw new Error("checkScript: witnessScript without P2WSH");
|
|
2679
|
+
}
|
|
2680
|
+
function checkTaprootScript(script, internalPubKey, allowUnknownOutputs = false, customScripts) {
|
|
2681
|
+
const out = OutScript2.decode(script);
|
|
2682
|
+
if (out.type === "unknown") {
|
|
2683
|
+
if (customScripts) {
|
|
2684
|
+
const cs = apply(Script2, coders.match(customScripts));
|
|
2685
|
+
let c;
|
|
2686
|
+
try {
|
|
2687
|
+
c = cs.decode(script);
|
|
2688
|
+
} catch (e) {
|
|
2689
|
+
c = undefined;
|
|
2690
|
+
}
|
|
2691
|
+
if (c !== undefined) {
|
|
2692
|
+
if (!astring(c.type, "c.type").startsWith("tr_"))
|
|
2693
|
+
throw new Error(`P2TR: invalid custom type=${c.type}`);
|
|
2694
|
+
return;
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2697
|
+
if (allowUnknownOutputs)
|
|
2698
|
+
return;
|
|
2699
|
+
}
|
|
2700
|
+
if (!["tr_ns", "tr_ms"].includes(out.type))
|
|
2701
|
+
throw new Error(`P2TR: invalid leaf script=${out.type}`);
|
|
2702
|
+
const outms = out;
|
|
2703
|
+
if (!allowUnknownOutputs && outms.pubkeys) {
|
|
2704
|
+
for (const p of outms.pubkeys) {
|
|
2705
|
+
if (equalBytes2(p, taprootNumsKey()))
|
|
2706
|
+
throw new Error("Unspendable taproot key in leaf script");
|
|
2707
|
+
if (equalBytes2(p, internalPubKey)) {
|
|
2708
|
+
throw new Error("Using P2TR with leaf script with same key as internal key is not supported");
|
|
2709
|
+
}
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
function taprootListToTree2(taprootList) {
|
|
2714
|
+
aarray(taprootList, "taprootList", (leaf, title) => {
|
|
2715
|
+
if (Array.isArray(leaf))
|
|
2716
|
+
return;
|
|
2717
|
+
validateObject2(leaf, {}, {}, title);
|
|
2718
|
+
if (leaf.weight !== undefined)
|
|
2719
|
+
anumber(leaf.weight, title + ".weight");
|
|
2720
|
+
});
|
|
2721
|
+
if (!taprootList.length)
|
|
2722
|
+
throw new Error("taprootListToTree: empty tree");
|
|
2723
|
+
const lst = Array.from(taprootList);
|
|
2724
|
+
while (lst.length >= 2) {
|
|
2725
|
+
lst.sort((a, b) => (b.weight || 1) - (a.weight || 1));
|
|
2726
|
+
const b = lst.pop();
|
|
2727
|
+
const a = lst.pop();
|
|
2728
|
+
const weight = (a?.weight || 1) + (b?.weight || 1);
|
|
2729
|
+
lst.push({
|
|
2730
|
+
weight,
|
|
2731
|
+
childs: [a?.childs || a, b?.childs || b]
|
|
2732
|
+
});
|
|
2733
|
+
}
|
|
2734
|
+
const last = lst[0];
|
|
2735
|
+
return last?.childs || last;
|
|
2736
|
+
}
|
|
2737
|
+
function taprootAddPath(tree, path = []) {
|
|
2738
|
+
if (!tree)
|
|
2739
|
+
throw new Error(`taprootAddPath: empty tree`);
|
|
2740
|
+
if (tree.type === "leaf")
|
|
2741
|
+
return { ...tree, path };
|
|
2742
|
+
if (tree.type !== "branch")
|
|
2743
|
+
throw new Error(`taprootAddPath: wrong type=${tree}`);
|
|
2744
|
+
return {
|
|
2745
|
+
...tree,
|
|
2746
|
+
path,
|
|
2747
|
+
left: taprootAddPath(tree.left, [tree.right.hash, ...path]),
|
|
2748
|
+
right: taprootAddPath(tree.right, [tree.left.hash, ...path])
|
|
2749
|
+
};
|
|
2750
|
+
}
|
|
2751
|
+
function taprootWalkTree(tree) {
|
|
2752
|
+
if (!tree)
|
|
2753
|
+
throw new Error(`taprootAddPath: empty tree`);
|
|
2754
|
+
if (tree.type === "leaf")
|
|
2755
|
+
return [tree];
|
|
2756
|
+
if (tree.type !== "branch")
|
|
2757
|
+
throw new Error(`taprootWalkTree: wrong type=${tree}`);
|
|
2758
|
+
return [...taprootWalkTree(tree.left), ...taprootWalkTree(tree.right)];
|
|
2759
|
+
}
|
|
2760
|
+
var TAPROOT_MAX_DEPTH = 128;
|
|
2761
|
+
function taprootHashTree(tree, internalPubKey, allowUnknownOutputs = false, customScripts, depth = 0) {
|
|
2762
|
+
if (depth > TAPROOT_MAX_DEPTH)
|
|
2763
|
+
throw new RangeError(`P2TR: tree depth exceeds ${TAPROOT_MAX_DEPTH}`);
|
|
2764
|
+
if (tree === undefined)
|
|
2765
|
+
throw new Error("taprootHashTree: empty tree");
|
|
2766
|
+
if (!Array.isArray(tree) && !utils.isPlainObject(tree))
|
|
2767
|
+
throw new TypeError('"tree" expected object or array, got type=' + typeof tree);
|
|
2768
|
+
if (Array.isArray(tree) && tree.length === 1)
|
|
2769
|
+
tree = tree[0];
|
|
2770
|
+
if (!Array.isArray(tree)) {
|
|
2771
|
+
validateObject2(tree, {}, {}, "tree");
|
|
2772
|
+
const version = tree.leafVersion;
|
|
2773
|
+
const { script: leafScript } = tree;
|
|
2774
|
+
if (tree.tapLeafScript || tree.tapMerkleRoot && !equalBytes2(tree.tapMerkleRoot, EMPTY))
|
|
2775
|
+
throw new Error("P2TR: tapRoot leafScript cannot have tree");
|
|
2776
|
+
const script = typeof leafScript === "string" ? hex.decode(leafScript) : abytes2(leafScript, undefined, "tree.script");
|
|
2777
|
+
checkTaprootScript(script, internalPubKey, allowUnknownOutputs, customScripts);
|
|
2778
|
+
return {
|
|
2779
|
+
type: "leaf",
|
|
2780
|
+
version,
|
|
2781
|
+
script,
|
|
2782
|
+
hash: tapLeafHash(script, tapLeafVersion(version))
|
|
2783
|
+
};
|
|
2784
|
+
}
|
|
2785
|
+
if (tree.length !== 2)
|
|
2786
|
+
tree = taprootListToTree2(tree);
|
|
2787
|
+
if (tree.length !== 2)
|
|
2788
|
+
throw new Error("hashTree: non binary tree!");
|
|
2789
|
+
const left = taprootHashTree(tree[0], internalPubKey, allowUnknownOutputs, customScripts, depth + 1);
|
|
2790
|
+
const right = taprootHashTree(tree[1], internalPubKey, allowUnknownOutputs, customScripts, depth + 1);
|
|
2791
|
+
let [lH, rH] = [left.hash, right.hash];
|
|
2792
|
+
if (compareBytes(rH, lH) === -1)
|
|
2793
|
+
[lH, rH] = [rH, lH];
|
|
2794
|
+
return {
|
|
2795
|
+
type: "branch",
|
|
2796
|
+
left,
|
|
2797
|
+
right,
|
|
2798
|
+
hash: tagSchnorr("TapBranch", lH, rH)
|
|
2799
|
+
};
|
|
2800
|
+
}
|
|
2801
|
+
var TAP_LEAF_VERSION = 192;
|
|
2802
|
+
var tapLeafVersion = (version) => {
|
|
2803
|
+
if (version === undefined)
|
|
2804
|
+
return TAP_LEAF_VERSION;
|
|
2805
|
+
anumber(version, "leafVersion");
|
|
2806
|
+
if (version > 254 || version === 80 || !!(version & 1))
|
|
2807
|
+
throw new Error(`P2TR: invalid leafVersion=${version}`);
|
|
2808
|
+
return version;
|
|
2809
|
+
};
|
|
2810
|
+
var tapLeafHash = (script, version = TAP_LEAF_VERSION) => tagSchnorr("TapLeaf", new Uint8Array([tapLeafVersion(version)]), VarBytes.encode(script));
|
|
2811
|
+
function p2tr2(internalPubKey, tree, network = NETWORK2, allowUnknownOutputs = false, customScripts) {
|
|
2812
|
+
if (!internalPubKey && !tree)
|
|
2813
|
+
throw new Error("p2tr: should have pubKey or scriptTree (or both)");
|
|
2814
|
+
const pubKey = typeof internalPubKey === "string" ? hex.decode(internalPubKey) : internalPubKey ?? taprootNumsKey();
|
|
2815
|
+
if (!isValidPubkey(pubKey, PubT.schnorr))
|
|
2816
|
+
throw new Error("p2tr: non-schnorr pubkey");
|
|
2817
|
+
if (tree) {
|
|
2818
|
+
let hashedTree = taprootAddPath(taprootHashTree(tree, pubKey, allowUnknownOutputs, customScripts));
|
|
2819
|
+
const tapMerkleRoot = hashedTree.hash;
|
|
2820
|
+
const [tweakedPubkey, parity] = taprootTweakPubkey(pubKey, tapMerkleRoot);
|
|
2821
|
+
const tapLeafScript = [];
|
|
2822
|
+
const leaves = taprootWalkTree(hashedTree).map((l) => {
|
|
2823
|
+
const version = tapLeafVersion(l.version);
|
|
2824
|
+
const controlBlock = {
|
|
2825
|
+
version: version + parity,
|
|
2826
|
+
internalKey: pubKey,
|
|
2827
|
+
merklePath: l.path
|
|
2828
|
+
};
|
|
2829
|
+
tapLeafScript.push([controlBlock, concatBytes3(l.script, new Uint8Array([version]))]);
|
|
2830
|
+
return { ...l, controlBlock: TaprootControlBlock2.encode(controlBlock) };
|
|
2831
|
+
});
|
|
2832
|
+
return {
|
|
2833
|
+
type: "tr",
|
|
2834
|
+
script: OutScript2.encode({ type: "tr", pubkey: tweakedPubkey }),
|
|
2835
|
+
address: Address2(network).encode({ type: "tr", pubkey: tweakedPubkey }),
|
|
2836
|
+
tweakedPubkey,
|
|
2837
|
+
tapInternalKey: pubKey,
|
|
2838
|
+
leaves,
|
|
2839
|
+
tapLeafScript,
|
|
2840
|
+
tapMerkleRoot
|
|
2841
|
+
};
|
|
2842
|
+
} else {
|
|
2843
|
+
const tweakedPubkey = taprootTweakPubkey(pubKey, EMPTY)[0];
|
|
2844
|
+
return {
|
|
2845
|
+
type: "tr",
|
|
2846
|
+
script: OutScript2.encode({ type: "tr", pubkey: tweakedPubkey }),
|
|
2847
|
+
address: Address2(network).encode({ type: "tr", pubkey: tweakedPubkey }),
|
|
2848
|
+
tweakedPubkey,
|
|
2849
|
+
tapInternalKey: pubKey
|
|
2850
|
+
};
|
|
2851
|
+
}
|
|
2852
|
+
}
|
|
2853
|
+
var base58check = /* @__PURE__ */ createBase58check(sha2562);
|
|
2854
|
+
function validateWitness(version, data) {
|
|
2855
|
+
if (data.length < 2 || data.length > 40)
|
|
2856
|
+
throw new Error("Witness: invalid length");
|
|
2857
|
+
if (version > 16)
|
|
2858
|
+
throw new Error("Witness: invalid version");
|
|
2859
|
+
if (version === 0 && !(data.length === 20 || data.length === 32))
|
|
2860
|
+
throw new Error("Witness: invalid length for version");
|
|
2861
|
+
}
|
|
2862
|
+
function programToWitness(version, data, network = NETWORK2) {
|
|
2863
|
+
validateWitness(version, data);
|
|
2864
|
+
const coder = version === 0 ? bech32 : bech32m;
|
|
2865
|
+
return coder.encode(network.bech32, [version].concat(coder.toWords(data)));
|
|
2866
|
+
}
|
|
2867
|
+
function formatKey(hashed, prefix) {
|
|
2868
|
+
return base58check.encode(concatBytes3(Uint8Array.from(prefix), hashed));
|
|
2869
|
+
}
|
|
2870
|
+
function Address2(network = NETWORK2) {
|
|
2871
|
+
validateObject2(network, {}, {}, "network");
|
|
2872
|
+
return {
|
|
2873
|
+
encode(from) {
|
|
2874
|
+
validateObject2(from, {}, {}, "from");
|
|
2875
|
+
const { type } = from;
|
|
2876
|
+
astring(type, "from.type");
|
|
2877
|
+
if (type === "wpkh")
|
|
2878
|
+
return programToWitness(0, from.hash, network);
|
|
2879
|
+
else if (type === "wsh")
|
|
2880
|
+
return programToWitness(0, from.hash, network);
|
|
2881
|
+
else if (type === "tr")
|
|
2882
|
+
return programToWitness(1, from.pubkey, network);
|
|
2883
|
+
else if (type === "p2a")
|
|
2884
|
+
return programToWitness(1, P2A_PROGRAM, network);
|
|
2885
|
+
else if (type === "pkh")
|
|
2886
|
+
return formatKey(from.hash, [network.pubKeyHash]);
|
|
2887
|
+
else if (type === "sh")
|
|
2888
|
+
return formatKey(from.hash, [network.scriptHash]);
|
|
2889
|
+
throw new Error(`Unknown address type=${type}`);
|
|
2890
|
+
},
|
|
2891
|
+
decode(address) {
|
|
2892
|
+
astring(address, "address");
|
|
2893
|
+
if (address.length < 14 || address.length > 74)
|
|
2894
|
+
throw new Error("Invalid address length");
|
|
2895
|
+
if (network.bech32 && address.toLowerCase().startsWith(`${network.bech32}1`)) {
|
|
2896
|
+
let res;
|
|
2897
|
+
try {
|
|
2898
|
+
res = bech32.decode(address);
|
|
2899
|
+
if (res.words[0] !== 0)
|
|
2900
|
+
throw new Error(`bech32: wrong version=${res.words[0]}`);
|
|
2901
|
+
} catch (_) {
|
|
2902
|
+
res = bech32m.decode(address);
|
|
2903
|
+
if (res.words[0] === 0)
|
|
2904
|
+
throw new Error(`bech32m: wrong version=${res.words[0]}`);
|
|
2905
|
+
}
|
|
2906
|
+
if (res.prefix !== network.bech32)
|
|
2907
|
+
throw new Error(`wrong bech32 prefix=${res.prefix}`);
|
|
2908
|
+
const [version, ...program] = res.words;
|
|
2909
|
+
const data = bech32.fromWords(program);
|
|
2910
|
+
validateWitness(version, data);
|
|
2911
|
+
if (version === 0 && data.length === 32)
|
|
2912
|
+
return { type: "wsh", hash: data };
|
|
2913
|
+
else if (version === 0 && data.length === 20)
|
|
2914
|
+
return { type: "wpkh", hash: data };
|
|
2915
|
+
else if (version === 1 && data.length === 32)
|
|
2916
|
+
return { type: "tr", pubkey: data };
|
|
2917
|
+
else if (version === 1 && equalBytes2(data, P2A_PROGRAM))
|
|
2918
|
+
return { type: "p2a", script: Script2.encode([1, data]) };
|
|
2919
|
+
else
|
|
2920
|
+
throw new Error("Unknown witness program");
|
|
2921
|
+
}
|
|
2922
|
+
const data = base58check.decode(address);
|
|
2923
|
+
if (data.length !== 21)
|
|
2924
|
+
throw new Error("Invalid base58 address");
|
|
2925
|
+
if (data[0] === network.pubKeyHash) {
|
|
2926
|
+
return { type: "pkh", hash: data.slice(1) };
|
|
2927
|
+
} else if (data[0] === network.scriptHash) {
|
|
2928
|
+
return {
|
|
2929
|
+
type: "sh",
|
|
2930
|
+
hash: data.slice(1)
|
|
2931
|
+
};
|
|
2932
|
+
}
|
|
2933
|
+
throw new Error(`Invalid address prefix=${data[0]}`);
|
|
2934
|
+
}
|
|
2935
|
+
};
|
|
2936
|
+
}
|
|
2937
|
+
// ../../node_modules/.bun/@scure+btc-signer@2.4.1/node_modules/@scure/btc-signer/transaction.js
|
|
2938
|
+
var _0n5 = /* @__PURE__ */ BigInt(0);
|
|
2939
|
+
var _1n4 = /* @__PURE__ */ BigInt(1);
|
|
2940
|
+
var U64_MAX = /* @__PURE__ */ BigInt("0xffffffffffffffff");
|
|
2941
|
+
var EMPTY32 = /* @__PURE__ */ new Uint8Array(32);
|
|
2942
|
+
var EMPTY_OUTPUT = {
|
|
2943
|
+
amount: U64_MAX,
|
|
2944
|
+
script: EMPTY
|
|
2945
|
+
};
|
|
2946
|
+
var toVsize = (weight) => Math.ceil(weight / 4);
|
|
2947
|
+
var stripCodeSeparator = (script) => {
|
|
2948
|
+
let start = 0;
|
|
2949
|
+
const out = [];
|
|
2950
|
+
for (let i = 0;i < script.length; ) {
|
|
2951
|
+
const pos = i;
|
|
2952
|
+
const op = script[i++];
|
|
2953
|
+
if (op === OP.CODESEPARATOR) {
|
|
2954
|
+
if (start < pos)
|
|
2955
|
+
out.push(script.subarray(start, pos));
|
|
2956
|
+
start = i;
|
|
2957
|
+
continue;
|
|
2958
|
+
}
|
|
2959
|
+
const len = scriptPushLen(op, (bytes) => {
|
|
2960
|
+
if (i + bytes > script.length)
|
|
2961
|
+
throw new Error("Unexpected end of script");
|
|
2962
|
+
let len = 0;
|
|
2963
|
+
for (let j = 0;j < bytes; j++)
|
|
2964
|
+
len |= script[i + j] << 8 * j;
|
|
2965
|
+
i += bytes;
|
|
2966
|
+
return len;
|
|
2967
|
+
});
|
|
2968
|
+
if (len === undefined)
|
|
2969
|
+
continue;
|
|
2970
|
+
i += len;
|
|
2971
|
+
if (i > script.length)
|
|
2972
|
+
throw new Error("Unexpected end of script");
|
|
2973
|
+
}
|
|
2974
|
+
if (start === 0)
|
|
2975
|
+
return script;
|
|
2976
|
+
if (start < script.length)
|
|
2977
|
+
out.push(script.subarray(start));
|
|
2978
|
+
return out.length ? concatBytes3(...out) : EMPTY;
|
|
2979
|
+
};
|
|
2980
|
+
var DEFAULT_VERSION = 2;
|
|
2981
|
+
var DEFAULT_LOCKTIME = 0;
|
|
2982
|
+
var DEFAULT_SEQUENCE = 4294967295;
|
|
2983
|
+
var def = (value, def) => value === undefined ? def : value;
|
|
2984
|
+
function cloneDeep(obj) {
|
|
2985
|
+
if (Array.isArray(obj))
|
|
2986
|
+
return obj.map((i) => cloneDeep(i));
|
|
2987
|
+
else if (isBytes2(obj))
|
|
2988
|
+
return Uint8Array.from(obj);
|
|
2989
|
+
else if (["number", "bigint", "boolean", "string", "undefined"].includes(typeof obj))
|
|
2990
|
+
return obj;
|
|
2991
|
+
else if (obj === null)
|
|
2992
|
+
return obj;
|
|
2993
|
+
else if (typeof obj === "object") {
|
|
2994
|
+
return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, cloneDeep(v)]));
|
|
2995
|
+
}
|
|
2996
|
+
throw new Error(`cloneDeep: unknown type=${typeof obj}`);
|
|
2997
|
+
}
|
|
2998
|
+
var SignatureHash = /* @__PURE__ */ (() => Object.freeze({
|
|
2999
|
+
DEFAULT: 0,
|
|
3000
|
+
ALL: 1,
|
|
3001
|
+
NONE: 2,
|
|
3002
|
+
SINGLE: 3,
|
|
3003
|
+
ANYONECANPAY: 128
|
|
3004
|
+
}))();
|
|
3005
|
+
var SigHash2 = /* @__PURE__ */ (() => Object.freeze({
|
|
3006
|
+
DEFAULT: SignatureHash.DEFAULT,
|
|
3007
|
+
ALL: SignatureHash.ALL,
|
|
3008
|
+
NONE: SignatureHash.NONE,
|
|
3009
|
+
SINGLE: SignatureHash.SINGLE,
|
|
3010
|
+
ALL_ANYONECANPAY: SignatureHash.ALL | SignatureHash.ANYONECANPAY,
|
|
3011
|
+
NONE_ANYONECANPAY: SignatureHash.NONE | SignatureHash.ANYONECANPAY,
|
|
3012
|
+
SINGLE_ANYONECANPAY: SignatureHash.SINGLE | SignatureHash.ANYONECANPAY
|
|
3013
|
+
}))();
|
|
3014
|
+
var SigHashNames = /* @__PURE__ */ (() => Object.freeze(reverseObject(SigHash2)))();
|
|
3015
|
+
function getTaprootKeys(privKey, pubKey, internalKey, merkleRoot = EMPTY) {
|
|
3016
|
+
if (equalBytes2(internalKey, pubKey)) {
|
|
3017
|
+
privKey = taprootTweakPrivKey(privKey, merkleRoot);
|
|
3018
|
+
pubKey = pubSchnorr(privKey);
|
|
3019
|
+
}
|
|
3020
|
+
return { privKey, pubKey };
|
|
3021
|
+
}
|
|
3022
|
+
function outputBeforeSign(i) {
|
|
3023
|
+
if (i.script === undefined || i.amount === undefined)
|
|
3024
|
+
throw new Error("Transaction/output: script and amount required");
|
|
3025
|
+
return { script: i.script, amount: i.amount };
|
|
3026
|
+
}
|
|
3027
|
+
function inputBeforeSign(i) {
|
|
3028
|
+
validateObject2(i, {}, {}, "i");
|
|
3029
|
+
if (i.txid === undefined || i.index === undefined)
|
|
3030
|
+
throw new Error("Transaction/input: txid and index required");
|
|
3031
|
+
const res = {
|
|
3032
|
+
txid: i.txid,
|
|
3033
|
+
index: i.index,
|
|
3034
|
+
sequence: def(i.sequence, DEFAULT_SEQUENCE),
|
|
3035
|
+
finalScriptSig: def(i.finalScriptSig, EMPTY)
|
|
3036
|
+
};
|
|
3037
|
+
RawInput.encode(res);
|
|
3038
|
+
return res;
|
|
3039
|
+
}
|
|
3040
|
+
var cleanExtensions = (map, unknownMode, proprietaryMode, rejectStrip = false) => {
|
|
3041
|
+
const out = { ...map };
|
|
3042
|
+
for (const [name, mode] of [
|
|
3043
|
+
["unknown", unknownMode],
|
|
3044
|
+
["proprietary", proprietaryMode]
|
|
3045
|
+
]) {
|
|
3046
|
+
const value = out[name];
|
|
3047
|
+
if (value !== undefined)
|
|
3048
|
+
aarray(value, `${name} PSBT field`);
|
|
3049
|
+
const rows = value;
|
|
3050
|
+
if (!rows?.length) {
|
|
3051
|
+
delete out[name];
|
|
3052
|
+
continue;
|
|
3053
|
+
}
|
|
3054
|
+
if (mode === "strict")
|
|
3055
|
+
throw new Error(`PSBT: ${name} PSBT field is not allowed in strict mode`);
|
|
3056
|
+
if (mode === "strip") {
|
|
3057
|
+
if (rejectStrip)
|
|
3058
|
+
throw new Error(`PSBT: ${name} PSBT field cannot be supplied when policy is strip`);
|
|
3059
|
+
delete out[name];
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
return out;
|
|
3063
|
+
};
|
|
3064
|
+
var cleanTxModifiable = (value, mode) => {
|
|
3065
|
+
if (value === undefined || !(value & ~7))
|
|
3066
|
+
return value;
|
|
3067
|
+
if (mode === "strict")
|
|
3068
|
+
throw new Error("PSBT: unknown txModifiable bits in strict mode");
|
|
3069
|
+
return mode === "strip" ? value & 7 : value;
|
|
3070
|
+
};
|
|
3071
|
+
function cleanFinalInput(i, unknownMode = "strip", proprietaryMode = "strip") {
|
|
3072
|
+
const _i = i;
|
|
3073
|
+
const extensions = cleanExtensions(_i, unknownMode, proprietaryMode);
|
|
3074
|
+
if (extensions.unknown)
|
|
3075
|
+
_i.unknown = extensions.unknown;
|
|
3076
|
+
else
|
|
3077
|
+
delete _i.unknown;
|
|
3078
|
+
if (extensions.proprietary)
|
|
3079
|
+
_i.proprietary = extensions.proprietary;
|
|
3080
|
+
else
|
|
3081
|
+
delete _i.proprietary;
|
|
3082
|
+
for (const _k in _i) {
|
|
3083
|
+
const k = _k;
|
|
3084
|
+
if (proprietaryMode === "ignore" && k === "proprietary" && _i.proprietary?.length)
|
|
3085
|
+
continue;
|
|
3086
|
+
if (!PSBTInputFinalKeys.includes(k))
|
|
3087
|
+
delete _i[k];
|
|
3088
|
+
}
|
|
3089
|
+
}
|
|
3090
|
+
var TxHashIdx = /* @__PURE__ */ (() => struct({ txid: createBytes(32, true), index: U32LE }))();
|
|
3091
|
+
function validateSigHash(s) {
|
|
3092
|
+
if (typeof s !== "number" || typeof SigHashNames[s] !== "string")
|
|
3093
|
+
throw new Error(`Invalid SigHash=${s}`);
|
|
3094
|
+
return s;
|
|
3095
|
+
}
|
|
3096
|
+
function unpackSighash(hashType) {
|
|
3097
|
+
const masked = hashType & 31;
|
|
3098
|
+
return {
|
|
3099
|
+
isAny: !!(hashType & SignatureHash.ANYONECANPAY),
|
|
3100
|
+
isNone: masked === SignatureHash.NONE,
|
|
3101
|
+
isSingle: masked === SignatureHash.SINGLE
|
|
3102
|
+
};
|
|
3103
|
+
}
|
|
3104
|
+
var sighashScope = (sighash) => ({
|
|
3105
|
+
sigInputs: sighash & SignatureHash.ANYONECANPAY,
|
|
3106
|
+
sigOutputs: sighash === SignatureHash.DEFAULT ? SignatureHash.ALL : sighash & 3
|
|
3107
|
+
});
|
|
3108
|
+
var normalizeUnknowns = (name, mode, legacy, fallback = "strip") => {
|
|
3109
|
+
const alias = legacy === undefined ? undefined : legacy ? "ignore" : "strip";
|
|
3110
|
+
if (mode !== undefined && mode !== "ignore" && mode !== "strip" && mode !== "strict")
|
|
3111
|
+
throw new Error(`Transaction options wrong value: ${name}=${mode}`);
|
|
3112
|
+
if (mode !== undefined && alias !== undefined && mode !== alias)
|
|
3113
|
+
throw new Error(`Transaction options: conflicting ${name} options`);
|
|
3114
|
+
return mode || alias || fallback;
|
|
3115
|
+
};
|
|
3116
|
+
function validateOpts(opts) {
|
|
3117
|
+
if (opts !== undefined)
|
|
3118
|
+
validateObject2(opts, {}, {}, "opts");
|
|
3119
|
+
const _opts = {
|
|
3120
|
+
...opts,
|
|
3121
|
+
version: def(opts.version, DEFAULT_VERSION),
|
|
3122
|
+
lockTime: def(opts.lockTime, 0),
|
|
3123
|
+
PSBTVersion: def(opts.PSBTVersion, 0)
|
|
3124
|
+
};
|
|
3125
|
+
if (typeof _opts.allowUnknowInput !== "undefined")
|
|
3126
|
+
_opts.allowUnknownInputs = _opts.allowUnknowInput;
|
|
3127
|
+
if (typeof _opts.allowUnknowOutput !== "undefined")
|
|
3128
|
+
_opts.allowUnknownOutputs = _opts.allowUnknowOutput;
|
|
3129
|
+
if (_opts.allowMissingTxModifiable === undefined)
|
|
3130
|
+
_opts.allowMissingTxModifiable = true;
|
|
3131
|
+
if (typeof _opts.lockTime !== "number")
|
|
3132
|
+
throw new Error("Transaction lock time should be number");
|
|
3133
|
+
U32LE.encode(_opts.lockTime);
|
|
3134
|
+
if (_opts.PSBTVersion !== 0 && _opts.PSBTVersion !== 2)
|
|
3135
|
+
throw new Error(`Unknown PSBT version ${_opts.PSBTVersion}`);
|
|
3136
|
+
for (const k of [
|
|
3137
|
+
"allowUnknownVersion",
|
|
3138
|
+
"allowUnknownOutputs",
|
|
3139
|
+
"allowUnknownInputs",
|
|
3140
|
+
"disableScriptCheck",
|
|
3141
|
+
"bip174jsCompat",
|
|
3142
|
+
"allowLegacyWitnessUtxo",
|
|
3143
|
+
"strictPrevoutValidation",
|
|
3144
|
+
"lowR",
|
|
3145
|
+
"allowUnknown",
|
|
3146
|
+
"allowMissingTxModifiable"
|
|
3147
|
+
]) {
|
|
3148
|
+
const v = _opts[k];
|
|
3149
|
+
if (v === undefined)
|
|
3150
|
+
continue;
|
|
3151
|
+
if (typeof v !== "boolean")
|
|
3152
|
+
throw new Error(`Transation options wrong type: ${k}=${v} (${typeof v})`);
|
|
3153
|
+
}
|
|
3154
|
+
_opts.unknown = normalizeUnknowns("unknown", _opts.unknown, _opts.allowUnknown);
|
|
3155
|
+
_opts.proprietary = normalizeUnknowns("proprietary", _opts.proprietary, undefined, _opts.unknown);
|
|
3156
|
+
if (_opts.allowUnknownVersion ? typeof _opts.version !== "number" : ![-1, 0, 1, 2, 3].includes(_opts.version))
|
|
3157
|
+
throw new Error(`Unknown version: ${_opts.version}`);
|
|
3158
|
+
I32LE.encode(_opts.version);
|
|
3159
|
+
if (_opts.customScripts !== undefined) {
|
|
3160
|
+
const cs = _opts.customScripts;
|
|
3161
|
+
if (!Array.isArray(cs)) {
|
|
3162
|
+
throw new Error(`wrong custom scripts type (expected array): customScripts=${cs} (${typeof cs})`);
|
|
3163
|
+
}
|
|
3164
|
+
for (const s of cs) {
|
|
3165
|
+
if (typeof s.encode !== "function" || typeof s.decode !== "function")
|
|
3166
|
+
throw new Error(`wrong script=${s} (${typeof s})`);
|
|
3167
|
+
if (s.finalizeTaproot !== undefined && typeof s.finalizeTaproot !== "function")
|
|
3168
|
+
throw new Error(`wrong script=${s} (${typeof s})`);
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
return Object.freeze(_opts);
|
|
3172
|
+
}
|
|
3173
|
+
function checkTaprootInputCommitments(input, prevScript) {
|
|
3174
|
+
const output = _WitnessOutScript.decode(prevScript);
|
|
3175
|
+
const hasTaprootCommitments = input.tapInternalKey !== undefined || input.tapMerkleRoot !== undefined || !!input.tapLeafScript?.length;
|
|
3176
|
+
if (output.type !== "tr") {
|
|
3177
|
+
if (hasTaprootCommitments)
|
|
3178
|
+
throw new Error("validateInput: Taproot metadata without P2TR previous output");
|
|
3179
|
+
return;
|
|
3180
|
+
}
|
|
3181
|
+
const checkOutputKey = (internalKey, merkleRoot, parity) => {
|
|
3182
|
+
const [outputKey, outputParity] = taprootTweakPubkey(internalKey, merkleRoot);
|
|
3183
|
+
if (!equalBytes2(outputKey, output.pubkey))
|
|
3184
|
+
throw new Error("validateInput: Taproot commitment does not match previous output");
|
|
3185
|
+
if (parity !== undefined && outputParity !== parity)
|
|
3186
|
+
throw new Error("validateInput: Taproot control-block parity does not match previous output");
|
|
3187
|
+
};
|
|
3188
|
+
if (input.tapLeafScript) {
|
|
3189
|
+
for (const [controlBlock, scriptWithVersion] of input.tapLeafScript) {
|
|
3190
|
+
const leafVersion = scriptWithVersion[scriptWithVersion.length - 1];
|
|
3191
|
+
const script = scriptWithVersion.subarray(0, -1);
|
|
3192
|
+
let merkleRoot = tapLeafHash(script, leafVersion);
|
|
3193
|
+
for (const sibling of controlBlock.merklePath) {
|
|
3194
|
+
merkleRoot = compareBytes(sibling, merkleRoot) === -1 ? tagSchnorr("TapBranch", sibling, merkleRoot) : tagSchnorr("TapBranch", merkleRoot, sibling);
|
|
3195
|
+
}
|
|
3196
|
+
checkOutputKey(controlBlock.internalKey, merkleRoot, controlBlock.version & 1);
|
|
3197
|
+
if (input.tapInternalKey && !equalBytes2(input.tapInternalKey, controlBlock.internalKey))
|
|
3198
|
+
throw new Error("validateInput: tapInternalKey does not match Taproot control block");
|
|
3199
|
+
if (input.tapMerkleRoot && !equalBytes2(input.tapMerkleRoot, merkleRoot))
|
|
3200
|
+
throw new Error("validateInput: tapMerkleRoot does not match Taproot control block");
|
|
3201
|
+
}
|
|
3202
|
+
}
|
|
3203
|
+
if (input.tapInternalKey && (input.tapMerkleRoot || !input.tapLeafScript?.length))
|
|
3204
|
+
checkOutputKey(input.tapInternalKey, input.tapMerkleRoot || EMPTY);
|
|
3205
|
+
}
|
|
3206
|
+
var LOCKTIME_THRESHOLD = 500000000;
|
|
3207
|
+
function validateRequiredLocktimes(input) {
|
|
3208
|
+
const height = input.requiredHeightLocktime;
|
|
3209
|
+
if (height !== undefined) {
|
|
3210
|
+
anumber(height, "requiredHeightLocktime");
|
|
3211
|
+
if (height === 0 || height >= LOCKTIME_THRESHOLD)
|
|
3212
|
+
throw new RangeError(`requiredHeightLocktime must be between 1 and ${LOCKTIME_THRESHOLD - 1}, got ${height}`);
|
|
3213
|
+
}
|
|
3214
|
+
const time = input.requiredTimeLocktime;
|
|
3215
|
+
if (time !== undefined) {
|
|
3216
|
+
anumber(time, "requiredTimeLocktime");
|
|
3217
|
+
if (time < LOCKTIME_THRESHOLD || time > 4294967295)
|
|
3218
|
+
throw new RangeError(`requiredTimeLocktime must be between ${LOCKTIME_THRESHOLD} and 4294967295, got ${time}`);
|
|
3219
|
+
}
|
|
3220
|
+
}
|
|
3221
|
+
function resolvePSBTLocktime(inputs, fallback = DEFAULT_LOCKTIME) {
|
|
3222
|
+
let height = DEFAULT_LOCKTIME;
|
|
3223
|
+
let time = DEFAULT_LOCKTIME;
|
|
3224
|
+
let hasRequirements = false;
|
|
3225
|
+
let heightSupported = true;
|
|
3226
|
+
let timeSupported = true;
|
|
3227
|
+
for (const input of inputs) {
|
|
3228
|
+
validateRequiredLocktimes(input);
|
|
3229
|
+
const hasHeight = input.requiredHeightLocktime !== undefined;
|
|
3230
|
+
const hasTime = input.requiredTimeLocktime !== undefined;
|
|
3231
|
+
if (!hasHeight && !hasTime)
|
|
3232
|
+
continue;
|
|
3233
|
+
hasRequirements = true;
|
|
3234
|
+
if (hasHeight)
|
|
3235
|
+
height = Math.max(height, input.requiredHeightLocktime);
|
|
3236
|
+
else
|
|
3237
|
+
heightSupported = false;
|
|
3238
|
+
if (hasTime)
|
|
3239
|
+
time = Math.max(time, input.requiredTimeLocktime);
|
|
3240
|
+
else
|
|
3241
|
+
timeSupported = false;
|
|
3242
|
+
}
|
|
3243
|
+
if (!hasRequirements)
|
|
3244
|
+
return fallback;
|
|
3245
|
+
if (heightSupported)
|
|
3246
|
+
return height;
|
|
3247
|
+
if (timeSupported)
|
|
3248
|
+
return time;
|
|
3249
|
+
throw new Error("PSBTv2: incompatible height-based and time-based locktime requirements");
|
|
3250
|
+
}
|
|
3251
|
+
function validateInput(i, disableScriptCheck = false) {
|
|
3252
|
+
validateObject2(i, {}, {}, "i");
|
|
3253
|
+
const _i = i;
|
|
3254
|
+
validateRequiredLocktimes(_i);
|
|
3255
|
+
let prevOut;
|
|
3256
|
+
if (_i.nonWitnessUtxo && _i.index !== undefined) {
|
|
3257
|
+
const last = _i.nonWitnessUtxo.outputs.length - 1;
|
|
3258
|
+
if (_i.index > last)
|
|
3259
|
+
throw new Error(`validateInput: index(${_i.index}) not in nonWitnessUtxo`);
|
|
3260
|
+
prevOut = _i.nonWitnessUtxo.outputs[_i.index];
|
|
3261
|
+
if (_i.witnessUtxo && (!equalBytes2(_i.witnessUtxo.script, prevOut.script) || _i.witnessUtxo.amount !== prevOut.amount))
|
|
3262
|
+
throw new Error("validateInput: witnessUtxo different from nonWitnessUtxo");
|
|
3263
|
+
if (_i.txid) {
|
|
3264
|
+
const outputs = _i.nonWitnessUtxo.outputs;
|
|
3265
|
+
if (outputs.length - 1 < _i.index)
|
|
3266
|
+
throw new Error("nonWitnessUtxo: incorect output index");
|
|
3267
|
+
const tx = Transaction2.fromRaw(RawTx.encode(_i.nonWitnessUtxo), {
|
|
3268
|
+
allowUnknownOutputs: true,
|
|
3269
|
+
disableScriptCheck: true,
|
|
3270
|
+
allowUnknownInputs: true,
|
|
3271
|
+
allowUnknownVersion: true
|
|
3272
|
+
});
|
|
3273
|
+
const txid = hex.encode(_i.txid);
|
|
3274
|
+
if (tx.id !== txid)
|
|
3275
|
+
throw new Error(`nonWitnessUtxo: wrong txid, exp=${txid} got=${tx.id}`);
|
|
3276
|
+
}
|
|
3277
|
+
} else if (_i.witnessUtxo)
|
|
3278
|
+
prevOut = _i.witnessUtxo;
|
|
3279
|
+
if (prevOut && !disableScriptCheck) {
|
|
3280
|
+
checkScript(prevOut.script, _i.redeemScript, _i.witnessScript);
|
|
3281
|
+
checkTaprootInputCommitments(_i, prevOut.script);
|
|
3282
|
+
}
|
|
3283
|
+
return _i;
|
|
3284
|
+
}
|
|
3285
|
+
var inputSignatures = (input) => {
|
|
3286
|
+
const _input = input;
|
|
3287
|
+
const res = [];
|
|
3288
|
+
const add = (signature, taproot, scriptPath = false) => {
|
|
3289
|
+
const sig = signature;
|
|
3290
|
+
if (!sig.length)
|
|
3291
|
+
return;
|
|
3292
|
+
const sighash = taproot && sig.length === 64 ? SignatureHash.DEFAULT : sig[sig.length - 1];
|
|
3293
|
+
res.push({ sighash, taproot, scriptPath });
|
|
3294
|
+
};
|
|
3295
|
+
for (const [, signature] of _input.partialSig || [])
|
|
3296
|
+
add(signature, false);
|
|
3297
|
+
if (_input.tapKeySig)
|
|
3298
|
+
add(_input.tapKeySig, true);
|
|
3299
|
+
for (const [, signature] of _input.tapScriptSig || [])
|
|
3300
|
+
add(signature, true, true);
|
|
3301
|
+
return res;
|
|
3302
|
+
};
|
|
3303
|
+
var inputSignedKeys = {
|
|
3304
|
+
self: ["txid", "index", "sequence", "nonWitnessUtxo", "witnessUtxo", "sighashType"],
|
|
3305
|
+
ecdsa: ["redeemScript", "witnessScript"],
|
|
3306
|
+
tapscript: ["tapLeafScript"],
|
|
3307
|
+
cross: ["txid", "index"],
|
|
3308
|
+
prevout: ["nonWitnessUtxo", "witnessUtxo"]
|
|
3309
|
+
};
|
|
3310
|
+
function getPrevOut(input) {
|
|
3311
|
+
validateObject2(input, {}, {}, "input");
|
|
3312
|
+
const _input = input;
|
|
3313
|
+
if (_input.nonWitnessUtxo) {
|
|
3314
|
+
if (_input.index === undefined)
|
|
3315
|
+
throw new Error("Unknown input index");
|
|
3316
|
+
if (!Number.isSafeInteger(_input.index) || _input.index < 0 || _input.index >= _input.nonWitnessUtxo.outputs.length)
|
|
3317
|
+
throw new Error(`Wrong input index=${_input.index}`);
|
|
3318
|
+
return _input.nonWitnessUtxo.outputs[_input.index];
|
|
3319
|
+
} else if ("witnessUtxo" in _input) {
|
|
3320
|
+
const prev = _input.witnessUtxo;
|
|
3321
|
+
validateObject2(prev, {}, {}, "input.witnessUtxo");
|
|
3322
|
+
abigint(prev.amount, "input.witnessUtxo.amount");
|
|
3323
|
+
if (!isBytes2(prev.script))
|
|
3324
|
+
throw new TypeError('"input.witnessUtxo.script" expected Uint8Array, got type=' + typeof prev.script);
|
|
3325
|
+
return prev;
|
|
3326
|
+
} else
|
|
3327
|
+
throw new Error("Cannot find previous output info");
|
|
3328
|
+
}
|
|
3329
|
+
function normalizeInput(i, cur, allowedFields, disableScriptCheck = false, unknown = "strip", proprietary = "strip") {
|
|
3330
|
+
validateObject2(i, {}, {}, "i");
|
|
3331
|
+
if (cur !== undefined)
|
|
3332
|
+
validateObject2(cur, {}, {}, "cur");
|
|
3333
|
+
if (allowedFields !== undefined)
|
|
3334
|
+
aarray(allowedFields, "allowedFields");
|
|
3335
|
+
const _i = i;
|
|
3336
|
+
const _cur = cur;
|
|
3337
|
+
const _allowedFields = allowedFields;
|
|
3338
|
+
let { nonWitnessUtxo, txid } = _i;
|
|
3339
|
+
if (typeof nonWitnessUtxo === "string")
|
|
3340
|
+
nonWitnessUtxo = hex.decode(nonWitnessUtxo);
|
|
3341
|
+
if (isBytes2(nonWitnessUtxo))
|
|
3342
|
+
nonWitnessUtxo = RawTx.decode(nonWitnessUtxo);
|
|
3343
|
+
if (!("nonWitnessUtxo" in _i) && nonWitnessUtxo === undefined)
|
|
3344
|
+
nonWitnessUtxo = _cur?.nonWitnessUtxo;
|
|
3345
|
+
if (typeof txid === "string")
|
|
3346
|
+
txid = hex.decode(txid);
|
|
3347
|
+
if (txid === undefined)
|
|
3348
|
+
txid = _cur?.txid;
|
|
3349
|
+
let res = { ..._cur, ..._i, nonWitnessUtxo, txid };
|
|
3350
|
+
if (!("nonWitnessUtxo" in _i) && res.nonWitnessUtxo === undefined)
|
|
3351
|
+
delete res.nonWitnessUtxo;
|
|
3352
|
+
if (res.sequence === undefined)
|
|
3353
|
+
res.sequence = DEFAULT_SEQUENCE;
|
|
3354
|
+
if (res.tapMerkleRoot === null)
|
|
3355
|
+
delete res.tapMerkleRoot;
|
|
3356
|
+
res = mergeKeyMap(PSBTInput, res, _cur, _allowedFields, unknown, proprietary);
|
|
3357
|
+
if (Array.isArray(res.tapLeafScript) && !res.tapLeafScript.length)
|
|
3358
|
+
delete res.tapLeafScript;
|
|
3359
|
+
validateRequiredLocktimes(res);
|
|
3360
|
+
PSBTInputCoder.encode(res);
|
|
3361
|
+
return validateInput(res, disableScriptCheck);
|
|
3362
|
+
}
|
|
3363
|
+
function getInputType(input, allowLegacyWitnessUtxo = false) {
|
|
3364
|
+
const _input = input;
|
|
3365
|
+
let txType = "legacy";
|
|
3366
|
+
let defaultSighash = SignatureHash.ALL;
|
|
3367
|
+
const prevOut = getPrevOut(_input);
|
|
3368
|
+
const first = _WitnessOutScript.decode(prevOut.script);
|
|
3369
|
+
let type = first.type;
|
|
3370
|
+
let cur = first;
|
|
3371
|
+
const stack = [first];
|
|
3372
|
+
let lastScript = prevOut.script;
|
|
3373
|
+
if (first.type === "tr") {
|
|
3374
|
+
defaultSighash = SignatureHash.DEFAULT;
|
|
3375
|
+
return {
|
|
3376
|
+
txType: "taproot",
|
|
3377
|
+
type: "tr",
|
|
3378
|
+
last: first,
|
|
3379
|
+
lastScript: prevOut.script,
|
|
3380
|
+
defaultSighash,
|
|
3381
|
+
sighash: _input.sighashType || defaultSighash
|
|
3382
|
+
};
|
|
3383
|
+
} else {
|
|
3384
|
+
if (first.type === "wpkh" || first.type === "wsh")
|
|
3385
|
+
txType = "segwit";
|
|
3386
|
+
if (first.type === "sh") {
|
|
3387
|
+
if (!_input.redeemScript)
|
|
3388
|
+
throw new Error("inputType: sh without redeemScript");
|
|
3389
|
+
let child = _WitnessOutScript.decode(_input.redeemScript);
|
|
3390
|
+
if (child.type === "wpkh" || child.type === "wsh")
|
|
3391
|
+
txType = "segwit";
|
|
3392
|
+
stack.push(child);
|
|
3393
|
+
cur = child;
|
|
3394
|
+
lastScript = _input.redeemScript;
|
|
3395
|
+
type += `-${child.type}`;
|
|
3396
|
+
}
|
|
3397
|
+
if (cur.type === "wsh") {
|
|
3398
|
+
if (!_input.witnessScript)
|
|
3399
|
+
throw new Error("inputType: wsh without witnessScript");
|
|
3400
|
+
let child = OutScript2.decode(_input.witnessScript);
|
|
3401
|
+
if (child.type === "wsh")
|
|
3402
|
+
txType = "segwit";
|
|
3403
|
+
stack.push(child);
|
|
3404
|
+
cur = child;
|
|
3405
|
+
lastScript = _input.witnessScript;
|
|
3406
|
+
type += `-${child.type}`;
|
|
3407
|
+
}
|
|
3408
|
+
const last = stack[stack.length - 1];
|
|
3409
|
+
if (last.type === "sh" || last.type === "wsh")
|
|
3410
|
+
throw new Error("inputType: sh/wsh cannot be terminal type");
|
|
3411
|
+
const res = {
|
|
3412
|
+
type,
|
|
3413
|
+
txType,
|
|
3414
|
+
last,
|
|
3415
|
+
lastScript,
|
|
3416
|
+
defaultSighash,
|
|
3417
|
+
sighash: _input.sighashType || defaultSighash
|
|
3418
|
+
};
|
|
3419
|
+
if (txType === "legacy" && !allowLegacyWitnessUtxo && !_input.nonWitnessUtxo) {
|
|
3420
|
+
throw new Error(`Transaction/sign: legacy input without nonWitnessUtxo, can result in attack that forces paying higher fees. Pass allowLegacyWitnessUtxo=true, if you sure`);
|
|
3421
|
+
}
|
|
3422
|
+
return res;
|
|
3423
|
+
}
|
|
3424
|
+
}
|
|
3425
|
+
|
|
3426
|
+
class Transaction2 {
|
|
3427
|
+
global = {};
|
|
3428
|
+
inputs = [];
|
|
3429
|
+
outputs = [];
|
|
3430
|
+
opts;
|
|
3431
|
+
constructor(opts = {}) {
|
|
3432
|
+
const _opts = this.opts = validateOpts(opts);
|
|
3433
|
+
this.global.fallbackLocktime = _opts.lockTime;
|
|
3434
|
+
this.global.txVersion = _opts.version;
|
|
3435
|
+
if (_opts.PSBTVersion === 2)
|
|
3436
|
+
this.global.txModifiable = 3;
|
|
3437
|
+
}
|
|
3438
|
+
isPSBTv2() {
|
|
3439
|
+
return (this.global.version ?? this.opts.PSBTVersion) === 2;
|
|
3440
|
+
}
|
|
3441
|
+
requireTxModifiable(bit, kind) {
|
|
3442
|
+
if (!this.isPSBTv2())
|
|
3443
|
+
return;
|
|
3444
|
+
if (!(this.txModifiablePolicy() & bit))
|
|
3445
|
+
throw new Error(`PSBTv2: ${kind} are not modifiable`);
|
|
3446
|
+
}
|
|
3447
|
+
txModifiablePolicy(allowMissing = this.opts.allowMissingTxModifiable, unknownMode = this.opts.unknown) {
|
|
3448
|
+
if (!this.isPSBTv2())
|
|
3449
|
+
return 3;
|
|
3450
|
+
if (this.global.txModifiable !== undefined)
|
|
3451
|
+
return cleanTxModifiable(this.global.txModifiable, unknownMode);
|
|
3452
|
+
return allowMissing ? 3 : 0;
|
|
3453
|
+
}
|
|
3454
|
+
modifiable(allowMissing = this.opts.allowMissingTxModifiable, unknownMode = this.opts.unknown) {
|
|
3455
|
+
let flags = this.txModifiablePolicy(allowMissing, unknownMode);
|
|
3456
|
+
let hasOpaqueFinal = false;
|
|
3457
|
+
let hasSingle = false;
|
|
3458
|
+
for (let idx = 0;idx < this.inputs.length; idx++) {
|
|
3459
|
+
const signatures = inputSignatures(this.inputs[idx]);
|
|
3460
|
+
if (!signatures.length && this.inputStatus(idx) === "finalized")
|
|
3461
|
+
hasOpaqueFinal = true;
|
|
3462
|
+
for (const { sighash } of signatures) {
|
|
3463
|
+
const { isAny, isNone, isSingle } = unpackSighash(sighash);
|
|
3464
|
+
if (!isAny)
|
|
3465
|
+
flags &= ~1;
|
|
3466
|
+
if (!isNone)
|
|
3467
|
+
flags &= ~2;
|
|
3468
|
+
if (isSingle)
|
|
3469
|
+
hasSingle = true;
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
if (hasSingle)
|
|
3473
|
+
flags |= 4;
|
|
3474
|
+
if (hasOpaqueFinal && this.global.txModifiable === undefined)
|
|
3475
|
+
flags &= ~3;
|
|
3476
|
+
return flags;
|
|
3477
|
+
}
|
|
3478
|
+
get txModifiable() {
|
|
3479
|
+
return this.modifiable();
|
|
3480
|
+
}
|
|
3481
|
+
static fromRaw(raw, opts = {}) {
|
|
3482
|
+
const parsed = RawTx.decode(raw);
|
|
3483
|
+
const tx = new Transaction2({ ...opts, version: parsed.version, lockTime: parsed.lockTime });
|
|
3484
|
+
for (const o of parsed.outputs)
|
|
3485
|
+
tx.addOutput(o);
|
|
3486
|
+
tx.outputs = parsed.outputs;
|
|
3487
|
+
tx.inputs = parsed.inputs;
|
|
3488
|
+
if (parsed.witnesses) {
|
|
3489
|
+
for (let i = 0;i < parsed.witnesses.length; i++)
|
|
3490
|
+
tx.inputs[i].finalScriptWitness = parsed.witnesses[i];
|
|
3491
|
+
}
|
|
3492
|
+
return tx;
|
|
3493
|
+
}
|
|
3494
|
+
static fromPSBT(psbt_, opts = {}) {
|
|
3495
|
+
let parsed;
|
|
3496
|
+
try {
|
|
3497
|
+
parsed = RawPSBTV0.decode(psbt_);
|
|
3498
|
+
} catch (e0) {
|
|
3499
|
+
try {
|
|
3500
|
+
parsed = RawPSBTV2.decode(psbt_);
|
|
3501
|
+
} catch (e2) {
|
|
3502
|
+
throw e0;
|
|
3503
|
+
}
|
|
3504
|
+
}
|
|
3505
|
+
const PSBTVersion = parsed.global.version || 0;
|
|
3506
|
+
if (PSBTVersion !== 0 && PSBTVersion !== 2)
|
|
3507
|
+
throw new Error(`Wrong PSBT version=${PSBTVersion}`);
|
|
3508
|
+
const unsigned = parsed.global.unsignedTx;
|
|
3509
|
+
const version = PSBTVersion === 0 ? unsigned?.version : parsed.global.txVersion;
|
|
3510
|
+
const lockTime = PSBTVersion === 0 ? unsigned?.lockTime : parsed.global.fallbackLocktime;
|
|
3511
|
+
const tx = new Transaction2({ ...opts, version, lockTime, PSBTVersion });
|
|
3512
|
+
const inputCount = PSBTVersion === 0 ? unsigned?.inputs.length : parsed.global.inputCount;
|
|
3513
|
+
tx.inputs = parsed.inputs.slice(0, inputCount).map((i, j) => {
|
|
3514
|
+
const input = {
|
|
3515
|
+
...parsed.global.unsignedTx?.inputs[j],
|
|
3516
|
+
...i
|
|
3517
|
+
};
|
|
3518
|
+
if (!i.finalScriptSig?.length)
|
|
3519
|
+
delete input.finalScriptSig;
|
|
3520
|
+
return validateInput(input, tx.opts.disableScriptCheck);
|
|
3521
|
+
});
|
|
3522
|
+
const outputCount = PSBTVersion === 0 ? unsigned?.outputs.length : parsed.global.outputCount;
|
|
3523
|
+
const hasBip174InputMap = PSBTVersion === 0 && inputCount === 0 && Object.keys(parsed.outputs[0] || {}).length === 0 && (outputCount > 0 && parsed.outputs.length === outputCount + 1 || outputCount === 0 && parsed.outputs.length === 2 && Object.keys(parsed.outputs[1]).length === 0);
|
|
3524
|
+
const outputStart = hasBip174InputMap ? 1 : 0;
|
|
3525
|
+
tx.outputs = parsed.outputs.slice(outputStart, outputStart + outputCount).map((i, j) => ({
|
|
3526
|
+
...i,
|
|
3527
|
+
...parsed.global.unsignedTx?.outputs[j]
|
|
3528
|
+
}));
|
|
3529
|
+
const unknownMode = tx.opts.unknown;
|
|
3530
|
+
const proprietaryMode = tx.opts.proprietary;
|
|
3531
|
+
tx.global = cleanExtensions({ ...parsed.global, txVersion: version }, unknownMode, proprietaryMode);
|
|
3532
|
+
tx.inputs = tx.inputs.map((input) => cleanExtensions(input, unknownMode, proprietaryMode));
|
|
3533
|
+
tx.outputs = tx.outputs.map((output) => cleanExtensions(output, unknownMode, proprietaryMode));
|
|
3534
|
+
if (tx.global.txModifiable !== undefined)
|
|
3535
|
+
tx.global.txModifiable = cleanTxModifiable(tx.global.txModifiable, unknownMode);
|
|
3536
|
+
resolvePSBTLocktime(tx.inputs, tx.global.fallbackLocktime ?? DEFAULT_LOCKTIME);
|
|
3537
|
+
if (PSBTVersion === 0)
|
|
3538
|
+
tx.global.fallbackLocktime = def(lockTime, DEFAULT_LOCKTIME);
|
|
3539
|
+
return tx;
|
|
3540
|
+
}
|
|
3541
|
+
toPSBT(PSBTVersion = this.global.version || this.opts.PSBTVersion) {
|
|
3542
|
+
if (PSBTVersion !== undefined)
|
|
3543
|
+
anumber(PSBTVersion, "PSBTVersion");
|
|
3544
|
+
if (PSBTVersion !== 0 && PSBTVersion !== 2)
|
|
3545
|
+
throw new Error(`Wrong PSBT version=${PSBTVersion}`);
|
|
3546
|
+
const inputs = this.inputs.map((i) => cleanExtensions(cleanPSBTFields(PSBTVersion, PSBTInput, validateInput(i, this.opts.disableScriptCheck)), this.opts.unknown, this.opts.proprietary));
|
|
3547
|
+
for (const inp of inputs) {
|
|
3548
|
+
if (inp.partialSig && !inp.partialSig.length)
|
|
3549
|
+
delete inp.partialSig;
|
|
3550
|
+
if (inp.finalScriptSig && !inp.finalScriptSig.length)
|
|
3551
|
+
delete inp.finalScriptSig;
|
|
3552
|
+
if (inp.finalScriptWitness && !inp.finalScriptWitness.length)
|
|
3553
|
+
delete inp.finalScriptWitness;
|
|
3554
|
+
}
|
|
3555
|
+
const outputs = this.outputs.map((i) => cleanExtensions(cleanPSBTFields(PSBTVersion, PSBTOutput, i), this.opts.unknown, this.opts.proprietary));
|
|
3556
|
+
const global = cleanExtensions({ ...this.global }, this.opts.unknown, this.opts.proprietary);
|
|
3557
|
+
if (global.txModifiable !== undefined)
|
|
3558
|
+
global.txModifiable = cleanTxModifiable(global.txModifiable, this.opts.unknown);
|
|
3559
|
+
if (PSBTVersion === 0) {
|
|
3560
|
+
global.unsignedTx = RawOldTx.decode(RawOldTx.encode({
|
|
3561
|
+
version: this.version,
|
|
3562
|
+
lockTime: this.lockTime,
|
|
3563
|
+
inputs: this.inputs.map((i) => inputBeforeSign(i)).map((i) => ({
|
|
3564
|
+
...i,
|
|
3565
|
+
finalScriptSig: EMPTY
|
|
3566
|
+
})),
|
|
3567
|
+
outputs: this.outputs.map((o) => outputBeforeSign(o))
|
|
3568
|
+
}));
|
|
3569
|
+
delete global.fallbackLocktime;
|
|
3570
|
+
delete global.txVersion;
|
|
3571
|
+
delete global.inputCount;
|
|
3572
|
+
delete global.outputCount;
|
|
3573
|
+
delete global.version;
|
|
3574
|
+
delete global.txModifiable;
|
|
3575
|
+
} else {
|
|
3576
|
+
delete global.unsignedTx;
|
|
3577
|
+
global.version = PSBTVersion;
|
|
3578
|
+
global.txVersion = this.version;
|
|
3579
|
+
global.inputCount = this.inputs.length;
|
|
3580
|
+
global.outputCount = this.outputs.length;
|
|
3581
|
+
if (!this.isPSBTv2() || global.txModifiable === undefined && this.opts.allowMissingTxModifiable)
|
|
3582
|
+
global.txModifiable = this.txModifiable;
|
|
3583
|
+
}
|
|
3584
|
+
if (this.opts.bip174jsCompat && PSBTVersion === 0 && !outputs.length)
|
|
3585
|
+
outputs.push({});
|
|
3586
|
+
const raw = { global, inputs, outputs };
|
|
3587
|
+
return PSBTVersion === 0 ? RawPSBTV0.encode(raw) : RawPSBTV2.encode(raw);
|
|
3588
|
+
}
|
|
3589
|
+
get lockTime() {
|
|
3590
|
+
return resolvePSBTLocktime(this.inputs, this.global.fallbackLocktime ?? DEFAULT_LOCKTIME);
|
|
3591
|
+
}
|
|
3592
|
+
get version() {
|
|
3593
|
+
if (this.global.txVersion === undefined)
|
|
3594
|
+
throw new Error("No global.txVersion");
|
|
3595
|
+
return this.global.txVersion;
|
|
3596
|
+
}
|
|
3597
|
+
inputStatus(idx) {
|
|
3598
|
+
this.checkInputIdx(idx);
|
|
3599
|
+
const input = this.inputs[idx];
|
|
3600
|
+
if (input.finalScriptSig && input.finalScriptSig.length)
|
|
3601
|
+
return "finalized";
|
|
3602
|
+
if (input.finalScriptWitness && input.finalScriptWitness.length)
|
|
3603
|
+
return "finalized";
|
|
3604
|
+
if (input.tapKeySig)
|
|
3605
|
+
return "signed";
|
|
3606
|
+
if (input.tapScriptSig && input.tapScriptSig.length)
|
|
3607
|
+
return "signed";
|
|
3608
|
+
if (input.partialSig && input.partialSig.length)
|
|
3609
|
+
return "signed";
|
|
3610
|
+
return "unsigned";
|
|
3611
|
+
}
|
|
3612
|
+
cleanFinalInput(input) {
|
|
3613
|
+
cleanFinalInput(input, this.opts.unknown, this.opts.proprietary);
|
|
3614
|
+
if (this.global.txModifiable !== undefined)
|
|
3615
|
+
this.global.txModifiable = cleanTxModifiable(this.global.txModifiable, this.opts.unknown);
|
|
3616
|
+
}
|
|
3617
|
+
inputSighash(idx) {
|
|
3618
|
+
this.checkInputIdx(idx);
|
|
3619
|
+
const inputSighash = this.inputs[idx].sighashType;
|
|
3620
|
+
const sighash = inputSighash === undefined ? SignatureHash.DEFAULT : inputSighash;
|
|
3621
|
+
return sighashScope(sighash);
|
|
3622
|
+
}
|
|
3623
|
+
signatures() {
|
|
3624
|
+
const res = [];
|
|
3625
|
+
for (let idx = 0;idx < this.inputs.length; idx++) {
|
|
3626
|
+
const actual = inputSignatures(this.inputs[idx]);
|
|
3627
|
+
for (const signature of actual)
|
|
3628
|
+
res.push({ idx, ...signature });
|
|
3629
|
+
if (actual.length || this.inputStatus(idx) !== "finalized")
|
|
3630
|
+
continue;
|
|
3631
|
+
let taproot = true;
|
|
3632
|
+
try {
|
|
3633
|
+
taproot = _WitnessOutScript.decode(getPrevOut(this.inputs[idx]).script).type === "tr";
|
|
3634
|
+
} catch {}
|
|
3635
|
+
const declared = this.inputs[idx].sighashType;
|
|
3636
|
+
const sighash = declared === undefined ? SignatureHash.DEFAULT : declared;
|
|
3637
|
+
res.push({ idx, sighash, taproot, scriptPath: taproot });
|
|
3638
|
+
}
|
|
3639
|
+
return res;
|
|
3640
|
+
}
|
|
3641
|
+
signedInputKeys(idx, signatures = this.signatures()) {
|
|
3642
|
+
const res = new Set;
|
|
3643
|
+
const add = (keys) => {
|
|
3644
|
+
for (const key of keys)
|
|
3645
|
+
res.add(key);
|
|
3646
|
+
};
|
|
3647
|
+
for (const signature of signatures) {
|
|
3648
|
+
const { isAny, isNone, isSingle } = unpackSighash(signature.sighash);
|
|
3649
|
+
if (signature.idx === idx) {
|
|
3650
|
+
add(inputSignedKeys.self);
|
|
3651
|
+
if (signature.taproot) {
|
|
3652
|
+
if (signature.scriptPath)
|
|
3653
|
+
add(inputSignedKeys.tapscript);
|
|
3654
|
+
} else
|
|
3655
|
+
add(inputSignedKeys.ecdsa);
|
|
3656
|
+
} else if (!isAny) {
|
|
3657
|
+
add(inputSignedKeys.cross);
|
|
3658
|
+
if (signature.taproot || !isNone && !isSingle)
|
|
3659
|
+
res.add("sequence");
|
|
3660
|
+
if (signature.taproot)
|
|
3661
|
+
add(inputSignedKeys.prevout);
|
|
3662
|
+
}
|
|
3663
|
+
}
|
|
3664
|
+
return [...res];
|
|
3665
|
+
}
|
|
3666
|
+
signStatus(signatures = this.signatures()) {
|
|
3667
|
+
let addInput = true, addOutput = true;
|
|
3668
|
+
let inputs = [], outputs = [];
|
|
3669
|
+
for (const { idx, sighash } of signatures) {
|
|
3670
|
+
const { sigInputs, sigOutputs } = sighashScope(sighash);
|
|
3671
|
+
if (sigInputs === SignatureHash.ANYONECANPAY) {
|
|
3672
|
+
if (!inputs.includes(idx))
|
|
3673
|
+
inputs.push(idx);
|
|
3674
|
+
} else
|
|
3675
|
+
addInput = false;
|
|
3676
|
+
if (sigOutputs === SignatureHash.ALL)
|
|
3677
|
+
addOutput = false;
|
|
3678
|
+
else if (sigOutputs === SignatureHash.SINGLE) {
|
|
3679
|
+
if (!outputs.includes(idx))
|
|
3680
|
+
outputs.push(idx);
|
|
3681
|
+
} else if (sigOutputs === SignatureHash.NONE) {} else
|
|
3682
|
+
throw new Error(`Wrong signature hash output type: ${sigOutputs}`);
|
|
3683
|
+
}
|
|
3684
|
+
return { addInput, addOutput, inputs, outputs };
|
|
3685
|
+
}
|
|
3686
|
+
get isFinal() {
|
|
3687
|
+
for (let idx = 0;idx < this.inputs.length; idx++)
|
|
3688
|
+
if (this.inputStatus(idx) !== "finalized")
|
|
3689
|
+
return false;
|
|
3690
|
+
return true;
|
|
3691
|
+
}
|
|
3692
|
+
get hasWitnesses() {
|
|
3693
|
+
for (const i of this.inputs)
|
|
3694
|
+
if (i.finalScriptWitness && i.finalScriptWitness.length)
|
|
3695
|
+
return true;
|
|
3696
|
+
return false;
|
|
3697
|
+
}
|
|
3698
|
+
get weight() {
|
|
3699
|
+
if (!this.isFinal)
|
|
3700
|
+
throw new Error("Transaction is not finalized");
|
|
3701
|
+
const varLen = (dataLen) => CompactSizeLen.encode(dataLen).length + dataLen;
|
|
3702
|
+
const hasWitnesses = this.hasWitnesses;
|
|
3703
|
+
let out = 32;
|
|
3704
|
+
const outputs = this.outputs.map(outputBeforeSign);
|
|
3705
|
+
out += 4 * CompactSizeLen.encode(this.outputs.length).length;
|
|
3706
|
+
for (const o of outputs)
|
|
3707
|
+
out += 32 + 4 * varLen(o.script.length);
|
|
3708
|
+
if (hasWitnesses)
|
|
3709
|
+
out += 2;
|
|
3710
|
+
out += 4 * CompactSizeLen.encode(this.inputs.length).length;
|
|
3711
|
+
for (const i of this.inputs) {
|
|
3712
|
+
out += 160 + 4 * varLen((i.finalScriptSig || EMPTY).length);
|
|
3713
|
+
if (hasWitnesses) {
|
|
3714
|
+
const witness = i.finalScriptWitness || [];
|
|
3715
|
+
out += CompactSizeLen.encode(witness.length).length;
|
|
3716
|
+
for (const w of witness)
|
|
3717
|
+
out += varLen(w.length);
|
|
3718
|
+
}
|
|
3719
|
+
}
|
|
3720
|
+
return out;
|
|
3721
|
+
}
|
|
3722
|
+
get vsize() {
|
|
3723
|
+
return toVsize(this.weight);
|
|
3724
|
+
}
|
|
3725
|
+
toBytes(withScriptSig = false, withWitness = false) {
|
|
3726
|
+
return RawTx.encode({
|
|
3727
|
+
version: this.version,
|
|
3728
|
+
lockTime: this.lockTime,
|
|
3729
|
+
inputs: this.inputs.map(inputBeforeSign).map((i) => ({
|
|
3730
|
+
...i,
|
|
3731
|
+
finalScriptSig: withScriptSig && i.finalScriptSig || EMPTY
|
|
3732
|
+
})),
|
|
3733
|
+
outputs: this.outputs.map(outputBeforeSign),
|
|
3734
|
+
witnesses: this.inputs.map((i) => i.finalScriptWitness || []),
|
|
3735
|
+
segwitFlag: withWitness && this.hasWitnesses
|
|
3736
|
+
});
|
|
3737
|
+
}
|
|
3738
|
+
get unsignedTx() {
|
|
3739
|
+
return this.toBytes(false, false);
|
|
3740
|
+
}
|
|
3741
|
+
get hex() {
|
|
3742
|
+
return hex.encode(this.toBytes(true, this.hasWitnesses));
|
|
3743
|
+
}
|
|
3744
|
+
get hash() {
|
|
3745
|
+
return hex.encode(sha256x2(this.toBytes(true)));
|
|
3746
|
+
}
|
|
3747
|
+
get id() {
|
|
3748
|
+
return hex.encode(sha256x2(this.toBytes(true)).reverse());
|
|
3749
|
+
}
|
|
3750
|
+
checkInputIdx(idx) {
|
|
3751
|
+
anumber(idx, "idx");
|
|
3752
|
+
if (idx >= this.inputs.length)
|
|
3753
|
+
throw new Error(`Wrong input index=${idx}`);
|
|
3754
|
+
}
|
|
3755
|
+
validatePrevoutsForSigning() {
|
|
3756
|
+
if (!this.opts.strictPrevoutValidation)
|
|
3757
|
+
return;
|
|
3758
|
+
for (let i = 0;i < this.inputs.length; i++) {
|
|
3759
|
+
const input = this.inputs[i];
|
|
3760
|
+
if (!input.nonWitnessUtxo) {
|
|
3761
|
+
throw new Error(`Transaction/sign: strictPrevoutValidation requires nonWitnessUtxo for input=${i}`);
|
|
3762
|
+
}
|
|
3763
|
+
if (input.txid === undefined || input.index === undefined) {
|
|
3764
|
+
throw new Error(`Transaction/sign: strictPrevoutValidation requires an outpoint for input=${i}`);
|
|
3765
|
+
}
|
|
3766
|
+
validateInput(input, this.opts.disableScriptCheck);
|
|
3767
|
+
}
|
|
3768
|
+
}
|
|
3769
|
+
getInput(idx) {
|
|
3770
|
+
this.checkInputIdx(idx);
|
|
3771
|
+
return cloneDeep(this.inputs[idx]);
|
|
3772
|
+
}
|
|
3773
|
+
get inputsLength() {
|
|
3774
|
+
return this.inputs.length;
|
|
3775
|
+
}
|
|
3776
|
+
addInput(input, _ignoreSignStatus = false) {
|
|
3777
|
+
validateObject2(input, {}, {}, "input");
|
|
3778
|
+
cleanExtensions(input, this.opts.unknown, this.opts.proprietary, true);
|
|
3779
|
+
this.requireTxModifiable(1, "inputs");
|
|
3780
|
+
const signatures = _ignoreSignStatus ? undefined : this.signatures();
|
|
3781
|
+
const status = signatures && this.signStatus(signatures);
|
|
3782
|
+
if (status && !status.addInput)
|
|
3783
|
+
throw new Error("Tx has signed inputs, cannot add new one");
|
|
3784
|
+
const normalized = cloneDeep(normalizeInput(input, undefined, undefined, this.opts.disableScriptCheck, this.opts.unknown, this.opts.proprietary));
|
|
3785
|
+
const nextLockTime = resolvePSBTLocktime([...this.inputs, normalized], this.global.fallbackLocktime ?? DEFAULT_LOCKTIME);
|
|
3786
|
+
if (signatures?.length && nextLockTime !== this.lockTime)
|
|
3787
|
+
throw new Error("Tx has signed inputs, cannot change lockTime");
|
|
3788
|
+
this.inputs.push(normalized);
|
|
3789
|
+
return this.inputs.length - 1;
|
|
3790
|
+
}
|
|
3791
|
+
updateInput(idx, input, _ignoreSignStatus = false) {
|
|
3792
|
+
this.checkInputIdx(idx);
|
|
3793
|
+
cleanExtensions(input, this.opts.unknown, this.opts.proprietary, true);
|
|
3794
|
+
let allowedFields;
|
|
3795
|
+
const signatures = _ignoreSignStatus ? undefined : this.signatures();
|
|
3796
|
+
if (signatures?.length) {
|
|
3797
|
+
if (this.inputStatus(idx) === "finalized") {
|
|
3798
|
+
allowedFields = PSBTInputSignatureKeys.filter((key) => this.inputs[idx][key] !== undefined);
|
|
3799
|
+
} else {
|
|
3800
|
+
const signed = new Set(this.signedInputKeys(idx, signatures));
|
|
3801
|
+
if (signed.size)
|
|
3802
|
+
allowedFields = Object.keys(PSBTInput).filter((key) => !signed.has(key));
|
|
3803
|
+
}
|
|
3804
|
+
}
|
|
3805
|
+
const normalized = cloneDeep(normalizeInput(input, this.inputs[idx], allowedFields, this.opts.disableScriptCheck, this.opts.unknown, this.opts.proprietary));
|
|
3806
|
+
const inputs = this.inputs.slice();
|
|
3807
|
+
inputs[idx] = normalized;
|
|
3808
|
+
const nextLockTime = resolvePSBTLocktime(inputs, this.global.fallbackLocktime ?? DEFAULT_LOCKTIME);
|
|
3809
|
+
if (signatures?.length && nextLockTime !== this.lockTime)
|
|
3810
|
+
throw new Error("Tx has signed inputs, cannot change lockTime");
|
|
3811
|
+
const current = this.inputs[idx];
|
|
3812
|
+
const transactionChanged = current.index !== normalized.index || def(current.sequence, DEFAULT_SEQUENCE) !== def(normalized.sequence, DEFAULT_SEQUENCE) || (current.txid === undefined ? normalized.txid !== undefined : normalized.txid === undefined || !equalBytes2(current.txid, normalized.txid)) || nextLockTime !== this.lockTime;
|
|
3813
|
+
if (transactionChanged)
|
|
3814
|
+
this.requireTxModifiable(1, "inputs");
|
|
3815
|
+
this.inputs[idx] = normalized;
|
|
3816
|
+
}
|
|
3817
|
+
checkOutputIdx(idx) {
|
|
3818
|
+
anumber(idx, "idx");
|
|
3819
|
+
if (idx >= this.outputs.length)
|
|
3820
|
+
throw new Error(`Wrong output index=${idx}`);
|
|
3821
|
+
}
|
|
3822
|
+
getOutput(idx) {
|
|
3823
|
+
this.checkOutputIdx(idx);
|
|
3824
|
+
return cloneDeep(this.outputs[idx]);
|
|
3825
|
+
}
|
|
3826
|
+
getOutputAddress(idx, network = NETWORK2) {
|
|
3827
|
+
const out = this.getOutput(idx);
|
|
3828
|
+
if (!out.script)
|
|
3829
|
+
return;
|
|
3830
|
+
return Address2(network).encode(_WitnessOutScript.decode(out.script));
|
|
3831
|
+
}
|
|
3832
|
+
get outputsLength() {
|
|
3833
|
+
return this.outputs.length;
|
|
3834
|
+
}
|
|
3835
|
+
normalizeOutput(o, cur, allowedFields) {
|
|
3836
|
+
validateObject2(o, {}, {}, "o");
|
|
3837
|
+
let { amount, script } = o;
|
|
3838
|
+
if (amount === undefined)
|
|
3839
|
+
amount = cur?.amount;
|
|
3840
|
+
amount = abigint(amount, "o.amount");
|
|
3841
|
+
if (typeof script === "string")
|
|
3842
|
+
script = hex.decode(script);
|
|
3843
|
+
if (script === undefined)
|
|
3844
|
+
script = cur?.script;
|
|
3845
|
+
let res = { ...cur, ...o, amount, script };
|
|
3846
|
+
if (res.amount === undefined)
|
|
3847
|
+
delete res.amount;
|
|
3848
|
+
res = mergeKeyMap(PSBTOutput, res, cur, allowedFields, this.opts.unknown, this.opts.proprietary);
|
|
3849
|
+
PSBTOutputCoder.encode(res);
|
|
3850
|
+
if (res.script && !this.opts.allowUnknownOutputs && _WitnessOutScript.decode(res.script).type === "unknown") {
|
|
3851
|
+
throw new Error("Transaction/output: unknown output script type, there is a chance that input is unspendable. Pass allowUnknownOutputs=true, if you sure");
|
|
3852
|
+
}
|
|
3853
|
+
if (!this.opts.disableScriptCheck)
|
|
3854
|
+
checkScript(res.script, res.redeemScript, res.witnessScript);
|
|
3855
|
+
return res;
|
|
3856
|
+
}
|
|
3857
|
+
addOutput(o, _ignoreSignStatus = false) {
|
|
3858
|
+
cleanExtensions(o, this.opts.unknown, this.opts.proprietary, true);
|
|
3859
|
+
this.requireTxModifiable(2, "outputs");
|
|
3860
|
+
const status = _ignoreSignStatus ? undefined : this.signStatus();
|
|
3861
|
+
if (status && (!status.addOutput || status.outputs.includes(this.outputs.length)))
|
|
3862
|
+
throw new Error("Tx has signed outputs, cannot add new one");
|
|
3863
|
+
this.outputs.push(cloneDeep(this.normalizeOutput(o)));
|
|
3864
|
+
return this.outputs.length - 1;
|
|
3865
|
+
}
|
|
3866
|
+
updateOutput(idx, output, _ignoreSignStatus = false) {
|
|
3867
|
+
this.checkOutputIdx(idx);
|
|
3868
|
+
cleanExtensions(output, this.opts.unknown, this.opts.proprietary, true);
|
|
3869
|
+
let allowedFields = undefined;
|
|
3870
|
+
if (!_ignoreSignStatus) {
|
|
3871
|
+
const status = this.signStatus();
|
|
3872
|
+
if (!status.addOutput || status.outputs.includes(idx))
|
|
3873
|
+
allowedFields = PSBTOutputUnsignedKeys;
|
|
3874
|
+
}
|
|
3875
|
+
const current = this.outputs[idx];
|
|
3876
|
+
const normalized = cloneDeep(this.normalizeOutput(output, current, allowedFields));
|
|
3877
|
+
const transactionChanged = current.amount !== normalized.amount || (current.script === undefined ? normalized.script !== undefined : normalized.script === undefined || !equalBytes2(current.script, normalized.script));
|
|
3878
|
+
if (transactionChanged)
|
|
3879
|
+
this.requireTxModifiable(2, "outputs");
|
|
3880
|
+
this.outputs[idx] = normalized;
|
|
3881
|
+
}
|
|
3882
|
+
addOutputAddress(address, amount, network = NETWORK2) {
|
|
3883
|
+
return this.addOutput({
|
|
3884
|
+
script: OutScript2.encode(Address2(network).decode(address)),
|
|
3885
|
+
amount
|
|
3886
|
+
});
|
|
3887
|
+
}
|
|
3888
|
+
get fee() {
|
|
3889
|
+
let res = _0n5;
|
|
3890
|
+
for (const i of this.inputs) {
|
|
3891
|
+
const prevOut = getPrevOut(i);
|
|
3892
|
+
if (!prevOut)
|
|
3893
|
+
throw new Error("Empty input amount");
|
|
3894
|
+
res += prevOut.amount;
|
|
3895
|
+
}
|
|
3896
|
+
const outputs = this.outputs.map(outputBeforeSign);
|
|
3897
|
+
for (const o of outputs)
|
|
3898
|
+
res -= o.amount;
|
|
3899
|
+
return res;
|
|
3900
|
+
}
|
|
3901
|
+
preimageLegacy(idx, prevOutScript, hashType) {
|
|
3902
|
+
const { isAny, isNone, isSingle } = unpackSighash(hashType);
|
|
3903
|
+
if (idx < 0 || !Number.isSafeInteger(idx))
|
|
3904
|
+
throw new Error(`Invalid input idx=${idx}`);
|
|
3905
|
+
if (isSingle && idx >= this.outputs.length || idx >= this.inputs.length)
|
|
3906
|
+
return U256LE.encode(_1n4);
|
|
3907
|
+
prevOutScript = stripCodeSeparator(prevOutScript);
|
|
3908
|
+
let inputs = this.inputs.map(inputBeforeSign).map((input, inputIdx) => ({
|
|
3909
|
+
...input,
|
|
3910
|
+
finalScriptSig: inputIdx === idx ? prevOutScript : EMPTY
|
|
3911
|
+
}));
|
|
3912
|
+
if (isAny)
|
|
3913
|
+
inputs = [inputs[idx]];
|
|
3914
|
+
else if (isNone || isSingle) {
|
|
3915
|
+
inputs = inputs.map((input, inputIdx) => ({
|
|
3916
|
+
...input,
|
|
3917
|
+
sequence: inputIdx === idx ? input.sequence : 0
|
|
3918
|
+
}));
|
|
3919
|
+
}
|
|
3920
|
+
let outputs = this.outputs.map(outputBeforeSign);
|
|
3921
|
+
if (isNone)
|
|
3922
|
+
outputs = [];
|
|
3923
|
+
else if (isSingle) {
|
|
3924
|
+
outputs = outputs.slice(0, idx).fill(EMPTY_OUTPUT).concat([outputs[idx]]);
|
|
3925
|
+
}
|
|
3926
|
+
const tmpTx = RawTx.encode({
|
|
3927
|
+
lockTime: this.lockTime,
|
|
3928
|
+
version: this.version,
|
|
3929
|
+
segwitFlag: false,
|
|
3930
|
+
inputs,
|
|
3931
|
+
outputs
|
|
3932
|
+
});
|
|
3933
|
+
return sha256x2(tmpTx, I32LE.encode(hashType));
|
|
3934
|
+
}
|
|
3935
|
+
preimageWitnessV0(idx, prevOutScript, hashType, amount) {
|
|
3936
|
+
anumber(idx, "idx");
|
|
3937
|
+
if (idx >= this.inputs.length)
|
|
3938
|
+
throw new Error(`Invalid input idx=${idx}`);
|
|
3939
|
+
const { isAny, isNone, isSingle } = unpackSighash(hashType);
|
|
3940
|
+
let inputHash = EMPTY32;
|
|
3941
|
+
let sequenceHash = EMPTY32;
|
|
3942
|
+
let outputHash = EMPTY32;
|
|
3943
|
+
const inputs = this.inputs.map(inputBeforeSign);
|
|
3944
|
+
const outputs = this.outputs.map(outputBeforeSign);
|
|
3945
|
+
if (!isAny)
|
|
3946
|
+
inputHash = sha256x2(...inputs.map(TxHashIdx.encode));
|
|
3947
|
+
if (!isAny && !isSingle && !isNone)
|
|
3948
|
+
sequenceHash = sha256x2(...inputs.map((i) => U32LE.encode(i.sequence)));
|
|
3949
|
+
if (!isSingle && !isNone) {
|
|
3950
|
+
outputHash = sha256x2(...outputs.map(RawOutput.encode));
|
|
3951
|
+
} else if (isSingle && idx < outputs.length)
|
|
3952
|
+
outputHash = sha256x2(RawOutput.encode(outputs[idx]));
|
|
3953
|
+
const input = inputs[idx];
|
|
3954
|
+
return sha256x2(I32LE.encode(this.version), inputHash, sequenceHash, createBytes(32, true).encode(input.txid), U32LE.encode(input.index), VarBytes.encode(prevOutScript), U64LE.encode(amount), U32LE.encode(input.sequence), outputHash, U32LE.encode(this.lockTime), U32LE.encode(hashType));
|
|
3955
|
+
}
|
|
3956
|
+
preimageWitnessV1(idx, prevOutScript, hashType, amount, codeSeparator = -1, leafScript, leafVer = 192, annex) {
|
|
3957
|
+
anumber(idx, "idx");
|
|
3958
|
+
if (idx >= this.inputs.length)
|
|
3959
|
+
throw new Error(`Invalid input idx=${idx}`);
|
|
3960
|
+
aarray(amount, "amount");
|
|
3961
|
+
aarray(prevOutScript, "prevOutScript");
|
|
3962
|
+
if (this.inputs.length !== amount.length)
|
|
3963
|
+
throw new Error(`Invalid amounts array=${amount}`);
|
|
3964
|
+
if (this.inputs.length !== prevOutScript.length)
|
|
3965
|
+
throw new Error(`Invalid prevOutScript array=${prevOutScript}`);
|
|
3966
|
+
const out = [
|
|
3967
|
+
U8.encode(0),
|
|
3968
|
+
U8.encode(hashType),
|
|
3969
|
+
I32LE.encode(this.version),
|
|
3970
|
+
U32LE.encode(this.lockTime)
|
|
3971
|
+
];
|
|
3972
|
+
const outType = hashType === SignatureHash.DEFAULT ? SignatureHash.ALL : hashType & 3;
|
|
3973
|
+
const inType = hashType & SignatureHash.ANYONECANPAY;
|
|
3974
|
+
const inputs = this.inputs.map(inputBeforeSign);
|
|
3975
|
+
const outputs = this.outputs.map(outputBeforeSign);
|
|
3976
|
+
if (outType === SignatureHash.SINGLE && idx >= outputs.length) {
|
|
3977
|
+
throw new Error(`Input with sighash SINGLE, but there is no output with corresponding index=${idx}`);
|
|
3978
|
+
}
|
|
3979
|
+
if (inType !== SignatureHash.ANYONECANPAY) {
|
|
3980
|
+
out.push(...[
|
|
3981
|
+
inputs.map(TxHashIdx.encode),
|
|
3982
|
+
amount.map(U64LE.encode),
|
|
3983
|
+
prevOutScript.map(VarBytes.encode),
|
|
3984
|
+
inputs.map((i) => U32LE.encode(i.sequence))
|
|
3985
|
+
].map((i) => sha2562(concatBytes3(...i))));
|
|
3986
|
+
}
|
|
3987
|
+
if (outType === SignatureHash.ALL) {
|
|
3988
|
+
out.push(sha2562(concatBytes3(...outputs.map(RawOutput.encode))));
|
|
3989
|
+
}
|
|
3990
|
+
const spendType = (annex ? 1 : 0) | (leafScript ? 2 : 0);
|
|
3991
|
+
out.push(new Uint8Array([spendType]));
|
|
3992
|
+
if (inType === SignatureHash.ANYONECANPAY) {
|
|
3993
|
+
const inp = inputs[idx];
|
|
3994
|
+
out.push(TxHashIdx.encode(inp), U64LE.encode(amount[idx]), VarBytes.encode(prevOutScript[idx]), U32LE.encode(inp.sequence));
|
|
3995
|
+
} else
|
|
3996
|
+
out.push(U32LE.encode(idx));
|
|
3997
|
+
if (spendType & 1)
|
|
3998
|
+
out.push(sha2562(VarBytes.encode(annex || EMPTY)));
|
|
3999
|
+
if (outType === SignatureHash.SINGLE)
|
|
4000
|
+
out.push(sha2562(RawOutput.encode(outputs[idx])));
|
|
4001
|
+
if (leafScript)
|
|
4002
|
+
out.push(tapLeafHash(leafScript, leafVer), U8.encode(0), I32LE.encode(codeSeparator));
|
|
4003
|
+
return tagSchnorr("TapSighash", ...out);
|
|
4004
|
+
}
|
|
4005
|
+
signIdx(privateKey, idx, allowedSighash, _auxRand) {
|
|
4006
|
+
if (!isBytes2(privateKey)) {
|
|
4007
|
+
if (!privateKey || typeof privateKey !== "object" || typeof privateKey.deriveChild !== "function")
|
|
4008
|
+
throw new TypeError('"privateKey" expected Uint8Array or HDKey, got type=' + typeof privateKey);
|
|
4009
|
+
}
|
|
4010
|
+
this.checkInputIdx(idx);
|
|
4011
|
+
this.validatePrevoutsForSigning();
|
|
4012
|
+
const input = validateInput(this.inputs[idx], this.opts.disableScriptCheck);
|
|
4013
|
+
const inputType = getInputType(input, this.opts.allowLegacyWitnessUtxo);
|
|
4014
|
+
const canSign = (privateKey) => {
|
|
4015
|
+
if (inputType.txType === "taproot") {
|
|
4016
|
+
const pubKey = pubSchnorr(privateKey);
|
|
4017
|
+
if (input.tapInternalKey && equalBytes2(pubKey, input.tapInternalKey))
|
|
4018
|
+
return true;
|
|
4019
|
+
if (!input.tapLeafScript)
|
|
4020
|
+
return false;
|
|
4021
|
+
for (const [_, leaf] of input.tapLeafScript) {
|
|
4022
|
+
for (const op of Script2.decode(leaf.subarray(0, -1))) {
|
|
4023
|
+
if (isBytes2(op) && equalBytes2(op, pubKey))
|
|
4024
|
+
return true;
|
|
4025
|
+
}
|
|
4026
|
+
}
|
|
4027
|
+
return false;
|
|
4028
|
+
}
|
|
4029
|
+
const pubKey = pubECDSA(privateKey);
|
|
4030
|
+
const pubKeyHash = hash160(pubKey);
|
|
4031
|
+
for (const op of Script2.decode(inputType.lastScript)) {
|
|
4032
|
+
if (isBytes2(op) && (equalBytes2(op, pubKey) || equalBytes2(op, pubKeyHash)))
|
|
4033
|
+
return true;
|
|
4034
|
+
}
|
|
4035
|
+
return false;
|
|
4036
|
+
};
|
|
4037
|
+
if (!isBytes2(privateKey)) {
|
|
4038
|
+
const root = privateKey;
|
|
4039
|
+
const deriveSigners = (label, rows, pubKey) => {
|
|
4040
|
+
if (!rows || !rows.length)
|
|
4041
|
+
throw new Error(`${label}: empty`);
|
|
4042
|
+
const signers = rows.filter((row) => row.fingerprint == root.fingerprint).map((row) => {
|
|
4043
|
+
let s = root;
|
|
4044
|
+
for (const i of row.path)
|
|
4045
|
+
s = s.deriveChild(i);
|
|
4046
|
+
if (!equalBytes2(pubKey(s), row.pubKey))
|
|
4047
|
+
throw new Error(`${label}: wrong pubKey`);
|
|
4048
|
+
if (!s.privateKey)
|
|
4049
|
+
throw new Error(`${label}: no privateKey`);
|
|
4050
|
+
return s;
|
|
4051
|
+
});
|
|
4052
|
+
if (!signers.length)
|
|
4053
|
+
throw new Error(`${label}: no items with fingerprint=${root.fingerprint}`);
|
|
4054
|
+
return signers;
|
|
4055
|
+
};
|
|
4056
|
+
const signers = inputType.txType === "taproot" ? deriveSigners("tapBip32Derivation", input.tapBip32Derivation?.map(([pubKey, { der }]) => ({
|
|
4057
|
+
pubKey,
|
|
4058
|
+
fingerprint: der.fingerprint,
|
|
4059
|
+
path: der.path
|
|
4060
|
+
})), (s) => s.publicKey.slice(1)) : deriveSigners("bip32Derivation", input.bip32Derivation?.map(([pubKey, der]) => ({
|
|
4061
|
+
pubKey,
|
|
4062
|
+
fingerprint: der.fingerprint,
|
|
4063
|
+
path: der.path
|
|
4064
|
+
})), (s) => s.publicKey);
|
|
4065
|
+
let signed = false;
|
|
4066
|
+
for (const s of signers) {
|
|
4067
|
+
if (!canSign(s.privateKey))
|
|
4068
|
+
continue;
|
|
4069
|
+
if (this.signIdx(s.privateKey, idx, allowedSighash, _auxRand))
|
|
4070
|
+
signed = true;
|
|
4071
|
+
}
|
|
4072
|
+
if (signed)
|
|
4073
|
+
return true;
|
|
4074
|
+
if (inputType.txType === "taproot")
|
|
4075
|
+
throw new Error("No taproot scripts signed");
|
|
4076
|
+
throw new Error(`Input script doesn't have pubKey: ${inputType.lastScript}`);
|
|
4077
|
+
}
|
|
4078
|
+
if (!allowedSighash)
|
|
4079
|
+
allowedSighash = [inputType.defaultSighash];
|
|
4080
|
+
else
|
|
4081
|
+
allowedSighash.forEach(validateSigHash);
|
|
4082
|
+
const sighash = inputType.sighash;
|
|
4083
|
+
if (!allowedSighash.includes(sighash)) {
|
|
4084
|
+
throw new Error(`Input with not allowed sigHash=${sighash}. Allowed: ${allowedSighash.join(", ")}`);
|
|
4085
|
+
}
|
|
4086
|
+
const { sigOutputs } = this.inputSighash(idx);
|
|
4087
|
+
if (sigOutputs === SignatureHash.SINGLE && idx >= this.outputs.length) {
|
|
4088
|
+
throw new Error(`Input with sighash SINGLE, but there is no output with corresponding index=${idx}`);
|
|
4089
|
+
}
|
|
4090
|
+
const prevOut = getPrevOut(input);
|
|
4091
|
+
if (inputType.txType === "taproot") {
|
|
4092
|
+
const prevOuts = this.inputs.map(getPrevOut);
|
|
4093
|
+
const prevOutScript = prevOuts.map((i) => i.script);
|
|
4094
|
+
const amount = prevOuts.map((i) => i.amount);
|
|
4095
|
+
let signed = false;
|
|
4096
|
+
let schnorrPub = pubSchnorr(privateKey);
|
|
4097
|
+
let merkleRoot = input.tapMerkleRoot || EMPTY;
|
|
4098
|
+
if (input.tapInternalKey) {
|
|
4099
|
+
const { pubKey, privKey } = getTaprootKeys(privateKey, schnorrPub, input.tapInternalKey, merkleRoot);
|
|
4100
|
+
const [taprootPubKey, _] = taprootTweakPubkey(input.tapInternalKey, merkleRoot);
|
|
4101
|
+
if (equalBytes2(taprootPubKey, pubKey)) {
|
|
4102
|
+
const hash = this.preimageWitnessV1(idx, prevOutScript, sighash, amount);
|
|
4103
|
+
const sig = concatBytes3(signSchnorr(hash, privKey, _auxRand), sighash !== SignatureHash.DEFAULT ? new Uint8Array([sighash]) : EMPTY);
|
|
4104
|
+
this.updateInput(idx, { tapKeySig: sig }, true);
|
|
4105
|
+
signed = true;
|
|
4106
|
+
}
|
|
4107
|
+
}
|
|
4108
|
+
if (input.tapLeafScript) {
|
|
4109
|
+
input.tapScriptSig = input.tapScriptSig || [];
|
|
4110
|
+
for (const [_, _script] of input.tapLeafScript) {
|
|
4111
|
+
const script = _script.subarray(0, -1);
|
|
4112
|
+
const scriptDecoded = Script2.decode(script);
|
|
4113
|
+
const ver = _script[_script.length - 1];
|
|
4114
|
+
const hash = tapLeafHash(script, ver);
|
|
4115
|
+
const pos = scriptDecoded.findIndex((i) => isBytes2(i) && equalBytes2(i, schnorrPub));
|
|
4116
|
+
if (pos === -1)
|
|
4117
|
+
continue;
|
|
4118
|
+
const msg = this.preimageWitnessV1(idx, prevOutScript, sighash, amount, undefined, script, ver);
|
|
4119
|
+
const sig = concatBytes3(signSchnorr(msg, privateKey, _auxRand), sighash !== SignatureHash.DEFAULT ? new Uint8Array([sighash]) : EMPTY);
|
|
4120
|
+
this.updateInput(idx, { tapScriptSig: [[{ pubKey: schnorrPub, leafHash: hash }, sig]] }, true);
|
|
4121
|
+
signed = true;
|
|
4122
|
+
}
|
|
4123
|
+
}
|
|
4124
|
+
if (!signed)
|
|
4125
|
+
throw new Error("No taproot scripts signed");
|
|
4126
|
+
return true;
|
|
4127
|
+
} else {
|
|
4128
|
+
const pubKey = pubECDSA(privateKey);
|
|
4129
|
+
let hasPubkey = false;
|
|
4130
|
+
const pubKeyHash = hash160(pubKey);
|
|
4131
|
+
for (const i of Script2.decode(inputType.lastScript)) {
|
|
4132
|
+
if (isBytes2(i) && (equalBytes2(i, pubKey) || equalBytes2(i, pubKeyHash)))
|
|
4133
|
+
hasPubkey = true;
|
|
4134
|
+
}
|
|
4135
|
+
if (!hasPubkey)
|
|
4136
|
+
throw new Error(`Input script doesn't have pubKey: ${inputType.lastScript}`);
|
|
4137
|
+
let hash;
|
|
4138
|
+
if (inputType.txType === "legacy") {
|
|
4139
|
+
hash = this.preimageLegacy(idx, inputType.lastScript, sighash);
|
|
4140
|
+
} else if (inputType.txType === "segwit") {
|
|
4141
|
+
let script = inputType.lastScript;
|
|
4142
|
+
if (inputType.last.type === "wpkh")
|
|
4143
|
+
script = OutScript2.encode({ type: "pkh", hash: inputType.last.hash });
|
|
4144
|
+
hash = this.preimageWitnessV0(idx, script, sighash, prevOut.amount);
|
|
4145
|
+
} else
|
|
4146
|
+
throw new Error(`Transaction/sign: unknown tx type: ${inputType.txType}`);
|
|
4147
|
+
const sig = signECDSA(hash, privateKey, this.opts.lowR);
|
|
4148
|
+
this.updateInput(idx, {
|
|
4149
|
+
partialSig: [[pubKey, concatBytes3(sig, new Uint8Array([sighash]))]]
|
|
4150
|
+
}, true);
|
|
4151
|
+
}
|
|
4152
|
+
return true;
|
|
4153
|
+
}
|
|
4154
|
+
sign(privateKey, allowedSighash, _auxRand) {
|
|
4155
|
+
this.validatePrevoutsForSigning();
|
|
4156
|
+
let num = 0;
|
|
4157
|
+
for (let i = 0;i < this.inputs.length; i++) {
|
|
4158
|
+
try {
|
|
4159
|
+
if (this.signIdx(privateKey, i, allowedSighash, _auxRand))
|
|
4160
|
+
num++;
|
|
4161
|
+
} catch (e) {}
|
|
4162
|
+
}
|
|
4163
|
+
if (!num)
|
|
4164
|
+
throw new Error("No inputs signed");
|
|
4165
|
+
return num;
|
|
4166
|
+
}
|
|
4167
|
+
finalizeIdx(idx) {
|
|
4168
|
+
this.checkInputIdx(idx);
|
|
4169
|
+
if (this.fee < _0n5)
|
|
4170
|
+
throw new Error("Outputs spends more than inputs amount");
|
|
4171
|
+
const input = this.inputs[idx];
|
|
4172
|
+
cleanExtensions(input, this.opts.unknown, this.opts.proprietary);
|
|
4173
|
+
cleanTxModifiable(this.global.txModifiable, this.opts.unknown);
|
|
4174
|
+
const inputType = getInputType(input, this.opts.allowLegacyWitnessUtxo);
|
|
4175
|
+
if (inputType.txType === "taproot") {
|
|
4176
|
+
if (input.tapKeySig)
|
|
4177
|
+
input.finalScriptWitness = [input.tapKeySig];
|
|
4178
|
+
else if (input.tapLeafScript && input.tapScriptSig) {
|
|
4179
|
+
const leafs = input.tapLeafScript.slice().sort((a, b) => TaprootControlBlock2.encode(a[0]).length - TaprootControlBlock2.encode(b[0]).length);
|
|
4180
|
+
let smallest;
|
|
4181
|
+
let smallestSize = Number.POSITIVE_INFINITY;
|
|
4182
|
+
let unsupported = false;
|
|
4183
|
+
for (const [cb, _script] of leafs) {
|
|
4184
|
+
const script = _script.slice(0, -1);
|
|
4185
|
+
const ver = _script[_script.length - 1];
|
|
4186
|
+
const outScript = OutScript2.decode(script);
|
|
4187
|
+
const hash = tapLeafHash(script, ver);
|
|
4188
|
+
const scriptSig = input.tapScriptSig.filter((i) => equalBytes2(i[0].leafHash, hash));
|
|
4189
|
+
let signatures = [];
|
|
4190
|
+
let witness;
|
|
4191
|
+
if (outScript.type === "tr_ms") {
|
|
4192
|
+
const m = outScript.m;
|
|
4193
|
+
const pubkeys = outScript.pubkeys;
|
|
4194
|
+
let added = 0;
|
|
4195
|
+
for (const pub of pubkeys) {
|
|
4196
|
+
const sigIdx = scriptSig.findIndex((i) => equalBytes2(i[0].pubKey, pub));
|
|
4197
|
+
if (added === m || sigIdx === -1) {
|
|
4198
|
+
signatures.push(EMPTY);
|
|
4199
|
+
continue;
|
|
4200
|
+
}
|
|
4201
|
+
signatures.push(scriptSig[sigIdx][1]);
|
|
4202
|
+
added++;
|
|
4203
|
+
}
|
|
4204
|
+
if (added !== m)
|
|
4205
|
+
continue;
|
|
4206
|
+
} else if (outScript.type === "tr_ns") {
|
|
4207
|
+
for (const pub of outScript.pubkeys) {
|
|
4208
|
+
const sigIdx = scriptSig.findIndex((i) => equalBytes2(i[0].pubKey, pub));
|
|
4209
|
+
if (sigIdx === -1)
|
|
4210
|
+
continue;
|
|
4211
|
+
signatures.push(scriptSig[sigIdx][1]);
|
|
4212
|
+
}
|
|
4213
|
+
if (signatures.length !== outScript.pubkeys.length)
|
|
4214
|
+
continue;
|
|
4215
|
+
} else if (outScript.type === "unknown" && this.opts.allowUnknownInputs) {
|
|
4216
|
+
const scriptDecoded = Script2.decode(script);
|
|
4217
|
+
signatures = scriptSig.map(([{ pubKey }, signature]) => {
|
|
4218
|
+
const pos = scriptDecoded.findIndex((i) => isBytes2(i) && equalBytes2(i, pubKey));
|
|
4219
|
+
if (pos === -1)
|
|
4220
|
+
throw new Error("finalize/taproot: cannot find position of pubkey in script");
|
|
4221
|
+
return { signature, pos };
|
|
4222
|
+
}).sort((a, b) => a.pos - b.pos).map((i) => i.signature);
|
|
4223
|
+
if (!signatures.length)
|
|
4224
|
+
continue;
|
|
4225
|
+
} else {
|
|
4226
|
+
const custom = this.opts.customScripts;
|
|
4227
|
+
let recognized = false;
|
|
4228
|
+
if (custom) {
|
|
4229
|
+
for (const c of custom) {
|
|
4230
|
+
if (!c.finalizeTaproot)
|
|
4231
|
+
continue;
|
|
4232
|
+
const scriptDecoded = Script2.decode(script);
|
|
4233
|
+
const csEncoded = c.encode(scriptDecoded);
|
|
4234
|
+
if (csEncoded === undefined)
|
|
4235
|
+
continue;
|
|
4236
|
+
recognized = true;
|
|
4237
|
+
const finalized = c.finalizeTaproot(script, csEncoded, scriptSig);
|
|
4238
|
+
if (!finalized)
|
|
4239
|
+
continue;
|
|
4240
|
+
witness = finalized.concat(TaprootControlBlock2.encode(cb));
|
|
4241
|
+
break;
|
|
4242
|
+
}
|
|
4243
|
+
}
|
|
4244
|
+
if (!witness && !recognized && scriptSig.length)
|
|
4245
|
+
unsupported = true;
|
|
4246
|
+
if (!witness)
|
|
4247
|
+
continue;
|
|
4248
|
+
}
|
|
4249
|
+
witness ||= signatures.reverse().concat([script, TaprootControlBlock2.encode(cb)]);
|
|
4250
|
+
const size = RawWitness.encode(witness).length;
|
|
4251
|
+
if (size >= smallestSize)
|
|
4252
|
+
continue;
|
|
4253
|
+
smallest = witness;
|
|
4254
|
+
smallestSize = size;
|
|
4255
|
+
}
|
|
4256
|
+
if (!smallest && unsupported)
|
|
4257
|
+
throw new Error("Finalize: Unknown tapLeafScript");
|
|
4258
|
+
if (!smallest)
|
|
4259
|
+
throw new Error("finalize/taproot: empty witness");
|
|
4260
|
+
input.finalScriptWitness = smallest;
|
|
4261
|
+
} else
|
|
4262
|
+
throw new Error("finalize/taproot: unknown input");
|
|
4263
|
+
delete input.finalScriptSig;
|
|
4264
|
+
this.cleanFinalInput(input);
|
|
4265
|
+
return;
|
|
4266
|
+
}
|
|
4267
|
+
if (!input.partialSig || !input.partialSig.length)
|
|
4268
|
+
throw new Error("Not enough partial sign");
|
|
4269
|
+
let inputScript = EMPTY;
|
|
4270
|
+
let witness = [];
|
|
4271
|
+
if (inputType.last.type === "ms") {
|
|
4272
|
+
const m = inputType.last.m;
|
|
4273
|
+
const pubkeys = inputType.last.pubkeys;
|
|
4274
|
+
let signatures = [];
|
|
4275
|
+
for (const pub of pubkeys) {
|
|
4276
|
+
const sign = input.partialSig.find((s) => equalBytes2(pub, s[0]));
|
|
4277
|
+
if (!sign)
|
|
4278
|
+
continue;
|
|
4279
|
+
signatures.push(sign[1]);
|
|
4280
|
+
}
|
|
4281
|
+
signatures = signatures.slice(0, m);
|
|
4282
|
+
if (signatures.length !== m) {
|
|
4283
|
+
throw new Error(`Multisig: wrong signatures count, m=${m} n=${pubkeys.length} signatures=${signatures.length}`);
|
|
4284
|
+
}
|
|
4285
|
+
inputScript = Script2.encode([0, ...signatures]);
|
|
4286
|
+
} else if (inputType.last.type === "pk") {
|
|
4287
|
+
inputScript = Script2.encode([input.partialSig[0][1]]);
|
|
4288
|
+
} else if (inputType.last.type === "pkh") {
|
|
4289
|
+
inputScript = Script2.encode([input.partialSig[0][1], input.partialSig[0][0]]);
|
|
4290
|
+
} else if (inputType.last.type === "wpkh") {
|
|
4291
|
+
inputScript = EMPTY;
|
|
4292
|
+
witness = [input.partialSig[0][1], input.partialSig[0][0]];
|
|
4293
|
+
} else if (inputType.last.type === "unknown" && !this.opts.allowUnknownInputs)
|
|
4294
|
+
throw new Error("Unknown inputs not allowed");
|
|
4295
|
+
let finalScriptSig, finalScriptWitness;
|
|
4296
|
+
if (inputType.type.includes("wsh-")) {
|
|
4297
|
+
if (inputScript.length && inputType.lastScript.length) {
|
|
4298
|
+
witness = Script2.decode(inputScript).map((i) => {
|
|
4299
|
+
if (i === 0)
|
|
4300
|
+
return EMPTY;
|
|
4301
|
+
if (isBytes2(i))
|
|
4302
|
+
return i;
|
|
4303
|
+
throw new Error(`Wrong witness op=${i}`);
|
|
4304
|
+
});
|
|
4305
|
+
}
|
|
4306
|
+
witness = witness.concat(inputType.lastScript);
|
|
4307
|
+
}
|
|
4308
|
+
if (inputType.txType === "segwit")
|
|
4309
|
+
finalScriptWitness = witness;
|
|
4310
|
+
if (inputType.type.startsWith("sh-wsh-")) {
|
|
4311
|
+
finalScriptSig = Script2.encode([Script2.encode([0, sha2562(inputType.lastScript)])]);
|
|
4312
|
+
} else if (inputType.type.startsWith("sh-")) {
|
|
4313
|
+
finalScriptSig = Script2.encode([...Script2.decode(inputScript), inputType.lastScript]);
|
|
4314
|
+
} else if (inputType.type.startsWith("wsh-")) {} else if (inputType.txType !== "segwit")
|
|
4315
|
+
finalScriptSig = inputScript;
|
|
4316
|
+
if (!finalScriptSig && !finalScriptWitness)
|
|
4317
|
+
throw new Error("Unknown error finalizing input");
|
|
4318
|
+
if (finalScriptSig)
|
|
4319
|
+
input.finalScriptSig = finalScriptSig;
|
|
4320
|
+
if (finalScriptWitness)
|
|
4321
|
+
input.finalScriptWitness = finalScriptWitness;
|
|
4322
|
+
this.cleanFinalInput(input);
|
|
4323
|
+
}
|
|
4324
|
+
finalize() {
|
|
4325
|
+
for (let i = 0;i < this.inputs.length; i++)
|
|
4326
|
+
this.finalizeIdx(i);
|
|
4327
|
+
}
|
|
4328
|
+
extract() {
|
|
4329
|
+
if (!this.isFinal)
|
|
4330
|
+
throw new Error("Transaction has unfinalized inputs");
|
|
4331
|
+
if (!this.outputs.length)
|
|
4332
|
+
throw new Error("Transaction has no outputs");
|
|
4333
|
+
if (this.fee < _0n5)
|
|
4334
|
+
throw new Error("Outputs spends more than inputs amount");
|
|
4335
|
+
return this.toBytes(true, true);
|
|
4336
|
+
}
|
|
4337
|
+
combine(other) {
|
|
4338
|
+
if (!(other instanceof Transaction2))
|
|
4339
|
+
throw new TypeError('"other" expected Transaction, got type=' + typeof other);
|
|
4340
|
+
const opts = this.opts;
|
|
4341
|
+
const PSBTVersion = Math.max(this.opts.PSBTVersion || 0, other.opts.PSBTVersion || 0);
|
|
4342
|
+
if (this.opts.version !== other.opts.version)
|
|
4343
|
+
throw new Error(`Transaction/combine: different version this=${this.opts.version} ` + `other=${other.opts.version}`);
|
|
4344
|
+
const thisV2 = this.isPSBTv2();
|
|
4345
|
+
const otherV2 = other.isPSBTv2();
|
|
4346
|
+
if (!thisV2 || !otherV2) {
|
|
4347
|
+
const thisLockTime = this.lockTime;
|
|
4348
|
+
const otherLockTime = other.lockTime;
|
|
4349
|
+
if (thisLockTime !== otherLockTime)
|
|
4350
|
+
throw new Error(`Transaction/combine: different lockTime this=${thisLockTime} other=${otherLockTime}`);
|
|
4351
|
+
}
|
|
4352
|
+
for (const k of ["inputs", "outputs"]) {
|
|
4353
|
+
if (this[k].length !== other[k].length) {
|
|
4354
|
+
throw new Error(`Transaction/combine: different ${k} length this=${this[k].length} other=${other[k].length}`);
|
|
4355
|
+
}
|
|
4356
|
+
}
|
|
4357
|
+
const unsignedTx = this.unsignedTx;
|
|
4358
|
+
if (!equalBytes2(unsignedTx, other.unsignedTx))
|
|
4359
|
+
throw new Error(`Transaction/combine: different unsigned tx`);
|
|
4360
|
+
let txModifiable;
|
|
4361
|
+
if (thisV2 && otherV2) {
|
|
4362
|
+
const policy = (tx) => {
|
|
4363
|
+
if (tx.global.txModifiable !== undefined)
|
|
4364
|
+
return cleanTxModifiable(tx.global.txModifiable, opts.unknown);
|
|
4365
|
+
return opts.allowMissingTxModifiable ? tx.modifiable(true, opts.unknown) : 0;
|
|
4366
|
+
};
|
|
4367
|
+
const a = policy(this);
|
|
4368
|
+
const b = policy(other);
|
|
4369
|
+
if ((a & ~7) !== (b & ~7))
|
|
4370
|
+
throw new Error("Transaction/combine: conflicting unknown txModifiable flags");
|
|
4371
|
+
txModifiable = a & ~7 | a & b & 3 | (a | b) & 4;
|
|
4372
|
+
if (txModifiable === 0 && this.global.txModifiable === undefined && other.global.txModifiable === undefined && !opts.allowMissingTxModifiable)
|
|
4373
|
+
txModifiable = undefined;
|
|
4374
|
+
} else if (thisV2)
|
|
4375
|
+
txModifiable = this.modifiable(opts.allowMissingTxModifiable, opts.unknown);
|
|
4376
|
+
else if (otherV2)
|
|
4377
|
+
txModifiable = other.modifiable(opts.allowMissingTxModifiable, opts.unknown);
|
|
4378
|
+
const thisGlobal = { ...this.global };
|
|
4379
|
+
const otherGlobal = { ...other.global };
|
|
4380
|
+
if (thisV2 !== otherV2) {
|
|
4381
|
+
if (!thisV2)
|
|
4382
|
+
delete thisGlobal.fallbackLocktime;
|
|
4383
|
+
if (!otherV2)
|
|
4384
|
+
delete otherGlobal.fallbackLocktime;
|
|
4385
|
+
if (!thisV2)
|
|
4386
|
+
delete thisGlobal.version;
|
|
4387
|
+
if (!otherV2)
|
|
4388
|
+
delete otherGlobal.version;
|
|
4389
|
+
}
|
|
4390
|
+
const fallbackLocktime = thisGlobal.fallbackLocktime !== undefined ? thisGlobal.fallbackLocktime : otherGlobal.fallbackLocktime;
|
|
4391
|
+
delete thisGlobal.txModifiable;
|
|
4392
|
+
delete otherGlobal.txModifiable;
|
|
4393
|
+
delete thisGlobal.fallbackLocktime;
|
|
4394
|
+
delete otherGlobal.fallbackLocktime;
|
|
4395
|
+
const global = combineKeyMap(PSBTGlobal, thisGlobal, otherGlobal, opts.unknown, opts.proprietary);
|
|
4396
|
+
if (fallbackLocktime !== undefined)
|
|
4397
|
+
global.fallbackLocktime = fallbackLocktime;
|
|
4398
|
+
if (PSBTVersion)
|
|
4399
|
+
global.version = PSBTVersion;
|
|
4400
|
+
if (txModifiable === undefined)
|
|
4401
|
+
delete global.txModifiable;
|
|
4402
|
+
else
|
|
4403
|
+
global.txModifiable = txModifiable;
|
|
4404
|
+
let hasOpaqueFinalizedV0 = false;
|
|
4405
|
+
const inputs = this.inputs.map((current, i) => {
|
|
4406
|
+
const currentFinal = this.inputStatus(i) === "finalized";
|
|
4407
|
+
const otherFinal = other.inputStatus(i) === "finalized";
|
|
4408
|
+
if (!thisV2 && currentFinal || !otherV2 && otherFinal)
|
|
4409
|
+
hasOpaqueFinalizedV0 = true;
|
|
4410
|
+
if (currentFinal && otherFinal) {
|
|
4411
|
+
for (const k of ["finalScriptSig", "finalScriptWitness"]) {
|
|
4412
|
+
const currentHas = !!this.inputs[i][k]?.length;
|
|
4413
|
+
const otherHas = !!other.inputs[i][k]?.length;
|
|
4414
|
+
if (currentHas !== otherHas)
|
|
4415
|
+
throw new Error(`Transaction/combine: different finalized field=${k} input=${i}`);
|
|
4416
|
+
}
|
|
4417
|
+
}
|
|
4418
|
+
const combined = combineKeyMap(PSBTInput, current, other.inputs[i], opts.unknown, opts.proprietary);
|
|
4419
|
+
if (currentFinal || otherFinal)
|
|
4420
|
+
cleanFinalInput(combined, opts.unknown, opts.proprietary);
|
|
4421
|
+
return cloneDeep(normalizeInput(combined, undefined, undefined, opts.disableScriptCheck, opts.unknown, opts.proprietary));
|
|
4422
|
+
});
|
|
4423
|
+
if (hasOpaqueFinalizedV0 && global.txModifiable !== undefined)
|
|
4424
|
+
global.txModifiable &= ~3;
|
|
4425
|
+
const candidate = new Transaction2({ ...opts, PSBTVersion });
|
|
4426
|
+
const outputs = this.outputs.map((current, i) => {
|
|
4427
|
+
const combined = combineKeyMap(PSBTOutput, current, other.outputs[i], opts.unknown, opts.proprietary);
|
|
4428
|
+
return cloneDeep(candidate.normalizeOutput(combined));
|
|
4429
|
+
});
|
|
4430
|
+
candidate.global = global;
|
|
4431
|
+
candidate.inputs = inputs;
|
|
4432
|
+
candidate.outputs = outputs;
|
|
4433
|
+
if ((!thisV2 || !otherV2) && candidate.isPSBTv2())
|
|
4434
|
+
candidate.global.txModifiable = candidate.txModifiable;
|
|
4435
|
+
if (!equalBytes2(candidate.unsignedTx, unsignedTx))
|
|
4436
|
+
throw new Error("Transaction/combine: combined unsigned tx differs");
|
|
4437
|
+
this.global = candidate.global;
|
|
4438
|
+
this.inputs = candidate.inputs;
|
|
4439
|
+
this.outputs = candidate.outputs;
|
|
4440
|
+
return this;
|
|
4441
|
+
}
|
|
4442
|
+
clone() {
|
|
4443
|
+
return Transaction2.fromPSBT(this.toPSBT(), this.opts);
|
|
4444
|
+
}
|
|
4445
|
+
}
|
|
4446
|
+
export { taprootTweakPrivKey, NETWORK2, TEST_NETWORK2, ScriptNum2, Script2, TaprootControlBlock2, OutScript2, taprootListToTree2, p2tr2, Address2, SigHash2, Transaction2 };
|