Skip to content

Commit

Permalink
Merge pull request #19 from EYBlockchain/liju.jose/concurrent-generat…
Browse files Browse the repository at this point in the history
…e-proof-fix

bug of concurrent generateProof fixed
  • Loading branch information
Westlad authored Jan 6, 2021
2 parents ea83ebd + 6fc6a6a commit b2074d0
Show file tree
Hide file tree
Showing 11 changed files with 228 additions and 299 deletions.
45 changes: 6 additions & 39 deletions src/queues/generateKeys.mjs
Original file line number Diff line number Diff line change
@@ -1,55 +1,22 @@
import fs from 'fs';
import path from 'path';
import zokrates from '@eyblockchain/zokrates-zexe.js';
import rabbitmq from '../utils/rabbitmq.mjs';
import logger from '../utils/logger.mjs';
import generateKeys from '../services/generateKeys.mjs';

export default function receiveMessage() {
const outputPath = `./output`;
const circuitsPath = `./circuits`;

rabbitmq.receiveMessage('generate-keys', async message => {
const { filepath, curve = 'bls12_377', backend = 'zexe', provingScheme = 'gm17' } = JSON.parse(
message.content.toString(),
);
const { replyTo, correlationId } = message.properties;
const response = {
error: null,
data: null,
};

try {
const ext = path.extname(filepath);
const circuitName = path.basename(filepath, '.zok'); // filename without '.zok'
const circuitDir = filepath.replace(ext, '');

fs.mkdirSync(`${outputPath}/${circuitDir}`, { recursive: true });

logger.info('Compile...');
await zokrates.compile(
`${circuitsPath}/${filepath}`,
`${outputPath}/${circuitDir}`,
`${circuitName}_out`,
curve,
);

logger.info('Setup...');
await zokrates.setup(
`${outputPath}/${circuitDir}/${circuitName}_out`,
`${outputPath}/${circuitDir}`,
provingScheme,
backend,
`${circuitName}_vk`,
`${circuitName}_pk`,
);

const vk = await zokrates.extractVk(`${outputPath}/${circuitDir}/${circuitName}_vk.key`);

logger.info(`Complete ${filepath}`);

response.data = { vk, filepath };
response.data = await generateKeys(JSON.parse(
message.content.toString(),
));
} catch (err) {
response.error = err;
logger.error('Error in generate-keys', err);
response.error = 'Key generation failed';
}

rabbitmq.sendMessage(replyTo, response, { correlationId });
Expand Down
68 changes: 7 additions & 61 deletions src/queues/generateProof.mjs
Original file line number Diff line number Diff line change
@@ -1,81 +1,27 @@
import fs from 'fs';
import util from 'util';
import zokrates from '@eyblockchain/zokrates-zexe.js';
import path from 'path';
import rabbitmq from '../utils/rabbitmq.mjs';
import { getProofByCircuitPath } from '../utils/filing.mjs';
import logger from '../utils/logger.mjs';

const unlink = util.promisify(fs.unlink);
import generateProof from '../services/generateProof.mjs';

export default function receiveMessage() {
const outputPath = `./output/`;

rabbitmq.receiveMessage('generate-proof', async message => {
const { replyTo, correlationId } = message.properties;
const {
folderpath,
inputs,
transactionInputs,
outputDirectoryPath,
proofFileName,
backend = 'zexe',
provingScheme = 'gm17',
} = JSON.parse(message.content.toString());

const response = {
error: null,
data: null,
};

const circuitName = path.basename(folderpath);

// Delete previous witness/proof files if they exist.
// Prevents bad inputs from going through anyway.
try {
await unlink(`${outputPath}/${folderpath}/${circuitName}_witness`);
await unlink(`${outputPath}/${folderpath}/${circuitName}_proof.json`);
} catch {
// No files to delete. Do nothing.
}

const opts = {};
opts.createFile = true;
opts.directory = `./output/${folderpath}` || outputDirectoryPath;
opts.fileName = `${circuitName}_proof.json` || proofFileName;

try {
logger.info('Compute witness...');
await zokrates.computeWitness(
`${outputPath}/${folderpath}/${circuitName}_out`,
`${outputPath}/${folderpath}/`,
`${circuitName}_witness`,
inputs,
);

logger.info('Generate proof...');
await zokrates.generateProof(
`${outputPath}/${folderpath}/${circuitName}_pk.key`,
`${outputPath}/${folderpath}/${circuitName}_out`,
`${outputPath}/${folderpath}/${circuitName}_witness`,
provingScheme,
backend,
opts,
);

const { proof, inputs: publicInputs } = await getProofByCircuitPath(folderpath);

logger.info(`Complete`);
logger.debug(`Responding with proof and inputs:`);
logger.debug(proof);
logger.debug(publicInputs);

response.data = { proof, inputs: publicInputs, transactionInputs };
response.data = await generateProof(JSON.parse(
message.content.toString(),
));
} catch (err) {
logger.error('Error in generate-proof', err);
response.error = 'Proof generation failed';
}

rabbitmq.sendMessage(replyTo, response, { correlationId, type: folderpath });

rabbitmq.sendMessage(replyTo, response, { correlationId });
rabbitmq.sendACK(message);
});
}
31 changes: 5 additions & 26 deletions src/queues/loadCircuits.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import fs from 'fs';

import rabbitmq from '../utils/rabbitmq.mjs';
import { untarFiles, deleteFile, getFilesRecursively } from '../utils/filing.mjs';
import logger from '../utils/logger.mjs';
import loadCircuits from '../services/loadCircuits.mjs';

export default function receiveMessage() {
const outputPath = `./circuits/`;

rabbitmq.receiveMessage('load-circuits', async message => {
const circuits = JSON.parse(message.content.toString());
const { replyTo, correlationId } = message.properties;
Expand All @@ -15,28 +12,10 @@ export default function receiveMessage() {
};

try {
if (!circuits.name.endsWith('.tar')) {
throw Error(`Expected an archive file with extension '.tar'. Got ${circuits.name}`);
}
fs.writeFileSync(`${outputPath}${circuits.name}`, circuits.data);

// unarchive the circuit files
await untarFiles('/app/circuits', circuits.name);

// get a list of files from the unarchived folder
const files = await getFilesRecursively(`/app/circuits/${circuits.name.replace('.tar', '')}`);
files.forEach(file => {
if (!file.endsWith('.zok')) {
throw Error('For shame, this is not an .zok file');
}
return null;
});

// delete the archive file
await deleteFile(`${outputPath}${circuits.name}`);
response.data = { message: 'Circuits loadded successfully' };
response.data = await loadCircuits(circuits);
} catch (err) {
response.error = err;
logger.error('Error in load-circuits', err);
response.error = 'Load-circuits failed';
}

rabbitmq.sendMessage(replyTo, response, { correlationId });
Expand Down
41 changes: 3 additions & 38 deletions src/routes/generateKeys.mjs
Original file line number Diff line number Diff line change
@@ -1,49 +1,14 @@
import express from 'express';
import fs from 'fs';
import path from 'path';
import zokrates from '@eyblockchain/zokrates-zexe.js';
import logger from '../utils/logger.mjs';
import generateKeys from '../services/generateKeys.mjs';

const router = express.Router();

const outputPath = `./output`;
const circuitsPath = `./circuits`;

router.post('/', async (req, res, next) => {
req.setTimeout(3600000); // 1 hour
const { filepath, curve = 'bls12_377', backend = 'zexe', provingScheme = 'gm17' } = req.body;
try {
const ext = path.extname(filepath);
const circuitName = path.basename(filepath, '.zok'); // filename without '.zok'
const circuitDir = filepath.replace(ext, '');

fs.mkdirSync(`${outputPath}/${circuitDir}`, { recursive: true });

logger.info('Compile...');
await zokrates.compile(
`${circuitsPath}/${filepath}`,
`${outputPath}/${circuitDir}`,
`${circuitName}_out`,
curve,
);

logger.info('Setup...');
await zokrates.setup(
`${outputPath}/${circuitDir}/${circuitName}_out`,
`${outputPath}/${circuitDir}`,
provingScheme,
backend,
`${circuitName}_vk`,
`${circuitName}_pk`,
);

const vk = await zokrates.extractVk(`${outputPath}/${circuitDir}/${circuitName}_vk.key`);

logger.info(`Complete`);

return res.send({ vk });
res.send(await generateKeys(req.body));
} catch (err) {
return next(err);
next(err);
}
});

Expand Down
70 changes: 3 additions & 67 deletions src/routes/generateProof.mjs
Original file line number Diff line number Diff line change
@@ -1,80 +1,16 @@
import fs from 'fs';
import util from 'util';
import express from 'express';
import zokrates from '@eyblockchain/zokrates-zexe.js';
import path from 'path';
import { getProofByCircuitPath } from '../utils/filing.mjs';
import logger from '../utils/logger.mjs';

const unlink = util.promisify(fs.unlink);
import generateProof from '../services/generateProof.mjs';

const router = express.Router();

const outputPath = `./output`;

router.post('/', async (req, res, next) => {
req.setTimeout(3600000); // 1 hour
const {
folderpath,
inputs,
transactionInputs,
outputDirectoryPath,
proofFileName,
backend = 'zexe',
provingScheme = 'gm17',
} = req.body;
logger.info(`Received request to /generate-proof`);
logger.debug(JSON.stringify(req.body, null, 2));

const circuitName = path.basename(folderpath);

// Delete previous witness/proof files if they exist.
// Prevents bad inputs from going through anyway.
try {
await unlink(`${outputPath}/${folderpath}/${circuitName}_witness`);
await unlink(`${outputPath}/${folderpath}/${circuitName}_proof.json`);
} catch {
// Do nothing. It's okay if files don't exist.
}

const opts = {};
opts.createFile = true;
opts.directory = `./output/${folderpath}` || outputDirectoryPath;
opts.fileName = `${circuitName}_proof.json` || proofFileName;

try {
logger.info('Compute witness...');
await zokrates.computeWitness(
`${outputPath}/${folderpath}/${circuitName}_out`,
`${outputPath}/${folderpath}/`,
`${circuitName}_witness`,
inputs,
);

logger.info('Generate proof...');
await zokrates.generateProof(
`${outputPath}/${folderpath}/${circuitName}_pk.key`,
`${outputPath}/${folderpath}/${circuitName}_out`,
`${outputPath}/${folderpath}/${circuitName}_witness`,
provingScheme,
backend,
opts,
);

const { proof, inputs: publicInputs } = await getProofByCircuitPath(folderpath);

logger.info(`Complete`);
logger.debug(`Responding with proof and inputs:`);
logger.debug(JSON.stringify(req.body, null, 2));
logger.debug(publicInputs);
return res.send({
proof,
inputs: publicInputs,
type: folderpath,
transactionInputs,
});
res.send(await generateProof(req.body));
} catch (err) {
return next(err);
next(err);
}
});

Expand Down
Loading

0 comments on commit b2074d0

Please sign in to comment.