2021-05-31 14:21:07 +03:00
|
|
|
/*
|
|
|
|
Copyright 2018 0KIMS association.
|
|
|
|
|
|
|
|
This file is part of snarkJS.
|
|
|
|
|
|
|
|
snarkJS is a free software: you can redistribute it and/or modify it
|
|
|
|
under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
|
|
License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2020-06-18 20:14:06 +03:00
|
|
|
// Format of the output
|
|
|
|
// Hash of the last contribution 64 Bytes
|
|
|
|
// 2^N*2-1 TauG1 Points (compressed)
|
|
|
|
// 2^N TauG2 Points (compressed)
|
|
|
|
// 2^N AlphaTauG1 Points (compressed)
|
|
|
|
// 2^N BetaTauG1 Points (compressed)
|
|
|
|
// Public Key
|
|
|
|
// BetaG2 (compressed)
|
|
|
|
// G1*s (compressed)
|
|
|
|
// G1*s*tau (compressed)
|
|
|
|
// G1*t (compressed)
|
|
|
|
// G1*t*alpha (compressed)
|
|
|
|
// G1*u (compressed)
|
|
|
|
// G1*u*beta (compressed)
|
|
|
|
// G2*sp*tau (compressed)
|
|
|
|
// G2*tp*alpha (compressed)
|
|
|
|
// G2*up*beta (compressed)
|
|
|
|
|
2020-07-11 11:31:52 +03:00
|
|
|
import * as fastFile from "fastfile";
|
|
|
|
import Blake2b from "blake2b-wasm";
|
|
|
|
import * as utils from "./zkey_utils.js";
|
|
|
|
import * as misc from "./misc.js";
|
2020-07-14 12:55:12 +03:00
|
|
|
import { applyKeyToChallengeSection } from "./mpc_applykey.js";
|
2020-07-11 11:31:52 +03:00
|
|
|
import { hashPubKey } from "./zkey_utils.js";
|
|
|
|
import { hashToG2 as hashToG2 } from "./keypair.js";
|
|
|
|
|
2020-07-14 12:55:12 +03:00
|
|
|
export default async function bellmanContribute(curve, challengeFilename, responesFileName, entropy, logger) {
|
2020-06-18 20:14:06 +03:00
|
|
|
await Blake2b.ready();
|
|
|
|
|
|
|
|
const rng = await misc.getRandomRng(entropy);
|
|
|
|
|
|
|
|
const delta = curve.Fr.fromRng(rng);
|
|
|
|
const invDelta = curve.Fr.inv(delta);
|
|
|
|
|
|
|
|
const sG1 = curve.G1.F.n8*2;
|
|
|
|
const sG2 = curve.G2.F.n8*2;
|
|
|
|
|
2020-07-14 12:55:12 +03:00
|
|
|
const fdFrom = await fastFile.readExisting(challengeFilename);
|
2020-06-18 20:14:06 +03:00
|
|
|
const fdTo = await fastFile.createOverride(responesFileName);
|
|
|
|
|
|
|
|
|
|
|
|
await copy(sG1); // alpha1
|
|
|
|
await copy(sG1); // beta1
|
|
|
|
await copy(sG2); // beta2
|
|
|
|
await copy(sG2); // gamma2
|
|
|
|
const oldDelta1 = await readG1();
|
2020-06-30 22:39:25 +03:00
|
|
|
const delta1 = curve.G1.timesFr(oldDelta1, delta);
|
2020-06-18 20:14:06 +03:00
|
|
|
await writeG1(delta1);
|
|
|
|
const oldDelta2 = await readG2();
|
2020-06-30 22:39:25 +03:00
|
|
|
const delta2 = curve.G2.timesFr(oldDelta2, delta);
|
2020-06-18 20:14:06 +03:00
|
|
|
await writeG2(delta2);
|
|
|
|
|
|
|
|
// IC
|
|
|
|
const nIC = await fdFrom.readUBE32();
|
|
|
|
await fdTo.writeUBE32(nIC);
|
|
|
|
await copy(nIC*sG1);
|
|
|
|
|
|
|
|
// H
|
|
|
|
const nH = await fdFrom.readUBE32();
|
|
|
|
await fdTo.writeUBE32(nH);
|
2020-07-14 12:55:12 +03:00
|
|
|
await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nH, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "H", logger);
|
2020-06-18 20:14:06 +03:00
|
|
|
|
|
|
|
// L
|
|
|
|
const nL = await fdFrom.readUBE32();
|
|
|
|
await fdTo.writeUBE32(nL);
|
2020-07-14 12:55:12 +03:00
|
|
|
await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nL, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "L", logger);
|
2020-06-18 20:14:06 +03:00
|
|
|
|
|
|
|
// A
|
|
|
|
const nA = await fdFrom.readUBE32();
|
|
|
|
await fdTo.writeUBE32(nA);
|
|
|
|
await copy(nA*sG1);
|
|
|
|
|
|
|
|
// B1
|
|
|
|
const nB1 = await fdFrom.readUBE32();
|
|
|
|
await fdTo.writeUBE32(nB1);
|
|
|
|
await copy(nB1*sG1);
|
|
|
|
|
|
|
|
// B2
|
|
|
|
const nB2 = await fdFrom.readUBE32();
|
|
|
|
await fdTo.writeUBE32(nB2);
|
|
|
|
await copy(nB2*sG2);
|
|
|
|
|
|
|
|
|
|
|
|
//////////
|
|
|
|
/// Read contributions
|
|
|
|
//////////
|
|
|
|
const transcriptHasher = Blake2b(64);
|
|
|
|
|
|
|
|
const mpcParams = {};
|
|
|
|
// csHash
|
|
|
|
mpcParams.csHash = await fdFrom.read(64);
|
|
|
|
transcriptHasher.update(mpcParams.csHash);
|
|
|
|
|
|
|
|
const nConttributions = await fdFrom.readUBE32();
|
|
|
|
mpcParams.contributions = [];
|
|
|
|
for (let i=0; i<nConttributions; i++) {
|
|
|
|
const c = { delta:{} };
|
|
|
|
c.deltaAfter = await readG1();
|
|
|
|
c.delta.g1_s = await readG1();
|
|
|
|
c.delta.g1_sx = await readG1();
|
|
|
|
c.delta.g2_spx = await readG2();
|
|
|
|
c.transcript = await fdFrom.read(64);
|
|
|
|
mpcParams.contributions.push(c);
|
|
|
|
hashPubKey(transcriptHasher, curve, c);
|
|
|
|
}
|
|
|
|
|
|
|
|
const curContribution = {};
|
|
|
|
curContribution.delta = {};
|
|
|
|
curContribution.delta.prvKey = delta;
|
2020-06-30 16:45:21 +03:00
|
|
|
curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng));
|
2020-06-30 22:39:25 +03:00
|
|
|
curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, delta));
|
2020-06-18 20:14:06 +03:00
|
|
|
utils.hashG1(transcriptHasher, curve, curContribution.delta.g1_s);
|
|
|
|
utils.hashG1(transcriptHasher, curve, curContribution.delta.g1_sx);
|
|
|
|
curContribution.transcript = transcriptHasher.digest();
|
2020-06-30 16:45:21 +03:00
|
|
|
curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript);
|
2020-06-30 22:39:25 +03:00
|
|
|
curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, delta));
|
2020-06-18 20:14:06 +03:00
|
|
|
curContribution.deltaAfter = delta1;
|
|
|
|
curContribution.type = 0;
|
|
|
|
mpcParams.contributions.push(curContribution);
|
|
|
|
|
|
|
|
|
|
|
|
//////////
|
|
|
|
/// Write COntribution
|
|
|
|
//////////
|
|
|
|
|
|
|
|
await fdTo.write(mpcParams.csHash);
|
|
|
|
await fdTo.writeUBE32(mpcParams.contributions.length);
|
|
|
|
|
|
|
|
for (let i=0; i<mpcParams.contributions.length; i++) {
|
|
|
|
const c = mpcParams.contributions[i];
|
|
|
|
await writeG1(c.deltaAfter);
|
|
|
|
await writeG1(c.delta.g1_s);
|
|
|
|
await writeG1(c.delta.g1_sx);
|
|
|
|
await writeG2(c.delta.g2_spx);
|
|
|
|
await fdTo.write(c.transcript);
|
|
|
|
}
|
|
|
|
|
|
|
|
const contributionHasher = Blake2b(64);
|
|
|
|
hashPubKey(contributionHasher, curve, curContribution);
|
|
|
|
|
2020-07-11 11:31:52 +03:00
|
|
|
const contributionHash = contributionHasher.digest();
|
|
|
|
|
|
|
|
if (logger) logger.info(misc.formatHash(contributionHash, "Contribution Hash: "));
|
2020-06-18 20:14:06 +03:00
|
|
|
|
|
|
|
await fdTo.close();
|
|
|
|
await fdFrom.close();
|
|
|
|
|
2020-07-11 11:31:52 +03:00
|
|
|
return contributionHash;
|
|
|
|
|
2020-06-18 20:14:06 +03:00
|
|
|
async function copy(nBytes) {
|
|
|
|
const CHUNK_SIZE = fdFrom.pageSize*2;
|
|
|
|
for (let i=0; i<nBytes; i+= CHUNK_SIZE) {
|
|
|
|
const n = Math.min(nBytes -i, CHUNK_SIZE);
|
|
|
|
const buff = await fdFrom.read(n);
|
|
|
|
await fdTo.write(buff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readG1() {
|
|
|
|
const buff = await fdFrom.read(curve.G1.F.n8*2);
|
|
|
|
return curve.G1.fromRprUncompressed(buff, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readG2() {
|
|
|
|
const buff = await fdFrom.read(curve.G2.F.n8*2);
|
|
|
|
return curve.G2.fromRprUncompressed(buff, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeG1(P) {
|
|
|
|
const buff = new Uint8Array(sG1);
|
|
|
|
curve.G1.toRprUncompressed(buff, 0, P);
|
|
|
|
await fdTo.write(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeG2(P) {
|
|
|
|
const buff = new Uint8Array(sG2);
|
|
|
|
curve.G2.toRprUncompressed(buff, 0, P);
|
|
|
|
await fdTo.write(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|