zeldhash-miner 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/worker.js CHANGED
@@ -1,152 +1,4 @@
1
- var u = /* @__PURE__ */ ((t) => (t.INVALID_ADDRESS = "INVALID_ADDRESS", t.UNSUPPORTED_ADDRESS_TYPE = "UNSUPPORTED_ADDRESS_TYPE", t.INSUFFICIENT_FUNDS = "INSUFFICIENT_FUNDS", t.NO_CHANGE_OUTPUT = "NO_CHANGE_OUTPUT", t.MULTIPLE_CHANGE_OUTPUTS = "MULTIPLE_CHANGE_OUTPUTS", t.INVALID_INPUT = "INVALID_INPUT", t.WEBGPU_NOT_AVAILABLE = "WEBGPU_NOT_AVAILABLE", t.WORKER_ERROR = "WORKER_ERROR", t.MINING_ABORTED = "MINING_ABORTED", t.DUST_OUTPUT = "DUST_OUTPUT", t))(u || {});
2
- const R = (1n << 64n) - 1n, K = (t) => {
3
- if (t < 0n)
4
- throw new Error("nonce must be non-negative");
5
- if (t === 0n) return 1;
6
- let e = 0, n = t;
7
- for (; n > 0n; )
8
- e += 1, n >>= 8n;
9
- return e;
10
- }, H = (t) => {
11
- if (t < 0n)
12
- throw new Error("nonce must be non-negative");
13
- if (t <= 23n) return 1;
14
- if (t <= 0xffn) return 2;
15
- if (t <= 0xffffn) return 3;
16
- if (t <= 0xffffffffn) return 5;
17
- if (t <= R) return 9;
18
- throw new Error("nonce range exceeds u64");
19
- }, X = (t) => {
20
- if (!Number.isInteger(t) || t <= 0 || t > 8)
21
- throw new Error("nonceLength must be between 1 and 8");
22
- return (1n << BigInt(t * 8)) - 1n;
23
- }, j = (t) => {
24
- switch (t) {
25
- case 1:
26
- return 23n;
27
- case 2:
28
- return 0xffn;
29
- case 3:
30
- return 0xffffn;
31
- case 5:
32
- return 0xffffffffn;
33
- case 9:
34
- return R;
35
- default:
36
- throw new Error("cbor nonceLength must be one of 1, 2, 3, 5, 9");
37
- }
38
- }, Y = (t, e) => {
39
- if (t < 0n)
40
- throw new Error("startNonce must be non-negative");
41
- if (!Number.isInteger(e) || e <= 0)
42
- throw new Error("batchSize must be a positive integer");
43
- const n = t + BigInt(e - 1);
44
- if (n > R)
45
- throw new Error("nonce range exceeds u64");
46
- const i = [];
47
- let r = t;
48
- for (; r <= n; ) {
49
- const s = K(r), o = X(s), a = n < o ? n : o, l = a - r + 1n;
50
- if (l > BigInt(Number.MAX_SAFE_INTEGER))
51
- throw new Error("segment size exceeds safe integer range");
52
- if (i.push({
53
- start: r,
54
- size: Number(l),
55
- nonceLength: s
56
- }), a === n)
57
- break;
58
- r = a + 1n;
59
- }
60
- return i;
61
- }, J = (t, e) => {
62
- if (t < 0n)
63
- throw new Error("startNonce must be non-negative");
64
- if (!Number.isInteger(e) || e <= 0)
65
- throw new Error("batchSize must be a positive integer");
66
- const n = t + BigInt(e - 1);
67
- if (n > R)
68
- throw new Error("nonce range exceeds u64");
69
- const i = [];
70
- let r = t;
71
- for (; r <= n; ) {
72
- const s = H(r), o = j(s), a = n < o ? n : o, l = a - r + 1n;
73
- if (l > BigInt(Number.MAX_SAFE_INTEGER))
74
- throw new Error("segment size exceeds safe integer range");
75
- if (i.push({
76
- start: r,
77
- size: Number(l),
78
- nonceLength: s
79
- }), a === n)
80
- break;
81
- r = a + 1n;
82
- }
83
- return i;
84
- }, Q = {};
85
- if (typeof globalThis.__ZELDMINER_WASM_BASE__ > "u")
86
- try {
87
- const t = typeof window < "u" && window.location?.origin ? window.location.origin : typeof self < "u" && self.location?.origin ? self.location.origin : "http://localhost";
88
- globalThis.__ZELDMINER_WASM_BASE__ = new URL("/wasm/", t).href;
89
- } catch {
90
- globalThis.__ZELDMINER_WASM_BASE__ = "/wasm/";
91
- }
92
- let y = null, d = null, O = !1;
93
- const Z = () => {
94
- if (O) return;
95
- O = !0;
96
- const t = globalThis.GPUAdapter?.prototype, e = t?.requestDevice;
97
- !t || typeof e != "function" || (t.requestDevice = function(i) {
98
- if (i?.requiredLimits && typeof this.limits == "object") {
99
- const r = i.requiredLimits, s = this.limits;
100
- for (const o of Object.keys(r))
101
- (!(o in s) || s[o] === void 0) && delete r[o];
102
- }
103
- return e.call(this, i);
104
- });
105
- }, U = (t) => t.endsWith("/") ? t : `${t}/`, A = (t) => {
106
- const e = t.trim();
107
- return e && (typeof window < "u" && typeof window.location?.origin == "string" ? U(new URL(e, window.location.origin).href) : U(new URL(e, import.meta.url).href));
108
- }, tt = () => {
109
- const t = globalThis.__ZELDMINER_WASM_BASE__;
110
- if (typeof t == "string" && t.trim())
111
- return A(t);
112
- const e = Q?.VITE_ZELDMINER_WASM_BASE;
113
- if (typeof e == "string" && e.trim())
114
- return A(e);
115
- const n = "./";
116
- return n.trim() ? A(`${U(n.trim())}wasm/`) : A("/wasm/");
117
- }, z = tt(), W = `${z}zeldhash_miner_wasm.js`, et = `${z}zeldhash_miner_wasm_bg.wasm`, x = (t) => t instanceof Error ? t.message : String(t), nt = async () => {
118
- Z();
119
- let t;
120
- try {
121
- t = await import(
122
- /* @vite-ignore */
123
- W
124
- );
125
- } catch (i) {
126
- throw new Error(
127
- `Failed to import WASM bundle (${W}). Did you run ./scripts/build-wasm.sh? (${x(i)})`
128
- );
129
- }
130
- const e = t.default;
131
- if (typeof e != "function")
132
- throw new Error("WASM init function is missing from the bundle.");
133
- try {
134
- const i = new URL(et, import.meta.url);
135
- await e({ module_or_path: i });
136
- } catch (i) {
137
- throw new Error(
138
- `Failed to initialize WASM bundle: ${x(i)}`
139
- );
140
- }
141
- const n = t;
142
- try {
143
- n.init_panic_hook?.();
144
- } catch {
145
- }
146
- return n;
147
- }, it = async () => y || (d || (d = nt().then((t) => (y = t, t)).catch((t) => {
148
- throw d = null, t;
149
- })), d);
1
+ import { Z as r, l as C, s as U, a as V } from "./nonce.js";
150
2
  if (typeof globalThis.__ZELDMINER_WASM_BASE__ > "u")
151
3
  try {
152
4
  const t = typeof self < "u" && self.location?.origin ? self.location.origin : "http://localhost";
@@ -154,200 +6,200 @@ if (typeof globalThis.__ZELDMINER_WASM_BASE__ > "u")
154
6
  } catch {
155
7
  globalThis.__ZELDMINER_WASM_BASE__ = "/wasm/";
156
8
  }
157
- const B = self, rt = B.name ?? void 0, I = (t) => t instanceof Error ? t.message : String(t);
158
- let N = "cpu", b = null;
159
- const w = (t) => {
160
- B.postMessage({ ...t, workerId: rt });
161
- }, h = (t, e = u.WORKER_ERROR, n) => {
162
- w({ type: "error", message: t, code: e, details: n });
163
- }, ot = (t) => typeof t == "object" && t !== null && "ok" in t, st = (t) => typeof t == "object" && t !== null && "nonce" in t && "txid" in t, at = (t) => {
9
+ const w = self, G = w.name ?? void 0, R = (t) => t instanceof Error ? t.message : String(t);
10
+ let m = "cpu", f = null;
11
+ const g = (t) => {
12
+ w.postMessage({ ...t, workerId: G });
13
+ }, b = (t, e = r.WORKER_ERROR, n) => {
14
+ g({ type: "error", message: t, code: e, details: n });
15
+ }, D = (t) => typeof t == "object" && t !== null && "ok" in t, F = (t) => typeof t == "object" && t !== null && "nonce" in t && "txid" in t, K = (t) => {
164
16
  const e = BigInt(Number.MAX_SAFE_INTEGER);
165
17
  return t > e ? Number.MAX_SAFE_INTEGER : t < -e ? -Number.MAX_SAFE_INTEGER : Number(t);
166
- }, ct = (t) => ({
18
+ }, Z = (t) => ({
167
19
  nonceLength: t.nonceLength,
168
20
  prefix: new Uint8Array(t.prefix),
169
21
  suffix: new Uint8Array(t.suffix),
170
22
  useCborNonce: t.useCborNonce
171
- }), F = (t, e) => {
172
- t.set(e.nonceLength, ct(e));
173
- }, ut = async (t, e, n, i, r) => {
174
- const s = t.get(i.nonceLength);
175
- if (s)
176
- return s;
177
- const o = e.build_mining_template(
23
+ }), M = (t, e) => {
24
+ t.set(e.nonceLength, Z(e));
25
+ }, $ = async (t, e, n, s, i) => {
26
+ const u = t.get(s.nonceLength);
27
+ if (u)
28
+ return u;
29
+ const p = e.build_mining_template(
178
30
  n.inputs,
179
31
  n.outputs,
180
- r,
32
+ i,
181
33
  BigInt(n.satsPerVbyte),
182
- i.start,
183
- i.size,
34
+ s.start,
35
+ s.size,
184
36
  n.distribution ?? null
185
37
  ), a = {
186
- ...o,
187
- nonceLength: i.nonceLength,
188
- useCborNonce: o.useCborNonce ?? n.useCborNonce
38
+ ...p,
39
+ nonceLength: s.nonceLength,
40
+ useCborNonce: p.useCborNonce ?? n.useCborNonce
189
41
  };
190
- return F(t, a), a;
191
- }, lt = async (t, e, n, i, r, s, o, a) => {
42
+ return M(t, a), a;
43
+ }, X = async (t, e, n, s, i, u, p, a) => {
192
44
  if (e === "gpu") {
193
45
  if (!t.mine_batch_gpu)
194
46
  throw new Error("GPU mining requested but mine_batch_gpu is unavailable");
195
47
  return t.mine_batch_gpu(
196
48
  n,
197
- i,
198
- r,
199
49
  s,
200
- o,
50
+ i,
51
+ u,
52
+ p,
201
53
  a
202
54
  );
203
55
  }
204
56
  return t.mine_batch_wasm(
205
57
  n,
206
- i,
207
- r,
208
58
  s,
209
- o,
59
+ i,
60
+ u,
61
+ p,
210
62
  a
211
63
  );
212
- }, ft = async (t, e) => {
64
+ }, j = async (t, e) => {
213
65
  let n;
214
66
  try {
215
- if (n = await it(), N === "gpu") {
67
+ if (n = await C(), m === "gpu") {
216
68
  if (!n.mine_batch_gpu) {
217
- h(
69
+ b(
218
70
  "GPU mining requested but mine_batch_gpu is unavailable",
219
- u.WEBGPU_NOT_AVAILABLE
71
+ r.WEBGPU_NOT_AVAILABLE
220
72
  );
221
73
  return;
222
74
  }
223
75
  n.init_gpu && await n.init_gpu();
224
76
  }
225
- } catch (m) {
226
- const g = I(m), E = N === "gpu" ? u.WEBGPU_NOT_AVAILABLE : u.WORKER_ERROR;
227
- h(`Failed to initialize WASM: ${g}`, E);
77
+ } catch (d) {
78
+ const _ = R(d), h = m === "gpu" ? r.WEBGPU_NOT_AVAILABLE : r.WORKER_ERROR;
79
+ b(`Failed to initialize WASM: ${_}`, h);
228
80
  return;
229
81
  }
230
- const i = /* @__PURE__ */ new Map(), r = t.template.useCborNonce ?? !!(t.distribution && t.distribution.length > 0);
231
- F(i, { ...t.template, useCborNonce: r });
232
- const s = t.nonceStep ?? BigInt(t.batchSize), o = t.network === "signet" ? "testnet" : t.network;
233
- let a = t.startNonce, l = 0n;
234
- const G = performance.now();
82
+ const s = /* @__PURE__ */ new Map(), i = t.template.useCborNonce ?? !!(t.distribution && t.distribution.length > 0);
83
+ M(s, { ...t.template, useCborNonce: i });
84
+ const u = t.nonceStep ?? BigInt(t.batchSize), p = t.network === "signet" ? "testnet" : t.network;
85
+ let a = t.startNonce, N = 0n;
86
+ const T = performance.now();
235
87
  for (; !e.signal.aborted; ) {
236
- const m = a;
237
- let g = t.batchSize, E = 0n;
238
- for (; g > 0 && !e.signal.aborted; ) {
239
- const D = m + E;
240
- let c;
88
+ const d = a;
89
+ let _ = t.batchSize, h = 0n;
90
+ for (; _ > 0 && !e.signal.aborted; ) {
91
+ const B = d + h;
92
+ let o;
241
93
  try {
242
- c = (r ? J(D, g) : Y(D, g))[0];
243
- } catch (_) {
244
- h(
245
- `Invalid nonce range: ${I(_)}`,
246
- u.INVALID_INPUT
94
+ o = (i ? U(B, _) : V(B, _))[0];
95
+ } catch (l) {
96
+ b(
97
+ `Invalid nonce range: ${R(l)}`,
98
+ r.INVALID_INPUT
247
99
  ), e.abort();
248
100
  return;
249
101
  }
250
- let S;
102
+ let I;
251
103
  try {
252
- S = await ut(
253
- i,
104
+ I = await $(
105
+ s,
254
106
  n,
255
107
  {
256
108
  inputs: t.inputs,
257
109
  outputs: t.outputs,
258
110
  satsPerVbyte: t.satsPerVbyte,
259
111
  distribution: t.distribution,
260
- useCborNonce: r
112
+ useCborNonce: i
261
113
  },
262
- c,
263
- o
114
+ o,
115
+ p
264
116
  );
265
- } catch (_) {
266
- h(
267
- `Failed to build mining template: ${I(_)}`,
268
- u.WORKER_ERROR
117
+ } catch (l) {
118
+ b(
119
+ `Failed to build mining template: ${R(l)}`,
120
+ r.WORKER_ERROR
269
121
  ), e.abort();
270
122
  return;
271
123
  }
272
- let f;
273
- const k = performance.now();
124
+ let c;
125
+ const O = performance.now();
274
126
  try {
275
- f = await lt(
127
+ c = await X(
276
128
  n,
277
- N,
278
- S.prefix,
279
- S.suffix,
280
- c.start,
281
- c.size,
129
+ m,
130
+ I.prefix,
131
+ I.suffix,
132
+ o.start,
133
+ o.size,
282
134
  t.targetZeros,
283
- r
135
+ i
284
136
  );
285
- } catch (_) {
286
- const p = I(_);
287
- h(
288
- `Batch mining failed: ${p}`,
289
- u.WORKER_ERROR
137
+ } catch (l) {
138
+ const E = R(l);
139
+ b(
140
+ `Batch mining failed: ${E}`,
141
+ r.WORKER_ERROR
290
142
  ), e.abort();
291
143
  return;
292
144
  }
293
- const P = performance.now() - k;
294
- if (ot(f)) {
295
- if (!f.ok) {
296
- h(
297
- f.error ?? "Validation failed",
298
- u.INVALID_INPUT
145
+ const S = performance.now() - O;
146
+ if (D(c)) {
147
+ if (!c.ok) {
148
+ b(
149
+ c.error ?? "Validation failed",
150
+ r.INVALID_INPUT
299
151
  ), e.abort();
300
152
  return;
301
153
  }
302
- } else if (st(f)) {
303
- const _ = l + E, p = BigInt(f.nonce) - c.start + 1n, L = _ + p, T = performance.now() - G, M = T > 0 ? at(L) / (T / 1e3) : 0, q = c.start + p - 1n, C = {
154
+ } else if (F(c)) {
155
+ const l = N + h, E = BigInt(c.nonce) - o.start + 1n, A = l + E, y = performance.now() - T, L = y > 0 ? K(A) / (y / 1e3) : 0, P = o.start + E - 1n, x = {
304
156
  psbt: "",
305
- txid: f.txid,
306
- nonce: BigInt(f.nonce),
307
- attempts: L,
308
- duration: T,
309
- hashRate: M
157
+ txid: c.txid,
158
+ nonce: BigInt(c.nonce),
159
+ attempts: A,
160
+ duration: y,
161
+ hashRate: L
310
162
  };
311
- w({
163
+ g({
312
164
  type: "found",
313
- result: C,
314
- hashesProcessed: L,
315
- hashRate: M,
316
- lastNonce: q
165
+ result: x,
166
+ hashesProcessed: A,
167
+ hashRate: L,
168
+ lastNonce: P
317
169
  }), e.abort();
318
170
  return;
319
171
  }
320
- l += BigInt(c.size), E += BigInt(c.size), g -= c.size;
321
- const v = P > 0 ? c.size / (P / 1e3) : c.size, $ = c.start + BigInt(c.size) - 1n;
322
- w({ type: "progress", hashesProcessed: l, hashRate: v, lastNonce: $ });
172
+ N += BigInt(o.size), h += BigInt(o.size), _ -= o.size;
173
+ const W = S > 0 ? o.size / (S / 1e3) : o.size, k = o.start + BigInt(o.size) - 1n;
174
+ g({ type: "progress", hashesProcessed: N, hashRate: W, lastNonce: k });
323
175
  }
324
176
  if (e.signal.aborted)
325
177
  break;
326
- const V = m + BigInt(t.batchSize) - 1n;
327
- w({ type: "batch_complete", lastNonce: V }), a = m + s;
178
+ const z = d + BigInt(t.batchSize) - 1n;
179
+ g({ type: "batch_complete", lastNonce: z }), a = d + u;
328
180
  }
329
- }, _t = (t) => {
181
+ }, q = (t) => {
330
182
  const e = new AbortController();
331
- b?.abort(), b = e, ft(t, e).finally(() => {
332
- b === e && (b = null);
183
+ f?.abort(), f = e, j(t, e).finally(() => {
184
+ f === e && (f = null);
333
185
  });
334
186
  };
335
- B.addEventListener("message", (t) => {
187
+ w.addEventListener("message", (t) => {
336
188
  const e = t.data;
337
189
  switch (e.type) {
338
190
  case "init":
339
- N = e.mode, w({ type: "ready" });
191
+ m = e.mode, g({ type: "ready" });
340
192
  break;
341
193
  case "mine":
342
- _t(e);
194
+ q(e);
343
195
  break;
344
196
  case "stop":
345
- b?.abort();
197
+ f?.abort();
346
198
  break;
347
199
  default:
348
- h(
200
+ b(
349
201
  `Unknown message type: ${e.type}`,
350
- u.WORKER_ERROR
202
+ r.WORKER_ERROR
351
203
  );
352
204
  }
353
205
  });
@@ -1 +1 @@
1
- {"version":3,"file":"worker.js","sources":["src/types.ts","src/nonce.ts","src/wasm.ts","src/worker.ts"],"sourcesContent":["export enum ZeldMinerErrorCode {\n INVALID_ADDRESS = \"INVALID_ADDRESS\",\n UNSUPPORTED_ADDRESS_TYPE = \"UNSUPPORTED_ADDRESS_TYPE\",\n INSUFFICIENT_FUNDS = \"INSUFFICIENT_FUNDS\",\n NO_CHANGE_OUTPUT = \"NO_CHANGE_OUTPUT\",\n MULTIPLE_CHANGE_OUTPUTS = \"MULTIPLE_CHANGE_OUTPUTS\",\n INVALID_INPUT = \"INVALID_INPUT\",\n WEBGPU_NOT_AVAILABLE = \"WEBGPU_NOT_AVAILABLE\",\n WORKER_ERROR = \"WORKER_ERROR\",\n MINING_ABORTED = \"MINING_ABORTED\",\n DUST_OUTPUT = \"DUST_OUTPUT\",\n}\n\nexport type ZeldMinerErrorDetails = Record<string, unknown>;\n\nexport type Network = \"mainnet\" | \"testnet\" | \"signet\" | \"regtest\";\n\nexport interface ZeldMinerOptions {\n network: Network;\n batchSize: number;\n useWebGPU: boolean;\n workerThreads: number;\n satsPerVbyte: number;\n}\n\nexport interface MiningCoordinatorOptions {\n mode: WorkerMode;\n batchSize: number;\n workerThreads: number;\n}\n\nexport interface TxInput {\n txid: string;\n vout: number;\n scriptPubKey: string;\n amount: number;\n}\n\nexport interface TxOutput {\n address: string;\n amount?: number;\n change: boolean;\n}\n\nexport interface MineResult {\n psbt: string;\n txid: string;\n nonce: bigint;\n attempts: bigint;\n duration: number;\n hashRate: number;\n}\n\nexport interface ProgressEvent {\n hashesProcessed: bigint;\n hashRate: number;\n elapsedMs?: number;\n lastNonce?: bigint;\n workerId?: string;\n}\n\nexport type WorkerMode = \"cpu\" | \"gpu\";\n\nexport type WorkerMessage =\n | { type: \"init\"; mode: WorkerMode }\n | {\n type: \"mine\";\n inputs: TxInput[];\n outputs: TxOutput[];\n network: Network;\n satsPerVbyte: number;\n template: WorkerTemplate;\n startNonce: bigint;\n batchSize: number;\n targetZeros: number;\n nonceStep?: bigint;\n distribution?: bigint[];\n }\n | { type: \"stop\" };\n\nexport type WorkerResponse =\n | { type: \"ready\"; workerId?: string }\n | {\n type: \"progress\";\n hashesProcessed: bigint;\n hashRate: number;\n lastNonce?: bigint;\n workerId?: string;\n }\n | {\n type: \"found\";\n result: MineResult;\n hashesProcessed?: bigint;\n hashRate?: number;\n lastNonce?: bigint;\n workerId?: string;\n }\n | { type: \"batch_complete\"; lastNonce: bigint; workerId?: string }\n | {\n type: \"error\";\n message: string;\n code?: ZeldMinerErrorCode;\n details?: ZeldMinerErrorDetails;\n workerId?: string;\n };\n\nexport interface MiningState {\n mode: WorkerMode;\n running: boolean;\n startNonce: bigint;\n nextNonce: bigint;\n batchSize: number;\n targetZeros: number;\n hashesProcessed: bigint;\n lastHashRate?: number;\n}\n\nexport interface MiningTemplate {\n prefix: Uint8Array;\n suffix: Uint8Array;\n useCborNonce?: boolean;\n}\n\nexport interface WorkerTemplate extends MiningTemplate {\n nonceLength: number;\n useCborNonce?: boolean;\n}\n\nexport interface ValidationResult {\n ok: boolean;\n error?: string;\n addressType?: \"p2wpkh\" | \"p2tr\";\n network?: Network;\n}\n\nexport interface WasmExports {\n init_panic_hook: () => void;\n mine_batch_wasm: (\n txPrefix: Uint8Array,\n txSuffix: Uint8Array,\n startNonce: bigint,\n batchSize: number,\n targetZeros: number,\n useCborNonce?: boolean\n ) => ValidationResult | MineResult | null;\n mine_batch_gpu?: (\n txPrefix: Uint8Array,\n txSuffix: Uint8Array,\n startNonce: bigint,\n batchSize: number,\n targetZeros: number,\n useCborNonce?: boolean\n ) => Promise<ValidationResult | MineResult | null>;\n mine_range_wasm: (\n inputs: TxInput[],\n outputs: TxOutput[],\n network: Network,\n satsPerVbyte: bigint,\n startNonce: bigint,\n batchSize: number,\n targetZeros: number,\n distribution?: bigint[] | null\n ) => ValidationResult | MineResult | null;\n mine_range_gpu?: (\n inputs: TxInput[],\n outputs: TxOutput[],\n network: Network,\n satsPerVbyte: bigint,\n startNonce: bigint,\n batchSize: number,\n targetZeros: number,\n distribution?: bigint[] | null\n ) => Promise<ValidationResult | MineResult | null>;\n validate_address: (addr: string, network: Network) => ValidationResult;\n build_psbt: (\n inputs: TxInput[],\n outputs: TxOutput[],\n network: Network,\n satsPerVbyte: bigint,\n nonce: bigint,\n distribution?: bigint[] | null\n ) => string;\n build_mining_template: (\n inputs: TxInput[],\n outputs: TxOutput[],\n network: Network,\n satsPerVbyte: bigint,\n startNonce: bigint,\n batchSize: number,\n distribution?: bigint[] | null\n ) => MiningTemplate;\n compute_txid: (txBytes: Uint8Array) => string;\n init_gpu?: () => Promise<unknown>;\n calibrate_batch_size?: () => Promise<number>;\n}\n\nexport type ProgressStats = ProgressEvent;\n\nexport interface MineParams {\n inputs: TxInput[];\n outputs: TxOutput[];\n targetZeros: number;\n startNonce?: bigint;\n batchSize?: number;\n signal?: AbortSignal;\n distribution?: bigint[];\n}\n\n","const MAX_U64 = (1n << 64n) - 1n;\n\nexport interface NonceSegment {\n start: bigint;\n size: number;\n nonceLength: number;\n}\n\nexport const nonceLength = (nonce: bigint): number => {\n if (nonce < 0n) {\n throw new Error(\"nonce must be non-negative\");\n }\n\n if (nonce === 0n) return 1;\n\n let len = 0;\n let value = nonce;\n while (value > 0n) {\n len += 1;\n value >>= 8n;\n }\n return len;\n};\n\nexport const cborNonceLength = (nonce: bigint): number => {\n if (nonce < 0n) {\n throw new Error(\"nonce must be non-negative\");\n }\n\n if (nonce <= 23n) return 1;\n if (nonce <= 0xffn) return 2;\n if (nonce <= 0xffffn) return 3;\n if (nonce <= 0xffff_ffffn) return 5;\n if (nonce <= MAX_U64) return 9;\n\n throw new Error(\"nonce range exceeds u64\");\n};\n\nconst maxValueForLength = (len: number): bigint => {\n if (!Number.isInteger(len) || len <= 0 || len > 8) {\n throw new Error(\"nonceLength must be between 1 and 8\");\n }\n return (1n << BigInt(len * 8)) - 1n;\n};\n\nconst maxValueForCborLength = (len: number): bigint => {\n switch (len) {\n case 1:\n return 23n;\n case 2:\n return 0xffn;\n case 3:\n return 0xffffn;\n case 5:\n return 0xffff_ffffn;\n case 9:\n return MAX_U64;\n default:\n throw new Error(\"cbor nonceLength must be one of 1, 2, 3, 5, 9\");\n }\n};\n\nexport const splitNonceSegments = (startNonce: bigint, span: number): NonceSegment[] => {\n if (startNonce < 0n) {\n throw new Error(\"startNonce must be non-negative\");\n }\n if (!Number.isInteger(span) || span <= 0) {\n throw new Error(\"batchSize must be a positive integer\");\n }\n\n const end = startNonce + BigInt(span - 1);\n if (end > MAX_U64) {\n throw new Error(\"nonce range exceeds u64\");\n }\n\n const segments: NonceSegment[] = [];\n let current = startNonce;\n\n while (current <= end) {\n const len = nonceLength(current);\n const maxForLen = maxValueForLength(len);\n const segmentEnd = end < maxForLen ? end : maxForLen;\n const segmentSize = segmentEnd - current + 1n;\n\n if (segmentSize > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error(\"segment size exceeds safe integer range\");\n }\n\n segments.push({\n start: current,\n size: Number(segmentSize),\n nonceLength: len,\n });\n\n if (segmentEnd === end) {\n break;\n }\n\n current = segmentEnd + 1n;\n }\n\n return segments;\n};\n\nexport const maxNonceForLength = (len: number): bigint => maxValueForLength(len);\n\nexport const splitNonceSegmentsCbor = (startNonce: bigint, span: number): NonceSegment[] => {\n if (startNonce < 0n) {\n throw new Error(\"startNonce must be non-negative\");\n }\n if (!Number.isInteger(span) || span <= 0) {\n throw new Error(\"batchSize must be a positive integer\");\n }\n\n const end = startNonce + BigInt(span - 1);\n if (end > MAX_U64) {\n throw new Error(\"nonce range exceeds u64\");\n }\n\n const segments: NonceSegment[] = [];\n let current = startNonce;\n\n while (current <= end) {\n const len = cborNonceLength(current);\n const maxForLen = maxValueForCborLength(len);\n const segmentEnd = end < maxForLen ? end : maxForLen;\n const segmentSize = segmentEnd - current + 1n;\n\n if (segmentSize > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error(\"segment size exceeds safe integer range\");\n }\n\n segments.push({\n start: current,\n size: Number(segmentSize),\n nonceLength: len,\n });\n\n if (segmentEnd === end) {\n break;\n }\n\n current = segmentEnd + 1n;\n }\n\n return segments;\n};\n\n\n","import type { WasmExports } from \"./types\";\n\n// Bootstrap: define a sensible default for WASM base path so consumers don't\n// need to patch the library. In Vite/dev the import.meta.url points inside\n// node_modules which is not served, so we derive a public path from the window\n// origin when available.\nif (typeof (globalThis as { __ZELDMINER_WASM_BASE__?: unknown }).__ZELDMINER_WASM_BASE__ === \"undefined\") {\n try {\n const origin =\n typeof window !== \"undefined\" && window.location?.origin\n ? window.location.origin\n : typeof self !== \"undefined\" && (self as { location?: { origin?: string } }).location?.origin\n ? (self as { location?: { origin?: string } }).location!.origin\n : \"http://localhost\";\n (globalThis as { __ZELDMINER_WASM_BASE__?: string }).__ZELDMINER_WASM_BASE__ = new URL(\"/wasm/\", origin!).href;\n } catch {\n (globalThis as { __ZELDMINER_WASM_BASE__?: string }).__ZELDMINER_WASM_BASE__ = \"/wasm/\";\n }\n}\n\nlet wasmModule: WasmExports | null = null;\nlet wasmInitPromise: Promise<WasmExports> | null = null;\n\n// Chrome/Dawn can reject requestDevice when optional limits (e.g.\n// maxInterStageShaderComponents) are present but unsupported. Strip any\n// limit keys the adapter doesn't expose to keep WebGPU initialization\n// portable across browser versions.\nlet webGpuLimitShimInstalled = false;\nconst installWebGpuLimitShim = (): void => {\n if (webGpuLimitShimInstalled) return;\n webGpuLimitShimInstalled = true;\n\n const adapterProto = (globalThis as typeof globalThis & { GPUAdapter?: { prototype?: unknown } })\n .GPUAdapter?.prototype as GPUAdapter | undefined;\n const requestDevice = adapterProto?.requestDevice;\n if (!adapterProto || typeof requestDevice !== \"function\") return;\n\n adapterProto.requestDevice = function patchedRequestDevice(\n this: GPUAdapter,\n descriptor?: GPUDeviceDescriptor\n ): Promise<GPUDevice> {\n if (descriptor?.requiredLimits && typeof this.limits === \"object\") {\n const limits = descriptor.requiredLimits as Record<string, unknown>;\n const supported = this.limits as unknown as Record<string, unknown>;\n for (const key of Object.keys(limits)) {\n if (!(key in supported) || supported[key] === undefined) {\n delete limits[key];\n }\n }\n }\n return requestDevice.call(this, descriptor);\n };\n};\n\nconst ensureTrailingSlash = (value: string): string =>\n value.endsWith(\"/\") ? value : `${value}/`;\n\nconst toAbsoluteBase = (base: string): string => {\n const trimmed = base.trim();\n if (!trimmed) return trimmed;\n // Use window origin when available so Vite treats it as an external URL and does not try to transform public assets.\n if (typeof window !== \"undefined\" && typeof window.location?.origin === \"string\") {\n return ensureTrailingSlash(new URL(trimmed, window.location.origin).href);\n }\n return ensureTrailingSlash(new URL(trimmed, import.meta.url).href);\n};\n\nconst resolveWasmBase = (): string => {\n const globalBase = (globalThis as { __ZELDMINER_WASM_BASE__?: unknown })\n .__ZELDMINER_WASM_BASE__;\n if (typeof globalBase === \"string\" && globalBase.trim()) {\n return toAbsoluteBase(globalBase);\n }\n\n const envBase = (import.meta as ImportMeta & { env?: Record<string, unknown> })\n .env?.VITE_ZELDMINER_WASM_BASE;\n if (typeof envBase === \"string\" && envBase.trim()) {\n return toAbsoluteBase(envBase);\n }\n\n const viteBase = (import.meta as ImportMeta & { env?: Record<string, unknown> }).env?.BASE_URL;\n if (typeof viteBase === \"string\" && viteBase.trim()) {\n return toAbsoluteBase(`${ensureTrailingSlash(viteBase.trim())}wasm/`);\n }\n\n return toAbsoluteBase(\"/wasm/\");\n};\n\nconst WASM_BASE_URL = resolveWasmBase();\nconst WASM_JS_PATH = `${WASM_BASE_URL}zeldhash_miner_wasm.js`;\nconst WASM_BINARY_PATH = `${WASM_BASE_URL}zeldhash_miner_wasm_bg.wasm`;\n\nconst formatError = (err: unknown): string =>\n err instanceof Error ? err.message : String(err);\n\nconst loadModule = async (): Promise<WasmExports> => {\n installWebGpuLimitShim();\n\n let bindings: unknown;\n try {\n bindings = await import(/* @vite-ignore */ WASM_JS_PATH);\n } catch (err) {\n throw new Error(\n `Failed to import WASM bundle (${WASM_JS_PATH}). ` +\n `Did you run ./scripts/build-wasm.sh? (${formatError(err)})`\n );\n }\n\n const init = (bindings as { default?: unknown }).default;\n if (typeof init !== \"function\") {\n throw new Error(\"WASM init function is missing from the bundle.\");\n }\n\n try {\n const wasmUrl = new URL(WASM_BINARY_PATH, import.meta.url);\n await init({ module_or_path: wasmUrl });\n } catch (err) {\n throw new Error(\n `Failed to initialize WASM bundle: ${formatError(err)}`\n );\n }\n\n const typedBindings = bindings as WasmExports;\n try {\n typedBindings.init_panic_hook?.();\n } catch {\n /* ignore optional panic hook failures */\n }\n\n return typedBindings;\n};\n\nexport const loadWasm = async (): Promise<WasmExports> => {\n if (wasmModule) return wasmModule;\n if (!wasmInitPromise) {\n wasmInitPromise = loadModule()\n .then((mod) => {\n wasmModule = mod;\n return mod;\n })\n .catch((err) => {\n wasmInitPromise = null;\n throw err;\n });\n }\n return wasmInitPromise;\n};\n\nexport const getWasm = (): WasmExports | null => wasmModule;\n\nexport const resetWasm = (): void => {\n wasmModule = null;\n wasmInitPromise = null;\n};\n\n","// Bootstrap: define a sensible default for WASM base path in worker context.\n// Workers don't have `window`, but `self` provides location. This must run\n// before any import that calls resolveWasmBase().\nif (typeof (globalThis as { __ZELDMINER_WASM_BASE__?: unknown }).__ZELDMINER_WASM_BASE__ === \"undefined\") {\n try {\n const origin =\n typeof self !== \"undefined\" && (self as { location?: { origin?: string } }).location?.origin\n ? (self as { location?: { origin?: string } }).location!.origin\n : \"http://localhost\";\n (globalThis as { __ZELDMINER_WASM_BASE__?: string }).__ZELDMINER_WASM_BASE__ = new URL(\"/wasm/\", origin!).href;\n } catch {\n (globalThis as { __ZELDMINER_WASM_BASE__?: string }).__ZELDMINER_WASM_BASE__ = \"/wasm/\";\n }\n}\n\nimport type {\n MineResult,\n ValidationResult,\n WasmExports,\n WorkerMessage,\n WorkerMode,\n WorkerTemplate,\n WorkerResponse,\n} from \"./types\";\nimport { ZeldMinerErrorCode } from \"./types\";\nimport { splitNonceSegments, splitNonceSegmentsCbor } from \"./nonce\";\nimport { loadWasm } from \"./wasm\";\n\ntype MineMessage = Extract<WorkerMessage, { type: \"mine\" }>;\n\nconst ctx = self as unknown as DedicatedWorkerGlobalScope;\nconst workerId =\n (ctx as DedicatedWorkerGlobalScope & { name?: string }).name ?? undefined;\n\nconst formatError = (err: unknown): string =>\n err instanceof Error ? err.message : String(err);\n\nlet currentMode: WorkerMode = \"cpu\";\nlet miningAbort: AbortController | null = null;\nlet miningPromise: Promise<void> | null = null;\n\nconst post = (message: WorkerResponse): void => {\n ctx.postMessage({ ...message, workerId });\n};\n\nconst postError = (\n message: string,\n code: ZeldMinerErrorCode = ZeldMinerErrorCode.WORKER_ERROR,\n details?: Record<string, unknown>\n): void => {\n post({ type: \"error\", message, code, details });\n};\n\nconst isValidationResult = (val: unknown): val is ValidationResult =>\n typeof val === \"object\" && val !== null && \"ok\" in (val as object);\n\nconst isMineResult = (\n val: unknown\n): val is { nonce: bigint; txid: string } =>\n typeof val === \"object\" &&\n val !== null &&\n \"nonce\" in (val as object) &&\n \"txid\" in (val as object);\n\nconst safeBigIntToNumber = (value: bigint): number => {\n const max = BigInt(Number.MAX_SAFE_INTEGER);\n if (value > max) return Number.MAX_SAFE_INTEGER;\n if (value < -max) return -Number.MAX_SAFE_INTEGER;\n return Number(value);\n};\n\ntype TemplateCache = Map<number, WorkerTemplate>;\n\nconst cloneTemplate = (template: WorkerTemplate): WorkerTemplate => ({\n nonceLength: template.nonceLength,\n prefix: new Uint8Array(template.prefix),\n suffix: new Uint8Array(template.suffix),\n useCborNonce: template.useCborNonce,\n});\n\nconst cacheTemplate = (cache: TemplateCache, template: WorkerTemplate): void => {\n cache.set(template.nonceLength, cloneTemplate(template));\n};\n\nconst ensureTemplateForSegment = async (\n cache: TemplateCache,\n wasm: WasmExports,\n params: {\n inputs: MineMessage[\"inputs\"];\n outputs: MineMessage[\"outputs\"];\n satsPerVbyte: number;\n distribution?: bigint[];\n useCborNonce: boolean;\n },\n segment: { start: bigint; size: number; nonceLength: number },\n normalizedNetwork: MineMessage[\"network\"]\n): Promise<WorkerTemplate> => {\n const cached = cache.get(segment.nonceLength);\n if (cached) {\n return cached;\n }\n\n const template = wasm.build_mining_template(\n params.inputs,\n params.outputs,\n normalizedNetwork,\n BigInt(params.satsPerVbyte),\n segment.start,\n segment.size,\n params.distribution ?? null\n );\n\n const built: WorkerTemplate = {\n ...template,\n nonceLength: segment.nonceLength,\n useCborNonce: template.useCborNonce ?? params.useCborNonce,\n };\n\n cacheTemplate(cache, built);\n return built;\n};\n\nconst runBatch = async (\n wasm: WasmExports,\n mode: WorkerMode,\n prefix: Uint8Array,\n suffix: Uint8Array,\n startNonce: bigint,\n batchSize: number,\n targetZeros: number,\n useCborNonce: boolean\n): Promise<unknown> => {\n if (mode === \"gpu\") {\n if (!wasm.mine_batch_gpu) {\n throw new Error(\"GPU mining requested but mine_batch_gpu is unavailable\");\n }\n return wasm.mine_batch_gpu(\n prefix,\n suffix,\n startNonce,\n batchSize,\n targetZeros,\n useCborNonce\n );\n }\n\n return wasm.mine_batch_wasm(\n prefix,\n suffix,\n startNonce,\n batchSize,\n targetZeros,\n useCborNonce\n );\n};\n\nconst mineLoop = async (msg: MineMessage, abort: AbortController): Promise<void> => {\n let wasm: WasmExports;\n try {\n wasm = await loadWasm();\n if (currentMode === \"gpu\") {\n if (!wasm.mine_batch_gpu) {\n postError(\n \"GPU mining requested but mine_batch_gpu is unavailable\",\n ZeldMinerErrorCode.WEBGPU_NOT_AVAILABLE\n );\n return;\n }\n if (wasm.init_gpu) {\n await wasm.init_gpu();\n }\n }\n } catch (err) {\n const message = formatError(err);\n const code =\n currentMode === \"gpu\"\n ? ZeldMinerErrorCode.WEBGPU_NOT_AVAILABLE\n : ZeldMinerErrorCode.WORKER_ERROR;\n postError(`Failed to initialize WASM: ${message}`, code);\n return;\n }\n\n const templateCache: TemplateCache = new Map();\n const useCborNonce =\n msg.template.useCborNonce ?? Boolean(msg.distribution && msg.distribution.length > 0);\n cacheTemplate(templateCache, { ...msg.template, useCborNonce });\n\n const stride = msg.nonceStep ?? BigInt(msg.batchSize);\n const normalizedNetwork = msg.network === \"signet\" ? \"testnet\" : msg.network;\n let nextNonce = msg.startNonce;\n let hashesProcessed = 0n;\n const startedAt = performance.now();\n\n while (!abort.signal.aborted) {\n const iterationStart = nextNonce;\n let remaining = msg.batchSize;\n let processedInIteration = 0n;\n\n while (remaining > 0 && !abort.signal.aborted) {\n const segmentStart = iterationStart + processedInIteration;\n let segment: { start: bigint; size: number; nonceLength: number };\n\n try {\n const segments = useCborNonce\n ? splitNonceSegmentsCbor(segmentStart, remaining)\n : splitNonceSegments(segmentStart, remaining);\n segment = segments[0];\n } catch (err) {\n postError(\n `Invalid nonce range: ${formatError(err)}`,\n ZeldMinerErrorCode.INVALID_INPUT\n );\n abort.abort();\n return;\n }\n\n let template: WorkerTemplate;\n try {\n template = await ensureTemplateForSegment(\n templateCache,\n wasm,\n {\n inputs: msg.inputs,\n outputs: msg.outputs,\n satsPerVbyte: msg.satsPerVbyte,\n distribution: msg.distribution,\n useCborNonce,\n },\n segment,\n normalizedNetwork\n );\n } catch (err) {\n postError(\n `Failed to build mining template: ${formatError(err)}`,\n ZeldMinerErrorCode.WORKER_ERROR\n );\n abort.abort();\n return;\n }\n\n let output: unknown;\n const batchStartedAt = performance.now();\n try {\n output = await runBatch(\n wasm,\n currentMode,\n template.prefix,\n template.suffix,\n segment.start,\n segment.size,\n msg.targetZeros,\n useCborNonce\n );\n } catch (err) {\n const message = formatError(err);\n postError(\n `Batch mining failed: ${message}`,\n ZeldMinerErrorCode.WORKER_ERROR\n );\n abort.abort();\n return;\n }\n\n const batchDurationMs = performance.now() - batchStartedAt;\n\n if (isValidationResult(output)) {\n if (!output.ok) {\n postError(\n output.error ?? \"Validation failed\",\n ZeldMinerErrorCode.INVALID_INPUT\n );\n abort.abort();\n return;\n }\n } else if (isMineResult(output)) {\n const attemptsBefore = hashesProcessed + processedInIteration;\n const attemptsInSegment = BigInt(output.nonce) - segment.start + 1n;\n const totalAttempts = attemptsBefore + attemptsInSegment;\n const elapsedMs = performance.now() - startedAt;\n const hashRate =\n elapsedMs > 0\n ? safeBigIntToNumber(totalAttempts) / (elapsedMs / 1000)\n : 0;\n const lastNonce = segment.start + attemptsInSegment - 1n;\n\n const result: MineResult = {\n psbt: \"\",\n txid: output.txid,\n nonce: BigInt(output.nonce),\n attempts: totalAttempts,\n duration: elapsedMs,\n hashRate,\n };\n\n post({\n type: \"found\",\n result,\n hashesProcessed: totalAttempts,\n hashRate,\n lastNonce,\n });\n abort.abort();\n return;\n }\n\n hashesProcessed += BigInt(segment.size);\n processedInIteration += BigInt(segment.size);\n remaining -= segment.size;\n\n const hashRate =\n batchDurationMs > 0\n ? segment.size / (batchDurationMs / 1000)\n : segment.size;\n const lastNonce = segment.start + BigInt(segment.size) - 1n;\n\n post({ type: \"progress\", hashesProcessed, hashRate, lastNonce });\n }\n\n if (abort.signal.aborted) {\n break;\n }\n\n const lastNonce = iterationStart + BigInt(msg.batchSize) - 1n;\n post({ type: \"batch_complete\", lastNonce });\n\n nextNonce = iterationStart + stride;\n }\n};\n\nconst startMining = (msg: MineMessage): void => {\n const abort = new AbortController();\n miningAbort?.abort();\n miningAbort = abort;\n\n const promise = mineLoop(msg, abort).finally(() => {\n if (miningAbort === abort) {\n miningAbort = null;\n }\n if (miningPromise === promise) {\n miningPromise = null;\n }\n });\n\n miningPromise = promise;\n};\n\nctx.addEventListener(\"message\", (event: MessageEvent<WorkerMessage>) => {\n const data = event.data;\n\n switch (data.type) {\n case \"init\":\n currentMode = data.mode;\n post({ type: \"ready\" });\n break;\n case \"mine\":\n startMining(data);\n break;\n case \"stop\":\n miningAbort?.abort();\n break;\n default:\n postError(\n `Unknown message type: ${(data as { type?: string }).type}`,\n ZeldMinerErrorCode.WORKER_ERROR\n );\n }\n});\n\n"],"names":["ZeldMinerErrorCode","MAX_U64","nonceLength","nonce","len","value","cborNonceLength","maxValueForLength","maxValueForCborLength","splitNonceSegments","startNonce","span","end","segments","current","maxForLen","segmentEnd","segmentSize","splitNonceSegmentsCbor","origin","wasmModule","wasmInitPromise","webGpuLimitShimInstalled","installWebGpuLimitShim","adapterProto","requestDevice","descriptor","limits","supported","key","ensureTrailingSlash","toAbsoluteBase","base","trimmed","resolveWasmBase","globalBase","envBase","__vite_import_meta_env__","viteBase","WASM_BASE_URL","WASM_JS_PATH","WASM_BINARY_PATH","formatError","err","loadModule","bindings","init","wasmUrl","typedBindings","loadWasm","mod","ctx","workerId","currentMode","miningAbort","post","message","postError","code","details","isValidationResult","val","isMineResult","safeBigIntToNumber","max","cloneTemplate","template","cacheTemplate","cache","ensureTemplateForSegment","wasm","params","segment","normalizedNetwork","cached","built","runBatch","mode","prefix","suffix","batchSize","targetZeros","useCborNonce","mineLoop","msg","abort","templateCache","stride","nextNonce","hashesProcessed","startedAt","iterationStart","remaining","processedInIteration","segmentStart","output","batchStartedAt","batchDurationMs","attemptsBefore","attemptsInSegment","totalAttempts","elapsedMs","hashRate","lastNonce","result","startMining","event","data"],"mappings":"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"}
1
+ {"version":3,"file":"worker.js","sources":["../src/worker.ts"],"sourcesContent":["// Bootstrap: define a sensible default for WASM base path in worker context.\n// Workers don't have `window`, but `self` provides location. This must run\n// before any import that calls resolveWasmBase().\nif (typeof (globalThis as { __ZELDMINER_WASM_BASE__?: unknown }).__ZELDMINER_WASM_BASE__ === \"undefined\") {\n try {\n const origin =\n typeof self !== \"undefined\" && (self as { location?: { origin?: string } }).location?.origin\n ? (self as { location?: { origin?: string } }).location!.origin\n : \"http://localhost\";\n (globalThis as { __ZELDMINER_WASM_BASE__?: string }).__ZELDMINER_WASM_BASE__ = new URL(\"/wasm/\", origin!).href;\n } catch {\n (globalThis as { __ZELDMINER_WASM_BASE__?: string }).__ZELDMINER_WASM_BASE__ = \"/wasm/\";\n }\n}\n\nimport type {\n MineResult,\n ValidationResult,\n WasmExports,\n WorkerMessage,\n WorkerMode,\n WorkerTemplate,\n WorkerResponse,\n} from \"./types\";\nimport { ZeldMinerErrorCode } from \"./types\";\nimport { splitNonceSegments, splitNonceSegmentsCbor } from \"./nonce\";\nimport { loadWasm } from \"./wasm\";\n\ntype MineMessage = Extract<WorkerMessage, { type: \"mine\" }>;\n\nconst ctx = self as unknown as DedicatedWorkerGlobalScope;\nconst workerId =\n (ctx as DedicatedWorkerGlobalScope & { name?: string }).name ?? undefined;\n\nconst formatError = (err: unknown): string =>\n err instanceof Error ? err.message : String(err);\n\nlet currentMode: WorkerMode = \"cpu\";\nlet miningAbort: AbortController | null = null;\nlet miningPromise: Promise<void> | null = null;\n\nconst post = (message: WorkerResponse): void => {\n ctx.postMessage({ ...message, workerId });\n};\n\nconst postError = (\n message: string,\n code: ZeldMinerErrorCode = ZeldMinerErrorCode.WORKER_ERROR,\n details?: Record<string, unknown>\n): void => {\n post({ type: \"error\", message, code, details });\n};\n\nconst isValidationResult = (val: unknown): val is ValidationResult =>\n typeof val === \"object\" && val !== null && \"ok\" in (val as object);\n\nconst isMineResult = (\n val: unknown\n): val is { nonce: bigint; txid: string } =>\n typeof val === \"object\" &&\n val !== null &&\n \"nonce\" in (val as object) &&\n \"txid\" in (val as object);\n\nconst safeBigIntToNumber = (value: bigint): number => {\n const max = BigInt(Number.MAX_SAFE_INTEGER);\n if (value > max) return Number.MAX_SAFE_INTEGER;\n if (value < -max) return -Number.MAX_SAFE_INTEGER;\n return Number(value);\n};\n\ntype TemplateCache = Map<number, WorkerTemplate>;\n\nconst cloneTemplate = (template: WorkerTemplate): WorkerTemplate => ({\n nonceLength: template.nonceLength,\n prefix: new Uint8Array(template.prefix),\n suffix: new Uint8Array(template.suffix),\n useCborNonce: template.useCborNonce,\n});\n\nconst cacheTemplate = (cache: TemplateCache, template: WorkerTemplate): void => {\n cache.set(template.nonceLength, cloneTemplate(template));\n};\n\nconst ensureTemplateForSegment = async (\n cache: TemplateCache,\n wasm: WasmExports,\n params: {\n inputs: MineMessage[\"inputs\"];\n outputs: MineMessage[\"outputs\"];\n satsPerVbyte: number;\n distribution?: bigint[];\n useCborNonce: boolean;\n },\n segment: { start: bigint; size: number; nonceLength: number },\n normalizedNetwork: MineMessage[\"network\"]\n): Promise<WorkerTemplate> => {\n const cached = cache.get(segment.nonceLength);\n if (cached) {\n return cached;\n }\n\n const template = wasm.build_mining_template(\n params.inputs,\n params.outputs,\n normalizedNetwork,\n BigInt(params.satsPerVbyte),\n segment.start,\n segment.size,\n params.distribution ?? null\n );\n\n const built: WorkerTemplate = {\n ...template,\n nonceLength: segment.nonceLength,\n useCborNonce: template.useCborNonce ?? params.useCborNonce,\n };\n\n cacheTemplate(cache, built);\n return built;\n};\n\nconst runBatch = async (\n wasm: WasmExports,\n mode: WorkerMode,\n prefix: Uint8Array,\n suffix: Uint8Array,\n startNonce: bigint,\n batchSize: number,\n targetZeros: number,\n useCborNonce: boolean\n): Promise<unknown> => {\n if (mode === \"gpu\") {\n if (!wasm.mine_batch_gpu) {\n throw new Error(\"GPU mining requested but mine_batch_gpu is unavailable\");\n }\n return wasm.mine_batch_gpu(\n prefix,\n suffix,\n startNonce,\n batchSize,\n targetZeros,\n useCborNonce\n );\n }\n\n return wasm.mine_batch_wasm(\n prefix,\n suffix,\n startNonce,\n batchSize,\n targetZeros,\n useCborNonce\n );\n};\n\nconst mineLoop = async (msg: MineMessage, abort: AbortController): Promise<void> => {\n let wasm: WasmExports;\n try {\n wasm = await loadWasm();\n if (currentMode === \"gpu\") {\n if (!wasm.mine_batch_gpu) {\n postError(\n \"GPU mining requested but mine_batch_gpu is unavailable\",\n ZeldMinerErrorCode.WEBGPU_NOT_AVAILABLE\n );\n return;\n }\n if (wasm.init_gpu) {\n await wasm.init_gpu();\n }\n }\n } catch (err) {\n const message = formatError(err);\n const code =\n currentMode === \"gpu\"\n ? ZeldMinerErrorCode.WEBGPU_NOT_AVAILABLE\n : ZeldMinerErrorCode.WORKER_ERROR;\n postError(`Failed to initialize WASM: ${message}`, code);\n return;\n }\n\n const templateCache: TemplateCache = new Map();\n const useCborNonce =\n msg.template.useCborNonce ?? Boolean(msg.distribution && msg.distribution.length > 0);\n cacheTemplate(templateCache, { ...msg.template, useCborNonce });\n\n const stride = msg.nonceStep ?? BigInt(msg.batchSize);\n const normalizedNetwork = msg.network === \"signet\" ? \"testnet\" : msg.network;\n let nextNonce = msg.startNonce;\n let hashesProcessed = 0n;\n const startedAt = performance.now();\n\n while (!abort.signal.aborted) {\n const iterationStart = nextNonce;\n let remaining = msg.batchSize;\n let processedInIteration = 0n;\n\n while (remaining > 0 && !abort.signal.aborted) {\n const segmentStart = iterationStart + processedInIteration;\n let segment: { start: bigint; size: number; nonceLength: number };\n\n try {\n const segments = useCborNonce\n ? splitNonceSegmentsCbor(segmentStart, remaining)\n : splitNonceSegments(segmentStart, remaining);\n segment = segments[0];\n } catch (err) {\n postError(\n `Invalid nonce range: ${formatError(err)}`,\n ZeldMinerErrorCode.INVALID_INPUT\n );\n abort.abort();\n return;\n }\n\n let template: WorkerTemplate;\n try {\n template = await ensureTemplateForSegment(\n templateCache,\n wasm,\n {\n inputs: msg.inputs,\n outputs: msg.outputs,\n satsPerVbyte: msg.satsPerVbyte,\n distribution: msg.distribution,\n useCborNonce,\n },\n segment,\n normalizedNetwork\n );\n } catch (err) {\n postError(\n `Failed to build mining template: ${formatError(err)}`,\n ZeldMinerErrorCode.WORKER_ERROR\n );\n abort.abort();\n return;\n }\n\n let output: unknown;\n const batchStartedAt = performance.now();\n try {\n output = await runBatch(\n wasm,\n currentMode,\n template.prefix,\n template.suffix,\n segment.start,\n segment.size,\n msg.targetZeros,\n useCborNonce\n );\n } catch (err) {\n const message = formatError(err);\n postError(\n `Batch mining failed: ${message}`,\n ZeldMinerErrorCode.WORKER_ERROR\n );\n abort.abort();\n return;\n }\n\n const batchDurationMs = performance.now() - batchStartedAt;\n\n if (isValidationResult(output)) {\n if (!output.ok) {\n postError(\n output.error ?? \"Validation failed\",\n ZeldMinerErrorCode.INVALID_INPUT\n );\n abort.abort();\n return;\n }\n } else if (isMineResult(output)) {\n const attemptsBefore = hashesProcessed + processedInIteration;\n const attemptsInSegment = BigInt(output.nonce) - segment.start + 1n;\n const totalAttempts = attemptsBefore + attemptsInSegment;\n const elapsedMs = performance.now() - startedAt;\n const hashRate =\n elapsedMs > 0\n ? safeBigIntToNumber(totalAttempts) / (elapsedMs / 1000)\n : 0;\n const lastNonce = segment.start + attemptsInSegment - 1n;\n\n const result: MineResult = {\n psbt: \"\",\n txid: output.txid,\n nonce: BigInt(output.nonce),\n attempts: totalAttempts,\n duration: elapsedMs,\n hashRate,\n };\n\n post({\n type: \"found\",\n result,\n hashesProcessed: totalAttempts,\n hashRate,\n lastNonce,\n });\n abort.abort();\n return;\n }\n\n hashesProcessed += BigInt(segment.size);\n processedInIteration += BigInt(segment.size);\n remaining -= segment.size;\n\n const hashRate =\n batchDurationMs > 0\n ? segment.size / (batchDurationMs / 1000)\n : segment.size;\n const lastNonce = segment.start + BigInt(segment.size) - 1n;\n\n post({ type: \"progress\", hashesProcessed, hashRate, lastNonce });\n }\n\n if (abort.signal.aborted) {\n break;\n }\n\n const lastNonce = iterationStart + BigInt(msg.batchSize) - 1n;\n post({ type: \"batch_complete\", lastNonce });\n\n nextNonce = iterationStart + stride;\n }\n};\n\nconst startMining = (msg: MineMessage): void => {\n const abort = new AbortController();\n miningAbort?.abort();\n miningAbort = abort;\n\n const promise = mineLoop(msg, abort).finally(() => {\n if (miningAbort === abort) {\n miningAbort = null;\n }\n if (miningPromise === promise) {\n miningPromise = null;\n }\n });\n\n miningPromise = promise;\n};\n\nctx.addEventListener(\"message\", (event: MessageEvent<WorkerMessage>) => {\n const data = event.data;\n\n switch (data.type) {\n case \"init\":\n currentMode = data.mode;\n post({ type: \"ready\" });\n break;\n case \"mine\":\n startMining(data);\n break;\n case \"stop\":\n miningAbort?.abort();\n break;\n default:\n postError(\n `Unknown message type: ${(data as { type?: string }).type}`,\n ZeldMinerErrorCode.WORKER_ERROR\n );\n }\n});\n\n"],"names":["origin","ctx","workerId","formatError","err","currentMode","miningAbort","post","message","postError","code","ZeldMinerErrorCode","details","isValidationResult","val","isMineResult","safeBigIntToNumber","value","max","cloneTemplate","template","cacheTemplate","cache","ensureTemplateForSegment","wasm","params","segment","normalizedNetwork","cached","built","runBatch","mode","prefix","suffix","startNonce","batchSize","targetZeros","useCborNonce","mineLoop","msg","abort","loadWasm","templateCache","stride","nextNonce","hashesProcessed","startedAt","iterationStart","remaining","processedInIteration","segmentStart","splitNonceSegmentsCbor","splitNonceSegments","output","batchStartedAt","batchDurationMs","attemptsBefore","attemptsInSegment","totalAttempts","elapsedMs","hashRate","lastNonce","result","startMining","event","data"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zeldhash-miner",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "author": "Ouziel Slama <ouziel@gmail.com>",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/wasm/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "Ouziel Slama <ouziel@gmail.com>"
6
6
  ],
7
7
  "description": "WASM bindings for the Zeldhash miner with optional WebGPU acceleration",
8
- "version": "0.2.2",
8
+ "version": "0.2.3",
9
9
  "license": "MIT",
10
10
  "repository": {
11
11
  "type": "git",
Binary file