arnaucube
arnaucube/websnarkPublic Self-hosted repository
websnark/tools/buildpkey.js
tools/buildpkey.jsRaw
  1const bigInt = require("big-integer");
  2const assert = require("assert");
  3
  4function writeUint32(h, val) {
  5    h.dataView.setUint32(h.offset, val, true);
  6    h.offset += 4;
  7}
  8
  9function writeUint32ToPointer(h, p, val) {
 10    h.dataView.setUint32(p, val, true);
 11}
 12
 13
 14function alloc(h, n) {
 15    const o = h.offset;
 16    h.offset += n;
 17    return o;
 18}
 19
 20function writeBigInt(h, bi) {
 21    for (let i=0; i<8; i++) {
 22        const v = bi.shiftRight(i*32).and(0xFFFFFFFF).toJSNumber();
 23        writeUint32(h, v);
 24    }
 25}
 26
 27function toMontgomeryQ(p) {
 28    const q = bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208583");
 29    return p.times(bigInt.one.shiftLeft(256)).mod(q);
 30}
 31
 32function toMontgomeryR(p) {
 33    const r = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
 34    return p.times(bigInt.one.shiftLeft(256)).mod(r);
 35}
 36
 37function writePoint(h, p) {
 38    writeBigInt(h, toMontgomeryQ(p[0]));
 39    writeBigInt(h, toMontgomeryQ(p[1]));
 40}
 41
 42function writePoint2(h, p) {
 43    writeBigInt(h, toMontgomeryQ(p[0][0]));
 44    writeBigInt(h, toMontgomeryQ(p[0][1]));
 45    writeBigInt(h, toMontgomeryQ(p[1][0]));
 46    writeBigInt(h, toMontgomeryQ(p[1][1]));
 47}
 48
 49function writeTransformedPolynomial(h, p) {
 50
 51    const keys = Object.keys(p);
 52
 53    writeUint32(h, keys.length);
 54
 55    for (let i=0; i<keys.length; i++) {
 56        writeUint32(h, keys[i]);
 57        writeBigInt(h, toMontgomeryR(p[keys[i]]));
 58    }
 59}
 60
 61function calculateBuffLen(provingKey) {
 62    function polSize(pol) {
 63        const l= Object.keys(pol).length;
 64        return 36*l + 4;
 65    }
 66
 67    let size = 40;
 68
 69    // alfa1, beta1, delta1
 70    size += 3 * (32*2);
 71
 72    // beta2, delta2
 73    size += 2 * (32*4);
 74
 75    for (let i=0; i<provingKey.nVars; i++) {
 76        size += polSize(provingKey.polsA[i]);
 77        size += polSize(provingKey.polsB[i]);
 78    }
 79
 80    size += provingKey.nVars* (32*2);
 81    size += provingKey.nVars* (32*2);
 82    size += provingKey.nVars* (32*4);
 83    size += (provingKey.nVars - provingKey.nPublic  - 1)* (32*2);
 84    size += provingKey.domainSize * (32*2);
 85
 86    return size;
 87}
 88
 89
 90function buildPKey(provingKey) {
 91    const buffLen = calculateBuffLen(provingKey);
 92
 93    const buff = new ArrayBuffer(buffLen);
 94
 95    const h = {
 96        dataView: new DataView(buff),
 97        offset: 0
 98    };
 99
100
101    writeUint32(h, provingKey.nVars);
102    writeUint32(h, provingKey.nPublic);
103    writeUint32(h, provingKey.domainSize);
104    const pPolsA = alloc(h, 4);
105    const pPolsB = alloc(h, 4);
106    const pPointsA = alloc(h, 4);
107    const pPointsB1 = alloc(h, 4);
108    const pPointsB2 = alloc(h, 4);
109    const pPointsC = alloc(h, 4);
110    const pPointsHExps = alloc(h, 4);
111
112    writePoint(h, provingKey.vk_alfa_1);
113    writePoint(h, provingKey.vk_beta_1);
114    writePoint(h, provingKey.vk_delta_1);
115    writePoint2(h, provingKey.vk_beta_2);
116    writePoint2(h, provingKey.vk_delta_2);
117
118    writeUint32ToPointer(h, pPolsA, h.offset);
119    for (let i=0; i<provingKey.nVars; i++) {
120        writeTransformedPolynomial(h, provingKey.polsA[i]);
121    }
122
123    writeUint32ToPointer(h, pPolsB, h.offset);
124    for (let i=0; i<provingKey.nVars; i++) {
125        writeTransformedPolynomial(h, provingKey.polsB[i]);
126    }
127
128    writeUint32ToPointer(h, pPointsA, h.offset);
129    for (let i=0; i<provingKey.nVars; i++) {
130        writePoint(h, provingKey.A[i]);
131    }
132
133    writeUint32ToPointer(h, pPointsB1, h.offset);
134    for (let i=0; i<provingKey.nVars; i++) {
135        writePoint(h, provingKey.B1[i]);
136    }
137
138    writeUint32ToPointer(h, pPointsB2, h.offset);
139    for (let i=0; i<provingKey.nVars; i++) {
140        writePoint2(h, provingKey.B2[i]);
141    }
142
143    writeUint32ToPointer(h, pPointsC, h.offset);
144    for (let i=provingKey.nPublic+1; i<provingKey.nVars; i++) {
145        writePoint(h, provingKey.C[i]);
146    }
147
148    writeUint32ToPointer(h, pPointsHExps, h.offset);
149    for (let i=0; i<provingKey.domainSize; i++) {
150        writePoint(h, provingKey.hExps[i]);
151    }
152
153    assert.equal(h.offset, buffLen);
154
155    return Buffer.from(buff);
156}
157
158module.exports = buildPKey;
159
160/*
161NSignals
162NPublic
163DomainSize (2 multiple)
164pPolsA
165pPolsB
166pPointsA
167pPointsB1
168pPointsB2
169pPointsC
170pPointsHExps
171Alfa1
172Beta1
173Delta1
174Beta2
175Delta2
176    PolinomialA_0
177    PolinomialA_1
178    PolinomialA_2
179    ...
180    PolinomialA_NVars-1
181
182    PolinomialB_0
183    PolinomialB_1
184    PolinomialB_2
185    ...
186    PolinomialB_NVars-1
187
188    PointA_0
189    PointA_1
190    ...
191    PointA_NVars-1
192
193    PointB1_0
194    PointB1_1
195    ...
196    PointB1_NVars-1
197
198    PointB2_0
199    PointB2_1
200    ...
201    PointB2_NVars-1
202
203    PointC_nPublics+1
204    PointC_nPublics+2
205    ...
206    PointC_nPublics+NVars
207
208    PointHExp_0
209    PointHExp_1
210    ...
211    PointHExp_DomainSize-1
212*/