function gpuMsmBaseKey(base) {
  return JSON.stringify([base.ledgerRevision, base.k, base.basis, base.length]);
}
const GPU_MSM_BASE_K_CAPACITY = 4;
class GpuMsmBaseLru {
  constructor(kCapacity = GPU_MSM_BASE_K_CAPACITY) {
    this.kCapacity = kCapacity;
    if (!Number.isInteger(kCapacity) || kCapacity < 1) {
      throw new RangeError("GPU base cache k capacity must be a positive integer");
    }
  }
  kCapacity;
  entries = /* @__PURE__ */ new Map();
  kLru = [];
  get size() {
    return this.entries.size;
  }
  has(base) {
    const found = this.entries.has(gpuMsmBaseKey(base));
    if (found) this.touchK(base.k);
    return found;
  }
  get(base) {
    const entry = this.entries.get(gpuMsmBaseKey(base));
    if (entry) this.touchK(base.k);
    return entry?.value;
  }
  delete(base) {
    const deleted = this.entries.delete(gpuMsmBaseKey(base));
    if (deleted && ![...this.entries.values()].some((entry) => entry.base.k === base.k)) {
      const index = this.kLru.indexOf(base.k);
      if (index >= 0) this.kLru.splice(index, 1);
    }
    return deleted;
  }
  set(base, value) {
    const key = gpuMsmBaseKey(base);
    this.entries.set(key, { base: { ...base }, value });
    this.touchK(base.k);
    const evicted = [];
    while (this.kLru.length > this.kCapacity) {
      const evictedK = this.kLru.shift();
      for (const [candidateKey, entry] of this.entries) {
        if (entry.base.k !== evictedK) continue;
        this.entries.delete(candidateKey);
        evicted.push({ key: candidateKey, base: entry.base, value: entry.value });
      }
    }
    return evicted;
  }
  clear() {
    const evicted = [...this.entries].map(([key, entry]) => ({ key, ...entry }));
    this.entries.clear();
    this.kLru.length = 0;
    return evicted;
  }
  touchK(k) {
    const oldIndex = this.kLru.indexOf(k);
    if (oldIndex >= 0) this.kLru.splice(oldIndex, 1);
    this.kLru.push(k);
  }
}

const GPU_MSM_SCALAR_BYTES = 32;
const GPU_MSM_G1_BYTES = 48;
const GPU_MSM_AFFINE_G1_BYTES = 96;
const GPU_MSM_PREPARED_G1_BYTES = 768;
const GPU_MSM_PREPARED_BASE_FORMAT = "bls12-381-g1-glv-13bit-v1";
const COMPLETION_HEADER_WORDS = 18;
const COMPLETION_HEADER_BYTES = COMPLETION_HEADER_WORDS * Int32Array.BYTES_PER_ELEMENT;
const failureCodes = [
  "user-disabled",
  "unsupported-browser",
  "webgpu-unavailable",
  "cross-origin-isolation-unavailable",
  "shared-memory-unavailable",
  "atomics-wait-unavailable",
  "adapter-unavailable",
  "fallback-adapter",
  "initialization-failed",
  "correctness-test-failed",
  "no-profitable-msm-sizes",
  "device-lost",
  "timeout",
  "shader-error",
  "transport-error",
  "point-decoding-error",
  "proof-verification-failed",
  "unknown"
];
const encoder = new TextEncoder();
new TextDecoder();
function gpuMsmCompletionStatus(completion) {
  return new Int32Array(completion, 0, COMPLETION_HEADER_WORDS);
}
function payloadView(completion) {
  return new Uint8Array(completion, COMPLETION_HEADER_BYTES);
}
function micros(milliseconds) {
  if (milliseconds === void 0 || !Number.isFinite(milliseconds)) return 0;
  return Math.max(0, Math.min(2147483647, Math.round(milliseconds * 1e3)));
}
function writeMetrics(words, metrics) {
  Atomics.store(words, 4 /* InitMicros */, micros(metrics?.initMs));
  Atomics.store(words, 5 /* BaseUploadMicros */, micros(metrics?.baseUploadMs));
  Atomics.store(words, 6 /* DispatchMicros */, micros(metrics?.dispatchMs));
  Atomics.store(words, 7 /* ReadbackMicros */, micros(metrics?.readbackMs));
  Atomics.store(words, 8 /* AffineConversionMicros */, micros(metrics?.affineConversionMs));
  Atomics.store(words, 9 /* GlvGenerationMicros */, micros(metrics?.glvGenerationMs));
  Atomics.store(words, 10 /* CacheReadMicros */, micros(metrics?.cacheReadMs));
  Atomics.store(words, 11 /* CacheWriteMicros */, micros(metrics?.cacheWriteMs));
  Atomics.store(words, 12 /* BufferUploadMicros */, micros(metrics?.bufferUploadMs));
  Atomics.store(
    words,
    13 /* MontgomeryConversionMicros */,
    micros(metrics?.montgomeryConversionMs)
  );
  Atomics.store(words, 14 /* FftDispatchMicros */, micros(metrics?.fftDispatchMs));
  Atomics.store(words, 15 /* FftReadbackMicros */, micros(metrics?.fftReadbackMs));
  Atomics.store(words, 16 /* FenceMicros */, micros(metrics?.fenceMs));
  Atomics.store(words, 17 /* ScalarDecodeMicros */, micros(metrics?.scalarDecodeMs));
}
function writePayload(completion, payload) {
  const target = payloadView(completion);
  if (payload.byteLength > target.byteLength) {
    throw new RangeError(
      `GPU MSM completion payload is ${payload.byteLength} bytes; capacity is ${target.byteLength}`
    );
  }
  target.fill(0);
  target.set(payload);
}
function publish(completion, status) {
  const words = gpuMsmCompletionStatus(completion);
  Atomics.store(words, 0 /* Status */, status);
  Atomics.notify(words, 0 /* Status */);
}
function completeGpuMsmBytes(completion, payload, metrics) {
  const words = gpuMsmCompletionStatus(completion);
  writePayload(completion, payload);
  Atomics.store(words, 1 /* Format */, 1 /* Bytes */);
  Atomics.store(words, 2 /* PayloadLength */, payload.byteLength);
  writeMetrics(words, metrics);
  publish(completion, 1 /* Success */);
}
function completeGpuMsmJson(completion, payload, metrics) {
  const bytes = encoder.encode(JSON.stringify(payload));
  const words = gpuMsmCompletionStatus(completion);
  writePayload(completion, bytes);
  Atomics.store(words, 1 /* Format */, 2 /* Json */);
  Atomics.store(words, 2 /* PayloadLength */, bytes.byteLength);
  writeMetrics(words, metrics);
  publish(completion, 1 /* Success */);
}
function completeGpuMsmEmpty(completion, metrics) {
  const words = gpuMsmCompletionStatus(completion);
  Atomics.store(words, 1 /* Format */, 0 /* None */);
  Atomics.store(words, 2 /* PayloadLength */, 0);
  writeMetrics(words, metrics);
  publish(completion, 1 /* Success */);
}
function failGpuMsmCompletion(completion, code, message, metrics) {
  const words = gpuMsmCompletionStatus(completion);
  const bytes = message ? encoder.encode(message) : new Uint8Array();
  const target = payloadView(completion);
  const bounded = bytes.subarray(0, target.byteLength);
  target.fill(0);
  target.set(bounded);
  Atomics.store(words, 1 /* Format */, 3 /* Text */);
  Atomics.store(words, 2 /* PayloadLength */, bounded.byteLength);
  Atomics.store(words, 3 /* FailureCode */, failureCodes.indexOf(code) + 1);
  writeMetrics(words, metrics);
  publish(completion, 2 /* Failure */);
}

const CACHE_NAME = `oneam-webgpu-prepared-bases-${GPU_MSM_PREPARED_BASE_FORMAT}`;
const CACHE_PATH = "/__oneam_webgpu_prepared_base__/";
const MAX_PERSISTED_PREPARED_BASE_BYTES = 32 * 1024 * 1024;
function expectedBytes(base) {
  return base.length * GPU_MSM_PREPARED_G1_BYTES;
}
async function sha256(bytes) {
  const subtle = globalThis.crypto?.subtle;
  if (!subtle || !bytes) return void 0;
  const digest = new Uint8Array(await subtle.digest("SHA-256", bytes.slice().buffer));
  return [...digest].map((byte) => byte.toString(16).padStart(2, "0")).join("");
}
function cacheUrl(base, fingerprint) {
  const origin = "https://oneam.invalid";
  return new URL(
    `${CACHE_PATH}${fingerprint}/${encodeURIComponent(gpuMsmBaseKey(base))}`,
    origin
  ).href;
}
function createGpuPreparedBaseStore(storage = globalThis.caches) {
  const open = () => storage?.open(CACHE_NAME);
  return {
    async get(base, trustedAffine) {
      if (expectedBytes(base) > MAX_PERSISTED_PREPARED_BASE_BYTES) return void 0;
      const fingerprint = await sha256(trustedAffine);
      if (!fingerprint) return void 0;
      const cache = await open();
      if (!cache) return void 0;
      const url = cacheUrl(base, fingerprint);
      const response = await cache.match(url);
      if (!response) return void 0;
      if (response.headers.get("x-oneam-gpu-base-format") !== GPU_MSM_PREPARED_BASE_FORMAT || Number(response.headers.get("x-oneam-gpu-base-points")) !== base.length || response.headers.get("x-oneam-gpu-base-sha256") !== fingerprint) {
        await cache.delete(url);
        return void 0;
      }
      const prepared = new Uint8Array(await response.arrayBuffer());
      const preparedFingerprint = await sha256(prepared);
      if (prepared.byteLength !== expectedBytes(base) || !preparedFingerprint || response.headers.get("x-oneam-gpu-prepared-sha256") !== preparedFingerprint) {
        await cache.delete(url);
        return void 0;
      }
      return prepared;
    },
    async put(base, trustedAffine, prepared) {
      if (prepared.byteLength !== expectedBytes(base)) {
        throw new RangeError(
          `prepared GPU base has ${prepared.byteLength} bytes; expected ${expectedBytes(base)}`
        );
      }
      if (prepared.byteLength > MAX_PERSISTED_PREPARED_BASE_BYTES) return;
      const [fingerprint, preparedFingerprint] = await Promise.all([
        sha256(trustedAffine),
        sha256(prepared)
      ]);
      if (!fingerprint || !preparedFingerprint) return;
      const cache = await open();
      if (!cache) return;
      const body = prepared.slice().buffer;
      await cache.put(cacheUrl(base, fingerprint), new Response(body, {
        headers: {
          "content-type": "application/octet-stream",
          "x-oneam-gpu-base-format": GPU_MSM_PREPARED_BASE_FORMAT,
          "x-oneam-gpu-base-points": String(base.length),
          "x-oneam-gpu-base-sha256": fingerprint,
          "x-oneam-gpu-prepared-sha256": preparedFingerprint
        }
      }));
    },
    async delete(base, trustedAffine) {
      const fingerprint = await sha256(trustedAffine);
      if (!fingerprint) return;
      const cache = await open();
      if (cache) await cache.delete(cacheUrl(base, fingerprint));
    }
  };
}

function isGeneratedSidecarModule(value) {
  if (typeof value !== "object" || value === null) return false;
  const candidate = value;
  return typeof candidate.default === "function" && typeof candidate.GpuMsmContext?.create === "function";
}
const loadGeneratedGpuMsmSidecar = async ({ moduleUrl }) => {
  const imported = await import(
    /* @vite-ignore */
    moduleUrl
  );
  if (!isGeneratedSidecarModule(imported)) {
    throw new GpuMsmSidecarError(
      "initialization-failed",
      "WebGPU sidecar module does not expose default init and GpuMsmContext.create"
    );
  }
  const wasmUrl = new URL("./oneam_webgpu_msm_sidecar_bg.wasm", moduleUrl);
  await imported.default({ module_or_path: wasmUrl });
  const profile = selectGpuMsmPipelineProfile(globalThis.navigator);
  if (profile === "windows-g1-minimal") {
    if (typeof imported.GpuMsmContext.createWindowsG1Minimal !== "function") {
      throw new GpuMsmSidecarError(
        "initialization-failed",
        "WebGPU sidecar does not expose the Windows G1 minimal profile"
      );
    }
    return { createContext: () => imported.GpuMsmContext.createWindowsG1Minimal() };
  }
  return { createContext: () => imported.GpuMsmContext.create() };
};
function selectGpuMsmPipelineProfile(navigatorLike) {
  const identity = `${navigatorLike?.platform ?? ""} ${navigatorLike?.userAgent ?? ""}`;
  return /Windows|Win32|Win64/i.test(identity) ? "windows-g1-minimal" : "full";
}
class GpuMsmSidecarError extends Error {
  constructor(code, message) {
    super(message);
    this.code = code;
    this.name = "GpuMsmSidecarError";
  }
  code;
}
const knownFailureCodes = /* @__PURE__ */ new Set([
  "user-disabled",
  "unsupported-browser",
  "webgpu-unavailable",
  "cross-origin-isolation-unavailable",
  "shared-memory-unavailable",
  "atomics-wait-unavailable",
  "adapter-unavailable",
  "fallback-adapter",
  "initialization-failed",
  "correctness-test-failed",
  "no-profitable-msm-sizes",
  "device-lost",
  "timeout",
  "shader-error",
  "transport-error",
  "point-decoding-error",
  "proof-verification-failed",
  "unknown"
]);
function gpuMsmFailureFrom(error, defaultCode) {
  if (error instanceof GpuMsmSidecarError) {
    return { code: error.code, message: error.message };
  }
  if (typeof error === "object" && error !== null) {
    const candidate = error;
    const text = typeof candidate.message === "string" ? candidate.message : String(candidate.name ?? error);
    if (typeof candidate.code === "string" && knownFailureCodes.has(candidate.code)) {
      return { code: candidate.code, message: text };
    }
    return classifyGpuMsmFailureText(text, defaultCode);
  }
  return classifyGpuMsmFailureText(String(error), defaultCode);
}
function classifyGpuMsmFailureText(message, defaultCode) {
  const lower = message.toLowerCase();
  if (lower.includes("device") && lower.includes("lost")) return { code: "device-lost", message };
  if (lower.includes("shader") || lower.includes("pipeline")) return { code: "shader-error", message };
  if (lower.includes("adapter") && /unavailable|not found|no suitable|no adapter/.test(lower)) {
    return { code: "adapter-unavailable", message };
  }
  return { code: defaultCode, message };
}
function isFallbackGpuAdapter(adapter) {
  if (adapter.isFallbackAdapter === true) return true;
  const identity = [
    adapter.vendor,
    adapter.architecture,
    adapter.device,
    adapter.description
  ].filter((part) => typeof part === "string").join(" ").toLowerCase();
  return ["swiftshader", "llvmpipe", "software", "lavapipe"].some((marker) => identity.includes(marker));
}

function now() {
  return performance.now();
}
function validBase(message) {
  const { base } = message;
  if (!base.ledgerRevision) return "GPU MSM base ledger revision is empty";
  if (!Number.isInteger(base.k) || base.k < 1) return `Invalid GPU MSM k ${base.k}`;
  if (base.basis !== "coefficient" && base.basis !== "lagrange") {
    return `Invalid GPU MSM basis ${String(base.basis)}`;
  }
  if (!Number.isSafeInteger(base.length) || base.length < 1) {
    return `Invalid GPU MSM base length ${base.length}`;
  }
  const batchItems = message.op === "msm-batch" ? message.batchItems : 1;
  if (!Number.isSafeInteger(batchItems) || batchItems < 1) {
    return `Invalid GPU MSM batch item count ${batchItems}`;
  }
  const expectedScalarBytes = batchItems * base.length * GPU_MSM_SCALAR_BYTES;
  if (!Number.isSafeInteger(expectedScalarBytes) || message.scalars.byteLength !== expectedScalarBytes) {
    return `GPU MSM scalar bytes ${message.scalars.byteLength} do not match ${base.length} points`;
  }
  if (message.bases && message.bases.byteLength !== base.length * GPU_MSM_AFFINE_G1_BYTES) {
    return `GPU MSM base bytes ${message.bases.byteLength} do not match ${base.length} points`;
  }
  return void 0;
}
async function runBatchFallback(context, key, scalarBytes, scalarVectorBytes) {
  const batches = Array.from(
    { length: scalarBytes.byteLength / scalarVectorBytes },
    (_, index) => scalarBytes.subarray(index * scalarVectorBytes, (index + 1) * scalarVectorBytes)
  );
  const results = await Promise.all(batches.map((batch) => context.msm(key, batch)));
  const encoded = new Uint8Array(results.length * GPU_MSM_G1_BYTES);
  results.forEach((result, index) => {
    if (!(result instanceof Uint8Array) || result.byteLength !== GPU_MSM_G1_BYTES) {
      throw new Error(
        `GPU MSM batch item ${index} returned ${result?.byteLength ?? "non-byte"} bytes; expected ${GPU_MSM_G1_BYTES}`
      );
    }
    encoded.set(result, index * GPU_MSM_G1_BYTES);
  });
  return encoded;
}
function releaseContext(context, cache) {
  if (!context) return;
  for (const entry of cache.clear()) {
    try {
      context.disposeBase?.(entry.key);
    } catch {
    }
  }
  try {
    context.dispose();
  } catch {
  }
}
async function restorePreparedBase(context, store, message, key, trustedAffine) {
  const startedAt = now();
  try {
    const prepared = await store.get(message.base, trustedAffine);
    if (prepared) context.uploadPreparedBase(key, message.base.length, prepared);
    return { restored: Boolean(prepared), cacheReadMs: now() - startedAt };
  } catch {
    await store.delete(message.base, trustedAffine).catch(() => void 0);
    return { restored: false, cacheReadMs: now() - startedAt };
  }
}
function uploadAndPersistBase(context, store, message, key, trustedAffine) {
  if (!trustedAffine) throw new Error(`GPU MSM base ${key} is not resident, persisted, or supplied`);
  const prepared = context.prepareAndUploadBase(key, trustedAffine);
  const expectedBytes = message.base.length * GPU_MSM_PREPARED_G1_BYTES;
  if (!(prepared instanceof Uint8Array) || prepared.byteLength !== expectedBytes) {
    throw new Error(
      `prepared GPU base has ${prepared?.byteLength ?? "non-byte"} bytes; expected ${expectedBytes}`
    );
  }
  const startedAt = now();
  return store.put(message.base, trustedAffine, prepared).then(
    () => now() - startedAt,
    () => now() - startedAt
  );
}
async function prepareGpuBase(context, cache, store, message) {
  const key = gpuMsmBaseKey(message.base);
  const sidecarHasBase = context.hasBase?.(key);
  if (cache.has(message.base) && sidecarHasBase === false) cache.delete(message.base);
  if (!cache.has(message.base) && sidecarHasBase === true) cache.set(message.base, true);
  if (cache.has(message.base)) {
    return {
      key,
      uploadMs: 0,
      glvGenerationMs: 0,
      cacheReadMs: 0,
      bufferUploadMs: 0,
      montgomeryConversionMs: 0
    };
  }
  const uploadStartedAt = now();
  const trustedAffine = message.bases ? new Uint8Array(message.bases) : void 0;
  const restored = await restorePreparedBase(context, store, message, key, trustedAffine);
  const cacheWriteTask = restored.restored ? void 0 : uploadAndPersistBase(context, store, message, key, trustedAffine);
  const timings = context.takeLastBaseTimings?.();
  for (const evicted of cache.set(message.base, true)) context.disposeBase?.(evicted.key);
  return {
    key,
    uploadMs: now() - uploadStartedAt,
    glvGenerationMs: timings?.glvGenerationMs ?? 0,
    cacheReadMs: restored.cacheReadMs,
    bufferUploadMs: timings?.bufferUploadMs ?? 0,
    montgomeryConversionMs: timings?.montgomeryConversionMs ?? 0,
    cacheWriteTask
  };
}
async function executeMsm(context, key, message) {
  const scalars = new Uint8Array(message.scalars);
  if (message.op === "msm") return context.msm(key, scalars);
  return context.msmBatch?.(key, scalars) ?? runBatchFallback(
    context,
    key,
    scalars,
    message.base.length * GPU_MSM_SCALAR_BYTES
  );
}
function expectedMsmResultBytes(message) {
  const items = message.op === "msm-batch" ? message.batchItems : 1;
  return items * GPU_MSM_G1_BYTES;
}

function assertHardwareAdapter(adapter) {
  if (!isFallbackGpuAdapter(adapter)) return;
  throw Object.assign(new Error("WebGPU adapter is a software/fallback adapter"), {
    code: "fallback-adapter"
  });
}
function assertStartupChecks(adapter, checks) {
  if (checks.scalarOne !== true || checks.random257 !== true) {
    throw Object.assign(new Error("WebGPU MSM or FFT startup correctness check failed"), {
      code: "correctness-test-failed"
    });
  }
  if (checks.fftRoundtrip === false) {
    throw Object.assign(new Error("WebGPU FFT forward/inverse roundtrip check failed"), {
      code: "correctness-test-failed"
    });
  }
  if (adapter.pipelineProfile !== "windows-g1-minimal" || checks.largeBucket257 === true) return;
  throw Object.assign(
    new Error("Windows G1 minimal profile large-bucket correctness check failed"),
    { code: "correctness-test-failed" }
  );
}
function createGpuMsmWorkerRuntime(scope, loadSidecar = loadGeneratedGpuMsmSidecar, preparedStore = createGpuPreparedBaseStore()) {
  const cache = new GpuMsmBaseLru(GPU_MSM_BASE_K_CAPACITY);
  const pending = /* @__PURE__ */ new Set();
  let context;
  let initialized = false;
  let adapter;
  let disposed = false;
  let fatal;
  let activeOperation;
  const describeDeviceLoss = (message) => {
    if (!activeOperation) return message || "WebGPU device lost";
    const elapsedMs = Math.max(0, now() - activeOperation.startedAt).toFixed(1);
    return `${message || "WebGPU device lost"} | active=${activeOperation.detail} elapsedMs=${elapsedMs}`;
  };
  const disable = (code, message) => {
    if (fatal) return;
    fatal = { code, message };
    for (const completion of pending) failGpuMsmCompletion(completion, code, message);
    pending.clear();
    releaseContext(context, cache);
    context = void 0;
    adapter = void 0;
  };
  const watchDeviceLoss = (gpuContext) => {
    const alreadyLost = gpuContext.deviceLost?.();
    if (alreadyLost) return alreadyLost;
    const lost = gpuContext.lost?.();
    if (lost) {
      void lost.then(
        (message) => {
          disable("device-lost", describeDeviceLoss(message));
        },
        (error) => {
          const failure = gpuMsmFailureFrom(error, "device-lost");
          disable("device-lost", describeDeviceLoss(failure.message));
        }
      );
    }
    return void 0;
  };
  const initialize = async (message) => {
    if (fatal) {
      failGpuMsmCompletion(message.completion, fatal.code, fatal.message);
      return;
    }
    if (disposed) {
      failGpuMsmCompletion(message.completion, "transport-error", "GPU MSM worker is disposed");
      return;
    }
    if (initialized && context && adapter) {
      completeGpuMsmJson(message.completion, { adapter }, { initMs: 0 });
      return;
    }
    const startedAt = now();
    pending.add(message.completion);
    try {
      const sidecar = await loadSidecar({ moduleUrl: message.sidecarModuleUrl });
      const gpuContext = await sidecar.createContext();
      context = gpuContext;
      const selectedAdapter = gpuContext.adapterMetadata?.() ?? {};
      assertHardwareAdapter(selectedAdapter);
      const checks = await gpuContext.runStartupVectors();
      assertStartupChecks(selectedAdapter, checks);
      const alreadyLost = watchDeviceLoss(gpuContext);
      if (alreadyLost) {
        throw Object.assign(new Error(alreadyLost), { code: "device-lost" });
      }
      initialized = true;
      adapter = selectedAdapter;
      completeGpuMsmJson(
        message.completion,
        { adapter: selectedAdapter },
        { initMs: now() - startedAt }
      );
    } catch (error) {
      const candidateCode = typeof error === "object" && error !== null ? error.code : void 0;
      const defaultCode = candidateCode === "fallback-adapter" || candidateCode === "correctness-test-failed" ? candidateCode : "initialization-failed";
      const failure = gpuMsmFailureFrom(error, defaultCode);
      pending.delete(message.completion);
      failGpuMsmCompletion(
        message.completion,
        failure.code,
        failure.message,
        { initMs: now() - startedAt }
      );
      disable(failure.code, failure.message);
    } finally {
      pending.delete(message.completion);
    }
  };
  const validateMsmRequest = (message) => {
    if (fatal) {
      failGpuMsmCompletion(message.completion, fatal.code, fatal.message);
      return void 0;
    }
    if (!initialized || !context) {
      failGpuMsmCompletion(message.completion, "initialization-failed", "GPU MSM worker is not initialized");
      return void 0;
    }
    const deviceLoss = context.deviceLost?.();
    if (typeof deviceLoss === "string") {
      failGpuMsmCompletion(message.completion, "device-lost", deviceLoss);
      disable("device-lost", deviceLoss);
      return void 0;
    }
    const validationError = validBase(message);
    if (validationError) {
      failGpuMsmCompletion(message.completion, "transport-error", validationError);
      disable("transport-error", validationError);
      return void 0;
    }
    return context;
  };
  const completeMsmExecution = async (gpuContext, message, baseRun) => {
    const dispatchStartedAt = now();
    const result = await executeMsm(gpuContext, baseRun.key, message);
    const totalMsmMs = now() - dispatchStartedAt;
    if (fatal) return 0;
    const expectedResultBytes = expectedMsmResultBytes(message);
    if (!(result instanceof Uint8Array) || result.byteLength !== expectedResultBytes) {
      throw new Error(
        `GPU MSM returned ${result?.byteLength ?? "non-byte"} result; expected ${expectedResultBytes}`
      );
    }
    const detailed = gpuContext.takeLastTimings?.();
    const cacheWriteMs = await baseRun.cacheWriteTask ?? 0;
    completeGpuMsmBytes(message.completion, result, {
      glvGenerationMs: baseRun.glvGenerationMs,
      cacheReadMs: baseRun.cacheReadMs,
      cacheWriteMs,
      bufferUploadMs: baseRun.bufferUploadMs,
      montgomeryConversionMs: baseRun.montgomeryConversionMs,
      baseUploadMs: baseRun.uploadMs,
      dispatchMs: detailed?.dispatchMs ?? totalMsmMs,
      readbackMs: detailed?.readbackMs ?? 0,
      fenceMs: detailed?.fenceMs ?? 0,
      scalarDecodeMs: detailed?.scalarDecodeMs ?? 0
    });
    return cacheWriteMs;
  };
  const reportMsmFailure = async (message, error, baseRun, cacheWriteMs) => {
    if (fatal) return;
    const finalCacheWriteMs = await baseRun?.cacheWriteTask ?? cacheWriteMs;
    const failure = gpuMsmFailureFrom(error, "transport-error");
    pending.delete(message.completion);
    failGpuMsmCompletion(message.completion, failure.code, failure.message, {
      glvGenerationMs: baseRun?.glvGenerationMs ?? 0,
      cacheReadMs: baseRun?.cacheReadMs ?? 0,
      cacheWriteMs: finalCacheWriteMs,
      bufferUploadMs: baseRun?.bufferUploadMs ?? 0,
      montgomeryConversionMs: baseRun?.montgomeryConversionMs ?? 0,
      baseUploadMs: baseRun?.uploadMs ?? 0
    });
    disable(failure.code, failure.message);
  };
  const runMsm = async (message) => {
    const gpuContext = validateMsmRequest(message);
    if (!gpuContext) return;
    pending.add(message.completion);
    const operation = {
      detail: [
        message.op,
        `k=${message.base.k}`,
        `basis=${message.base.basis}`,
        `points=${message.base.length}`,
        `batchItems=${message.op === "msm-batch" ? message.batchItems : 1}`,
        `ledger=${message.base.ledgerRevision}`
      ].join(" "),
      startedAt: now()
    };
    activeOperation = operation;
    let baseRun;
    let cacheWriteMs = 0;
    try {
      baseRun = await prepareGpuBase(gpuContext, cache, preparedStore, message);
      cacheWriteMs = await completeMsmExecution(gpuContext, message, baseRun);
    } catch (error) {
      await reportMsmFailure(message, error, baseRun, cacheWriteMs);
    } finally {
      pending.delete(message.completion);
      if (activeOperation === operation) activeOperation = void 0;
    }
  };
  const dispose = () => {
    if (disposed) return;
    disposed = true;
    releaseContext(context, cache);
    context = void 0;
    adapter = void 0;
  };
  const runFftBatch = async (message) => {
    if (fatal) {
      failGpuMsmCompletion(message.completion, fatal.code, fatal.message);
      return;
    }
    if (!initialized || !context || !context.fftBatch) {
      failGpuMsmCompletion(
        message.completion,
        "initialization-failed",
        "GPU FFT worker is not initialized"
      );
      return;
    }
    const expectedBytes = message.batchItems * 2 ** message.logN * GPU_MSM_SCALAR_BYTES;
    if (!Number.isSafeInteger(expectedBytes) || message.logN < 10 || message.logN > 20 || message.batchItems < 1 || message.batchItems > 128 || message.values.byteLength !== expectedBytes) {
      const detail = `invalid GPU FFT request ${message.batchItems} x 2^${message.logN}`;
      failGpuMsmCompletion(message.completion, "transport-error", detail);
      disable("transport-error", detail);
      return;
    }
    pending.add(message.completion);
    const operation = {
      detail: `fft-batch logN=${message.logN} inverse=${message.inverse} batchItems=${message.batchItems}`,
      startedAt: now()
    };
    activeOperation = operation;
    try {
      const result = await context.fftBatch(
        message.logN,
        message.inverse,
        message.batchItems,
        new Uint8Array(message.values)
      );
      if (!(result instanceof Uint8Array) || result.byteLength !== expectedBytes) {
        throw new Error(
          `GPU FFT returned ${result?.byteLength ?? "non-byte"} bytes; expected ${expectedBytes}`
        );
      }
      const timings = context.takeLastFftTimings?.();
      completeGpuMsmBytes(message.completion, result, {
        fftDispatchMs: timings?.dispatchMs ?? 0,
        fftReadbackMs: timings?.readbackMs ?? 0
      });
    } catch (error) {
      const failure = gpuMsmFailureFrom(error, "transport-error");
      pending.delete(message.completion);
      failGpuMsmCompletion(message.completion, failure.code, failure.message);
      disable(failure.code, failure.message);
    } finally {
      pending.delete(message.completion);
      if (activeOperation === operation) activeOperation = void 0;
    }
  };
  const runEvaluateH = async (message) => {
    if (fatal) {
      failGpuMsmCompletion(message.completion, fatal.code, fatal.message);
      return;
    }
    if (!initialized || !context || !context.evaluateH) {
      failGpuMsmCompletion(
        message.completion,
        "initialization-failed",
        "GPU evaluate_h worker is not initialized"
      );
      return;
    }
    const header = new Uint32Array(message.program, 0, 8);
    const rows = header[2];
    const expectedBytes = rows * GPU_MSM_SCALAR_BYTES;
    if (!Number.isSafeInteger(expectedBytes) || rows < 1) {
      const detail = `invalid GPU evaluate_h row count ${rows}`;
      failGpuMsmCompletion(message.completion, "transport-error", detail);
      disable("transport-error", detail);
      return;
    }
    pending.add(message.completion);
    const operation = {
      detail: `evaluate-h rows=${rows} programBytes=${message.program.byteLength} columnsBytes=${message.columns.byteLength}`,
      startedAt: now()
    };
    activeOperation = operation;
    try {
      const result = await context.evaluateH(
        new Uint8Array(message.program),
        new Uint8Array(message.columns)
      );
      if (!(result instanceof Uint8Array) || result.byteLength !== expectedBytes) {
        throw new Error(
          `GPU evaluate_h returned ${result?.byteLength ?? "non-byte"} bytes; expected ${expectedBytes}`
        );
      }
      completeGpuMsmBytes(message.completion, result, {});
    } catch (error) {
      const failure = gpuMsmFailureFrom(error, "transport-error");
      pending.delete(message.completion);
      failGpuMsmCompletion(message.completion, failure.code, failure.message);
      disable(failure.code, failure.message);
    } finally {
      pending.delete(message.completion);
      if (activeOperation === operation) activeOperation = void 0;
    }
  };
  const handle = async (message) => {
    switch (message.op) {
      case "init":
        await initialize(message);
        break;
      case "msm":
        await runMsm(message);
        break;
      case "msm-batch":
        await runMsm(message);
        break;
      case "fft-batch":
        await runFftBatch(message);
        break;
      case "evaluate-h":
        await runEvaluateH(message);
        break;
      case "dispose":
        dispose();
        completeGpuMsmEmpty(message.completion);
        break;
    }
  };
  let queue = Promise.resolve();
  scope.addEventListener("message", (event) => {
    queue = queue.then(async () => {
      try {
        await handle(event.data);
      } catch (error) {
        const failure = gpuMsmFailureFrom(error, "transport-error");
        failGpuMsmCompletion(event.data.completion, failure.code, failure.message);
        disable(failure.code, failure.message);
      }
    });
  });
  return { handle, dispose };
}

const workerGlobal = self;
const scope = "onconnect" in workerGlobal ? {
  addEventListener: (_type, listener) => {
    workerGlobal.addEventListener("connect", (event) => {
      for (const port of event.ports) {
        port.addEventListener("message", listener);
        port.start();
      }
    });
  }
} : self;
createGpuMsmWorkerRuntime(scope);
