Skeleton
This commit is contained in:
commit
3f2f303b94
33
.eslintrc.js
Normal file
33
.eslintrc.js
Normal file
@ -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"
|
||||||
|
}
|
||||||
|
};
|
63
.gitignore
vendored
Normal file
63
.gitignore
vendored
Normal file
@ -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
|
107
README
Normal file
107
README
Normal file
@ -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");
|
||||||
|
}
|
||||||
|
```
|
4
index.js
Normal file
4
index.js
Normal file
@ -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";
|
1066
package-lock.json
generated
Normal file
1066
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
26
package.json
Normal file
26
package.json
Normal file
@ -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"
|
||||||
|
}
|
||||||
|
}
|
6
src/circuit.js
Normal file
6
src/circuit.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
module.exports = class Circuit {
|
||||||
|
constructor(circuitDef) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
29
src/g1curve.js
Normal file
29
src/g1curve.js
Normal file
@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
28
src/g2curve.js
Normal file
28
src/g2curve.js
Normal file
@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
10
src/pairing.js
Normal file
10
src/pairing.js
Normal file
@ -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");
|
||||||
|
};
|
46
src/polinomial.js
Normal file
46
src/polinomial.js
Normal file
@ -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;
|
5
src/prover.js
Normal file
5
src/prover.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
|
module.exports = function genProof(vk_proof, witness) {
|
||||||
|
|
||||||
|
}
|
5
src/setup.js
Normal file
5
src/setup.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
|
module.exports = function setup(circuit) {
|
||||||
|
|
||||||
|
}
|
4
src/verifier.js
Normal file
4
src/verifier.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
module.exports = function isValid(vk_verifier, proof, publicSignals) {
|
||||||
|
|
||||||
|
}
|
39
src/znfield.js
Normal file
39
src/znfield.js
Normal file
@ -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;
|
Loading…
Reference in New Issue
Block a user