@ -0,0 +1,33 @@ |
|||
module.exports = { |
|||
"plugins": [ |
|||
"mocha" |
|||
], |
|||
"env": { |
|||
"es6": true, |
|||
"node": true, |
|||
"mocha": true |
|||
}, |
|||
"parserOptions": { |
|||
"ecmaVersion": 2017 |
|||
}, |
|||
"extends": "eslint:recommended", |
|||
"rules": { |
|||
"indent": [ |
|||
"error", |
|||
4 |
|||
], |
|||
"linebreak-style": [ |
|||
"error", |
|||
"unix" |
|||
], |
|||
"quotes": [ |
|||
"error", |
|||
"double" |
|||
], |
|||
"semi": [ |
|||
"error", |
|||
"always" |
|||
], |
|||
"mocha/no-exclusive-tests": "error" |
|||
} |
|||
}; |
@ -0,0 +1,63 @@ |
|||
# Logs |
|||
logs |
|||
*.log |
|||
npm-debug.log* |
|||
yarn-debug.log* |
|||
yarn-error.log* |
|||
|
|||
# Runtime data |
|||
pids |
|||
*.pid |
|||
*.seed |
|||
*.pid.lock |
|||
|
|||
# Directory for instrumented libs generated by jscoverage/JSCover |
|||
lib-cov |
|||
|
|||
# Coverage directory used by tools like istanbul |
|||
coverage |
|||
|
|||
# nyc test coverage |
|||
.nyc_output |
|||
|
|||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) |
|||
.grunt |
|||
|
|||
# Bower dependency directory (https://bower.io/) |
|||
bower_components |
|||
|
|||
# node-waf configuration |
|||
.lock-wscript |
|||
|
|||
# Compiled binary addons (https://nodejs.org/api/addons.html) |
|||
build/Release |
|||
|
|||
# Dependency directories |
|||
node_modules/ |
|||
jspm_packages/ |
|||
|
|||
# Typescript v1 declaration files |
|||
typings/ |
|||
|
|||
# Optional npm cache directory |
|||
.npm |
|||
|
|||
# Optional eslint cache |
|||
.eslintcache |
|||
|
|||
# Optional REPL history |
|||
.node_repl_history |
|||
|
|||
# Output of 'npm pack' |
|||
*.tgz |
|||
|
|||
# Yarn Integrity file |
|||
.yarn-integrity |
|||
|
|||
# dotenv environment variables file |
|||
.env |
|||
|
|||
# next.js build output |
|||
.next |
|||
|
|||
tmp |
@ -0,0 +1,107 @@ |
|||
# javascript implementation of zkSnark |
|||
|
|||
This is a javascript implementation of zkSnarks. |
|||
|
|||
This library allows to do the trusted setup, generate proofs and verify the proofs. |
|||
|
|||
This library uses the compiled circuits generated by the jaz compiler. |
|||
|
|||
## Install |
|||
|
|||
``` |
|||
npm install zkSnark |
|||
``` |
|||
|
|||
## Usage |
|||
|
|||
### import |
|||
|
|||
``` |
|||
const zkSnark = require("zksnark"); |
|||
``` |
|||
|
|||
### Load a circuit. |
|||
|
|||
``` |
|||
// "myCircuit.cir" is the output of the jaz compiler |
|||
|
|||
const circuitDef = JSON.parse(fs.readFileSync("myCircuit.cir", "utf8")); |
|||
const circuit = new zkSnark.Circuit(circuitDef); |
|||
``` |
|||
|
|||
### Inspect the circuit. |
|||
|
|||
``` |
|||
// `signalId` can always be a number or an alias string |
|||
|
|||
circuit.m; // number of constrains |
|||
circuit.n; // number of signals |
|||
circuit.p; // number of public signals (nPublicInputs + nOutputs) |
|||
|
|||
// The array of signals is always sorted in this order: |
|||
// [ outputs, publicInputs, privedInputs, internalSignals, constants] |
|||
|
|||
// returns a,b and c coeficients of the `signalId` on a given `constrain` |
|||
circuit.a(constrain, signalId) |
|||
circuit.b(constrain, signalId) |
|||
circuit.c(constrain, signalId) |
|||
|
|||
circuit.nOutputs // number of public outputs |
|||
circuit.nPublicInputs // number of public inputs |
|||
circuit.nPrivateInputs // number of private inputs |
|||
circuit.nInputs // number of inputs ( nPublicInputs + nPrivateInputs) |
|||
|
|||
circuit.outputIdx(i) // returns the index of the i'th output |
|||
circuit.inputIdx(i) // returns the index of the i'th input |
|||
circuit.inputPublicIdx(i) // returns the index of the i'th public input |
|||
circuit.inputPrivateIdx(i) // returns the index of the i'th private input |
|||
|
|||
// returns signal Idx given a signalId |
|||
// if the idx >= n , it is a constant |
|||
// if the idx == -1, the signal does not exist |
|||
circuit.signalId2idx(signalId); |
|||
|
|||
// returns an array aliases names for a given signalId |
|||
circuit.signalNames(signalId) |
|||
|
|||
// input is a key value object where keys are the signal names |
|||
// of all the inputs (public and private) |
|||
// returns an array of values that represent the witness |
|||
circuit.generateWitness(input) |
|||
``` |
|||
|
|||
### Trusted setup |
|||
|
|||
``` |
|||
const setup = zkSnark.setup(circuit); |
|||
fs.writeFileSink("myCircuit.vk_proof", JSON.stringify(setup.vk_proof), "utf8"); |
|||
fs.writeFileSink("myCircuit.vk_verifier", JSON.stringify(setup.vk_verifier), "utf8"); |
|||
setup.toxic // Must be discarded. |
|||
``` |
|||
|
|||
### Generate proof |
|||
|
|||
``` |
|||
const circuitDef = JSON.parse(fs.readFileSync("myCircuit.cir", "utf8")); |
|||
const circuit = new zkSnark.Circuit(circuitDef); |
|||
const input = { |
|||
"main.pubIn1": "123", |
|||
"main.out1": "456" |
|||
} |
|||
const witness = circuit.generateWitness(input); |
|||
const vk_proof = JSON.parse(fs.readFileSync("myCircuit.vk_proof", "utf8")); |
|||
|
|||
const {proof, publicSignals} = zkSnark.genProof(vk_proof, witness); |
|||
``` |
|||
|
|||
### Verifier |
|||
|
|||
``` |
|||
const vk_verifier = JSON.parse(fs.readFileSync("myCircuit.vk_verifier", "utf8")); |
|||
|
|||
if (zkSnark.isValid(vk_verifier, proof, publicSignals)) { |
|||
console.log("The proof is valid"); |
|||
} else { |
|||
console.log("The proof is not valid"); |
|||
} |
|||
``` |
@ -0,0 +1,4 @@ |
|||
exports.Circuit = require "./src/circuit.js"; |
|||
exports.setup = require "./src/setup.js"; |
|||
exports.genProof = require "./src/prover.js"; |
|||
exports.isValid = require "./src/verifier.js"; |
@ -0,0 +1,26 @@ |
|||
{ |
|||
"name": "zksnark", |
|||
"version": "0.0.1", |
|||
"description": "zkSnark implementation in javascript", |
|||
"main": "index.js", |
|||
"scripts": { |
|||
"test": "echo \"Error: no test specified\" && exit 1" |
|||
}, |
|||
"keywords": [ |
|||
"zksnark", |
|||
"zcash", |
|||
"ethereum", |
|||
"zero", |
|||
"knowlage", |
|||
"cryptography", |
|||
"circuit" |
|||
], |
|||
"author": "Jordi Baylina", |
|||
"license": "GPL-3.0", |
|||
"dependencies": { |
|||
"eslint": "^5.3.0" |
|||
}, |
|||
"devDependencies": { |
|||
"eslint-plugin-mocha": "^5.1.0" |
|||
} |
|||
} |
@ -0,0 +1,6 @@ |
|||
|
|||
module.exports = class Circuit { |
|||
constructor(circuitDef) { |
|||
|
|||
} |
|||
}; |
@ -0,0 +1,29 @@ |
|||
const bigInt = require("big-integer"); |
|||
const ZnField = require("./znfield.js"); |
|||
|
|||
module.eports = class G1Curve { |
|||
|
|||
constructor() { |
|||
this.F = new ZnField(bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208583")); |
|||
this.g = [ |
|||
|
|||
]; |
|||
|
|||
} |
|||
|
|||
add(p1, p2) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
double(p1) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
mulEscalar(p1, e) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
}; |
@ -0,0 +1,28 @@ |
|||
const bigInt = require("big-integer"); |
|||
const ZnField = require("./znfield.js"); |
|||
|
|||
module.eports = class G2Curve { |
|||
|
|||
constructor() { |
|||
this.F = new ZnField(bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208583")); |
|||
this.g = [ |
|||
|
|||
]; |
|||
} |
|||
|
|||
add(p1, p2) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
double(p1) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
mulEscalar(p1, e) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
}; |
@ -0,0 +1,10 @@ |
|||
/* |
|||
This module calculate the pairing of p1 and p2 where p1 in G1 and p2 in G2 |
|||
*/ |
|||
|
|||
const bigInt = require("big-integer"); |
|||
|
|||
module.exports = function pairing(p1, p2) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
}; |
@ -0,0 +1,46 @@ |
|||
/* |
|||
This library do operations on polinomials where their coefficients are in field F |
|||
|
|||
The polynomial P(x) = p0 + p1 * x + p2 * x^2 + p3 * x^3, ... |
|||
is represented by the array [ p0, p1, p2, p3, ... ] |
|||
*/ |
|||
|
|||
class PolField { |
|||
constructor (F) { |
|||
this.F = F; |
|||
} |
|||
|
|||
_reduce(a) { |
|||
let i = a.length-1; |
|||
while ((i>=0) && (this.F.isZero(a[i])) ) i--; |
|||
return (i < a.length-1) ? a.slice(0, i+1) : a; |
|||
} |
|||
|
|||
add(a, b) { |
|||
const maxGrade = Math.max(a.length, b.length); |
|||
const res = new Array(maxGrade); |
|||
for (let i=0; i<maxGrade; i++) { |
|||
res[i] = this.F.add(a[i], b[i]); |
|||
} |
|||
return this._reduce(res); |
|||
} |
|||
|
|||
sub(a, b) { |
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
mul(a, b) { |
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
div(a, b) { |
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
lagrange(points) { |
|||
throw new Error("Not Implementted"); |
|||
} |
|||
} |
|||
|
|||
|
|||
module.exports = PolField; |
@ -0,0 +1,5 @@ |
|||
|
|||
|
|||
module.exports = function genProof(vk_proof, witness) { |
|||
|
|||
} |
@ -0,0 +1,5 @@ |
|||
|
|||
|
|||
module.exports = function setup(circuit) { |
|||
|
|||
} |
@ -0,0 +1,4 @@ |
|||
|
|||
module.exports = function isValid(vk_verifier, proof, publicSignals) { |
|||
|
|||
} |
@ -0,0 +1,39 @@ |
|||
|
|||
|
|||
class ZnField { |
|||
constructor(n) { |
|||
this.n = n; |
|||
} |
|||
|
|||
add(a, b) { |
|||
const maxGrade = Math.max(a.length, b.length); |
|||
const res = new Array(maxGrade); |
|||
for (let i=0; i<maxGrade; i++) { |
|||
res[i] = this.F.add(a[i], b[i]); |
|||
} |
|||
return this._reduce(res); |
|||
} |
|||
|
|||
sub(a, b) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
mul(a, b) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
inverse(a, b) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
div(a, b) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
} |
|||
|
|||
module.exports = ZnField; |