UNPKG

micro-zk-proofs

Version:

Create & verify zero-knowledge SNARK proofs in parallel, using noble cryptography

62 lines 2.47 kB
/** * MSM - Multi Scalar Multiplication. Done in parallel using micro-wrkr. * MSM is a fast algorithm to add & multiply many elliptic curve points at once. * @module */ import {} from '@noble/curves/abstract/modular.js'; import { bn254 } from '@noble/curves/bn254.js'; import { wrkr } from 'micro-wrkr'; import {} from "./msm-worker.js"; function reducePoint(p) { return (lst) => lst.map((i) => new p(i.X, i.Y, i.Z)).reduce((acc, i) => acc.add(i), p.ZERO); } /** * Initializes batched MSM workers and reduction helpers. * @returns Worker methods together with a `terminate()` hook. * @example * Create the bn254 worker pool and terminate it when the batch work is done. * ```ts * const ctx = initMSM(); * ctx.terminate(); * ``` */ export function initMSM() { const { methods, terminate } = wrkr.initBatch(() => new Worker(new URL('./msm-worker.js', import.meta.url), { type: 'module' }), { bn254_msmG1: reducePoint(bn254.G1.Point), bn254_msmG2: reducePoint(bn254.G2.Point), }); return { methods, terminate }; } /** * Adapts a worker MSM function into the point-array/scalar-array shape used by Groth16. * @param field - Scalar field used to drop zero scalars. * @param point - Projective point constructor for normalization. * @param fn - Worker-backed MSM implementation. * @returns Helper that accepts separate point and scalar arrays. * @example * Wrap a worker MSM function so Groth16 can call it with separate point and scalar arrays. * ```ts * const { bn254 } = await import('@noble/curves/bn254.js'); * const workerMsm = async () => bn254.G1.Point.ZERO; * const msm = modifyArgs(bn254.fields.Fr, bn254.G1.Point, workerMsm); * await msm([bn254.G1.Point.BASE], [1n]); * ``` */ export function modifyArgs(field, point, fn) { return async (points, scalars) => { if (points.length !== scalars.length) throw new Error('points.length !== scalars.length'); const input = []; for (let i = 0; i < points.length; i++) { const scalar = scalars[i]; if (field.is0(scalar)) continue; input.push({ point: points[i], scalar }); } // NOTE: buildGroth accepts curve and can be build with different version of @noble/curves, // so we convert it here. const res = (await fn(input)); return res instanceof point ? res : new point(res.px, res.py, res.pz); }; } //# sourceMappingURL=msm.js.map