@cloudflare/zkp-ecdsa
Version:
zkp-ecdsa: A Typescript Implementation of ZKAttest
132 lines • 3.73 kB
JavaScript
class Pair {
constructor(pt, scalar) {
this.pt = pt;
this.scalar = scalar;
}
cmp(b) {
return this.scalar.cmp(b.scalar);
}
}
export class MultiMult {
constructor(g) {
this.group = g;
this.pairs = [];
this.known = [];
}
addKnown(pt) {
this.group.isCompatPoint(pt);
if (!this.known.some((x) => pt.eq(x.pt))) {
const newlen = this.pairs.push(new Pair(pt, this.group.newScalar(BigInt(0))));
this.known.push({ pt: pt, idx: newlen - 1 });
}
}
insert(pt, s) {
this.group.isCompatPoint(pt);
this.group.isCompatScalar(s);
const match = this.known.find((x) => pt.eq(x.pt));
if (match != undefined) {
this.pairs[match.idx].scalar = this.pairs[match.idx].scalar.add(s);
}
else {
this.pairs.push(new Pair(pt, s));
}
}
evaluate() {
if (this.pairs.length === 0) {
return this.group.identity();
}
if (this.pairs.length === 1) {
const a = this.pairs[0];
return a.pt.mul(a.scalar);
}
heapify(this.pairs);
while (true) {
if (this.pairs.length === 1) {
const a = this.pairs[0];
return a.pt.mul(a.scalar);
}
const a = extractMax(this.pairs), b = this.pairs[0];
if (b.scalar.isZero()) {
return a.pt.mul(a.scalar);
}
const c = new Pair(a.pt, a.scalar.sub(b.scalar)), d = new Pair(b.pt.add(a.pt), b.scalar);
this.pairs[0] = d;
if (!c.scalar.isZero()) {
this.pairs.push(c);
bubbleup(this.pairs, this.pairs.length);
}
}
}
}
function extractMax(arr) {
const t = arr[0];
arr[0] = arr[arr.length - 1];
arr[arr.length - 1] = t;
const max = arr.pop();
if (max == undefined) {
throw new Error('heap underflow');
}
pushdown(arr, 1);
return max;
}
function heapify(arr) {
for (let i = 0; i < arr.length; i++) {
bubbleup(arr, i + 1);
}
}
function bubbleup(arr, index) {
if (index == 0 || index == 1) {
return;
}
const parent = Math.floor(index / 2);
if (arr[parent - 1].cmp(arr[index - 1]) < 0) {
const t = arr[index - 1];
arr[index - 1] = arr[parent - 1];
arr[parent - 1] = t;
bubbleup(arr, parent);
}
}
function pushdown(arr, parent) {
const son = 2 * parent, daughter = 2 * parent + 1;
if (son > arr.length) {
return;
}
let child = son;
if (daughter <= arr.length) {
if (arr[daughter - 1].cmp(arr[son - 1]) > 0) {
child = daughter;
}
}
if (arr[parent - 1].cmp(arr[child - 1]) < 0) {
const t = arr[child - 1];
arr[child - 1] = arr[parent - 1];
arr[parent - 1] = t;
pushdown(arr, child);
}
}
export class Relation {
constructor(g) {
this.group = g;
this.pairs = [];
}
insertM(pts, scalars) {
if (pts.length !== scalars.length) {
throw new Error('arrays are not the same length');
}
for (let i = 0; i < pts.length; i++) {
this.insert(pts[i], scalars[i]);
}
}
insert(pt, s) {
this.group.isCompatPoint(pt);
this.group.isCompatScalar(s);
this.pairs.push(new Pair(pt, s));
}
drain(m) {
const randomizer = this.group.randomScalar();
for (let i = 0; i < this.pairs.length; i++) {
m.insert(this.pairs[i].pt, this.pairs[i].scalar.mul(randomizer));
}
}
}
//# sourceMappingURL=multimult.js.map