arnaucube
arnaucube/websnarkPublic Self-hosted repository
websnark/tools/buildpkey.js
tools/buildpkey.jsRaw
  1const {unstringifyBigInts} = require("./stringifybigint.js");
  2const fs = require("fs");
  3const bigInt = require("big-integer");
  4const assert = require("assert");
  5
  6const version = require("../package").version;
  7
  8const argv = require("yargs")
  9    .version(version)
 10    .usage(`node buildpkey.js -i "proving_key.json" -o "proving_key.bin"
 11  Default: circuit.json
 12        `)
 13    .alias("i", "input")
 14    .alias("o", "output")
 15    .help("h")
 16    .alias("h", "help")
 17    .epilogue(`Copyright (C) 2018  0kims association
 18    This program comes with ABSOLUTELY NO WARRANTY;
 19    This is free software, and you are welcome to redistribute it
 20    under certain conditions; see the COPYING file in the official
 21    repo directory at  https://github.com/iden3/circom `)
 22    .argv;
 23
 24const inputName = (argv.input) ? argv.input : "proving_key.json";
 25const outputName = (argv.output) ? argv.output : "proving_key.bin";
 26
 27
 28const provingKey = unstringifyBigInts(JSON.parse(fs.readFileSync(inputName, "utf8")));
 29
 30
 31
 32
 33
 34function writeUint32(h, val) {
 35    h.dataView.setUint32(h.offset, val, true);
 36    h.offset += 4;
 37}
 38
 39function writeUint32ToPointer(h, p, val) {
 40    h.dataView.setUint32(p, val, true);
 41}
 42
 43
 44function alloc(h, n) {
 45    const o = h.offset;
 46    h.offset += n;
 47    return o;
 48}
 49
 50function writeBigInt(h, bi) {
 51    for (let i=0; i<8; i++) {
 52        const v = bi.shiftRight(i*32).and(0xFFFFFFFF).toJSNumber();
 53        writeUint32(h, v);
 54    }
 55}
 56
 57function toMontgomeryQ(p) {
 58    const q = bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208583");
 59    return p.times(bigInt.one.shiftLeft(256)).mod(q);
 60}
 61
 62function toMontgomeryR(p) {
 63    const r = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
 64    return p.times(bigInt.one.shiftLeft(256)).mod(r);
 65}
 66
 67function writePoint(h, p) {
 68    writeBigInt(h, toMontgomeryQ(p[0]));
 69    writeBigInt(h, toMontgomeryQ(p[1]));
 70}
 71
 72function writePoint2(h, p) {
 73    writeBigInt(h, toMontgomeryQ(p[0][0]));
 74    writeBigInt(h, toMontgomeryQ(p[0][1]));
 75    writeBigInt(h, toMontgomeryQ(p[1][0]));
 76    writeBigInt(h, toMontgomeryQ(p[1][1]));
 77}
 78
 79function writeTransformedPolynomial(h, p) {
 80
 81    const keys = Object.keys(p);
 82
 83    writeUint32(h, keys.length);
 84
 85    for (let i=0; i<keys.length; i++) {
 86        writeUint32(h, keys[i]);
 87        writeBigInt(h, toMontgomeryR(p[keys[i]]));
 88    }
 89}
 90
 91function calculateBuffLen(provingKey) {
 92    function polSize(pol) {
 93        const l= Object.keys(pol).length;
 94        return 36*l + 4;
 95    }
 96
 97    let size = 40;
 98
 99    // alfa1, beta1, delta1
100    size += 3 * (32*2);
101
102    // beta2, delta2
103    size += 2 * (32*4);
104
105    for (let i=0; i<provingKey.nVars; i++) {
106        size += polSize(provingKey.polsA[i]);
107        size += polSize(provingKey.polsB[i]);
108    }
109
110    size += provingKey.nVars* (32*2);
111    size += provingKey.nVars* (32*2);
112    size += provingKey.nVars* (32*4);
113    size += (provingKey.nVars - provingKey.nPublic  - 1)* (32*2);
114    size += provingKey.domainSize * (32*2);
115
116    return size;
117}
118
119
120const buffLen = calculateBuffLen(provingKey);
121
122const buff = new ArrayBuffer(buffLen);
123
124const h = {
125    dataView: new DataView(buff),
126    offset: 0
127};
128
129
130writeUint32(h, provingKey.nVars);
131writeUint32(h, provingKey.nPublic);
132writeUint32(h, provingKey.domainSize);
133const pPolsA = alloc(h, 4);
134const pPolsB = alloc(h, 4);
135const pPointsA = alloc(h, 4);
136const pPointsB1 = alloc(h, 4);
137const pPointsB2 = alloc(h, 4);
138const pPointsC = alloc(h, 4);
139const pPointsHExps = alloc(h, 4);
140
141writePoint(h, provingKey.vk_alfa_1);
142writePoint(h, provingKey.vk_beta_1);
143writePoint(h, provingKey.vk_delta_1);
144writePoint2(h, provingKey.vk_beta_2);
145writePoint2(h, provingKey.vk_delta_2);
146
147writeUint32ToPointer(h, pPolsA, h.offset);
148for (let i=0; i<provingKey.nVars; i++) {
149    writeTransformedPolynomial(h, provingKey.polsA[i]);
150}
151
152writeUint32ToPointer(h, pPolsB, h.offset);
153for (let i=0; i<provingKey.nVars; i++) {
154    writeTransformedPolynomial(h, provingKey.polsB[i]);
155}
156
157writeUint32ToPointer(h, pPointsA, h.offset);
158for (let i=0; i<provingKey.nVars; i++) {
159    writePoint(h, provingKey.A[i]);
160}
161
162writeUint32ToPointer(h, pPointsB1, h.offset);
163for (let i=0; i<provingKey.nVars; i++) {
164    writePoint(h, provingKey.B1[i]);
165}
166
167writeUint32ToPointer(h, pPointsB2, h.offset);
168for (let i=0; i<provingKey.nVars; i++) {
169    writePoint2(h, provingKey.B2[i]);
170}
171
172writeUint32ToPointer(h, pPointsC, h.offset);
173for (let i=provingKey.nPublic+1; i<provingKey.nVars; i++) {
174    writePoint(h, provingKey.C[i]);
175}
176
177writeUint32ToPointer(h, pPointsHExps, h.offset);
178for (let i=0; i<provingKey.domainSize; i++) {
179    writePoint(h, provingKey.hExps[i]);
180}
181
182assert.equal(h.offset, buffLen);
183
184var wstream = fs.createWriteStream(outputName);
185wstream.write(Buffer.from(buff));
186wstream.end();
187
188/*
189NSignals
190NPublic
191DomainSize (2 multiple)
192pPolsA
193pPolsB
194pPointsA
195pPointsB1
196pPointsB2
197pPointsC
198pPointsHExps
199Alfa1
200Beta1
201Delta1
202Beta2
203Delta2
204    PolinomialA_0
205    PolinomialA_1
206    PolinomialA_2
207    ...
208    PolinomialA_NVars-1
209
210    PolinomialB_0
211    PolinomialB_1
212    PolinomialB_2
213    ...
214    PolinomialB_NVars-1
215
216    PointA_0
217    PointA_1
218    ...
219    PointA_NVars-1
220
221    PointB1_0
222    PointB1_1
223    ...
224    PointB1_NVars-1
225
226    PointB2_0
227    PointB2_1
228    ...
229    PointB2_NVars-1
230
231    PointC_nPublics+1
232    PointC_nPublics+2
233    ...
234    PointC_nPublics+NVars
235
236    PointHExp_0
237    PointHExp_1
238    ...
239    PointHExp_DomainSize-1
240*/