mirror of
https://github.com/arnaucube/circomlib.git
synced 2026-02-07 03:06:44 +01:00
Compare commits
36 Commits
v0.0.2
...
feature/js
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0aabe6447d | ||
|
|
58f758d5ad | ||
|
|
7792887216 | ||
|
|
7971f0150e | ||
|
|
b3ff8b246d | ||
|
|
951e51423d | ||
|
|
9a5294dea1 | ||
|
|
2635e8d3c9 | ||
|
|
138945bfdc | ||
|
|
2f9ad59c3a | ||
|
|
4a4a30b8b8 | ||
|
|
084f5b593b | ||
|
|
57da978ff5 | ||
|
|
d1bde3ab55 | ||
|
|
ed820fbc9b | ||
|
|
0639963bea | ||
|
|
345f040b41 | ||
|
|
9cab539698 | ||
|
|
6ea1ea718a | ||
|
|
37edfc1834 | ||
|
|
6d6558370f | ||
|
|
09f36d1e4d | ||
|
|
e02fd5edf8 | ||
|
|
e636a4ac83 | ||
|
|
ccaa7ff23b | ||
|
|
38fc4b7396 | ||
|
|
2d43178c8d | ||
|
|
2cab572c66 | ||
|
|
2ef25591b6 | ||
|
|
91fe53118a | ||
|
|
98a33d5700 | ||
|
|
55e9a60c37 | ||
|
|
fcc61f9237 | ||
|
|
4b147eca7f | ||
|
|
9513ee2ff2 | ||
|
|
e4a5860117 |
@@ -1,13 +1,15 @@
|
|||||||
const bn128 = require("snarkjs").bn128;
|
const bn128 = require("snarkjs").bn128;
|
||||||
const bigInt = require("snarkjs").bigInt;
|
const bigInt = require("snarkjs").bigInt;
|
||||||
const createBlakeHash = require("blake-hash");
|
const createBlakeHash = require("blake-hash");
|
||||||
const assert = require("assert");
|
const babyJub = require("../src/babyjub");
|
||||||
|
|
||||||
function getPoint(S) {
|
function getPoint(S) {
|
||||||
const F = bn128.Fr;
|
const F = bn128.Fr;
|
||||||
const h = createBlakeHash("blake256").update(S).digest();
|
const h = createBlakeHash("blake256").update(S).digest();
|
||||||
|
|
||||||
assert(h.length == 32);
|
if (h.length != 32) {
|
||||||
|
throw new Error("Invalid length")
|
||||||
|
}
|
||||||
|
|
||||||
let sign = false;
|
let sign = false;
|
||||||
if (h[31] & 0x80) {
|
if (h[31] & 0x80) {
|
||||||
@@ -15,26 +17,30 @@ function getPoint(S) {
|
|||||||
sign = true;
|
sign = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let x = bigInt(0);
|
let y = bigInt(0);
|
||||||
for (let i=0; i<32; i++) {
|
for (let i=0; i<32; i++) {
|
||||||
x = x.shl(8);
|
y = y.shl(8);
|
||||||
x = x.add(bigInt(h[i]));
|
y = y.add(bigInt(h[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
const a = bigInt("168700");
|
const a = bigInt("168700");
|
||||||
const d = bigInt("168696");
|
const d = bigInt("168696");
|
||||||
|
|
||||||
const x2 = F.square(x);
|
const y2 = F.square(y);
|
||||||
|
|
||||||
let y = F.sqrt(F.div(
|
let x = F.sqrt(F.div(
|
||||||
F.sub(F.one, F.mul(a, x2)),
|
F.sub(F.one, y2),
|
||||||
F.sub(F.one, F.mul(d, x2))));
|
F.sub(a, F.mul(d, y2))));
|
||||||
|
|
||||||
if (y == null) return null;
|
if (x == null) return null;
|
||||||
|
|
||||||
if (sign) y = F.neg(y);
|
if (sign) x = F.neg(x);
|
||||||
|
|
||||||
return [bn128.Fr.affine(x), bn128.Fr.affine(y)];
|
const p = [bn128.Fr.affine(x), bn128.Fr.affine(y)];
|
||||||
|
|
||||||
|
const p8 = babyJub.mulPointEscalar(p, 8);
|
||||||
|
|
||||||
|
return p8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -47,29 +53,22 @@ function generatePoint(S) {
|
|||||||
p = getPoint(S+"_"+sidx);
|
p = getPoint(S+"_"+sidx);
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
assert(inCurve(p));
|
if (!babyJub.inCurve(p)){
|
||||||
|
throw new Error("Point not in curve");
|
||||||
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
function inCurve(p) {
|
|
||||||
const F = bn128.Fr;
|
|
||||||
|
|
||||||
const a = bigInt("168700");
|
|
||||||
const d = bigInt("168696");
|
|
||||||
|
|
||||||
const x2 = F.square(p[0]);
|
|
||||||
const y2 = F.square(p[1]);
|
|
||||||
|
|
||||||
return F.equals(
|
|
||||||
F.add(F.mul(a, x2), y2),
|
|
||||||
F.add(F.one, F.mul(F.mul(x2, y2), d)));
|
|
||||||
}
|
|
||||||
|
|
||||||
const g = [
|
const g = [
|
||||||
bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
||||||
bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475")];
|
bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475")];
|
||||||
|
|
||||||
if (!inCurve(g)) {
|
// Sanity check
|
||||||
|
if (!babyJub.inCurve(g)) {
|
||||||
throw new Error("Generator not In curve -> Some thing goes wrong...");
|
throw new Error("Generator not In curve -> Some thing goes wrong...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
298
circuit.json
298
circuit.json
@@ -1,298 +0,0 @@
|
|||||||
{
|
|
||||||
"mainCode": "{\n {\n }\n ctx.setVar(\"base\", [], [\"17777552123799933955779906779655732241715742912184938656739573121738514868268\",\"2626589144620713026669568689430873010625803728049924121243784502389097019475\"]);\n}\n",
|
|
||||||
"signalName2Idx": {
|
|
||||||
"one": 0,
|
|
||||||
"main.out[0][0]": 1,
|
|
||||||
"main.out[0][1]": 2,
|
|
||||||
"main.out[1][0]": 3,
|
|
||||||
"main.out[1][1]": 4,
|
|
||||||
"main.out[2][0]": 5,
|
|
||||||
"main.out[2][1]": 6,
|
|
||||||
"main.out[3][0]": 7,
|
|
||||||
"main.out[3][1]": 8,
|
|
||||||
"main.out[4][0]": 9,
|
|
||||||
"main.out[4][1]": 10,
|
|
||||||
"main.out[5][0]": 11,
|
|
||||||
"main.out[5][1]": 12,
|
|
||||||
"main.out[6][0]": 13,
|
|
||||||
"main.out[6][1]": 14,
|
|
||||||
"main.out[7][0]": 15,
|
|
||||||
"main.out[7][1]": 16,
|
|
||||||
"main.out[8][0]": 17,
|
|
||||||
"main.out[8][1]": 18,
|
|
||||||
"main.out[9][0]": 19,
|
|
||||||
"main.out[9][1]": 20,
|
|
||||||
"main.out[10][0]": 21,
|
|
||||||
"main.out[10][1]": 22,
|
|
||||||
"main.out[11][0]": 23,
|
|
||||||
"main.out[11][1]": 24,
|
|
||||||
"main.out[12][0]": 25,
|
|
||||||
"main.out[12][1]": 26,
|
|
||||||
"main.out[13][0]": 27,
|
|
||||||
"main.out[13][1]": 28,
|
|
||||||
"main.out[14][0]": 29,
|
|
||||||
"main.out[14][1]": 30,
|
|
||||||
"main.out[15][0]": 31,
|
|
||||||
"main.out[15][1]": 32
|
|
||||||
},
|
|
||||||
"components": [
|
|
||||||
{
|
|
||||||
"name": "main",
|
|
||||||
"params": {
|
|
||||||
"base": [
|
|
||||||
{
|
|
||||||
"type": "NUMBER",
|
|
||||||
"value": "17777552123799933955779906779655732241715742912184938656739573121738514868268",
|
|
||||||
"first_line": 3,
|
|
||||||
"first_column": 12,
|
|
||||||
"last_line": 3,
|
|
||||||
"last_column": 89
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "NUMBER",
|
|
||||||
"value": "2626589144620713026669568689430873010625803728049924121243784502389097019475",
|
|
||||||
"first_line": 4,
|
|
||||||
"first_column": 12,
|
|
||||||
"last_line": 4,
|
|
||||||
"last_column": 88
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"k": {
|
|
||||||
"type": "NUMBER",
|
|
||||||
"value": "0",
|
|
||||||
"first_line": 6,
|
|
||||||
"first_column": 41,
|
|
||||||
"last_line": 6,
|
|
||||||
"last_column": 42
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"template": "EscalarMulW4Table",
|
|
||||||
"inputSignals": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"componentName2Idx": {
|
|
||||||
"main": 0
|
|
||||||
},
|
|
||||||
"signals": [
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"one"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[0][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[0][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[1][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[1][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[2][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[2][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[3][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[3][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[4][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[4][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[5][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[5][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[6][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[6][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[7][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[7][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[8][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[8][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[9][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[9][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[10][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[10][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[11][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[11][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[12][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[12][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[13][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[13][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[14][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[14][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[15][0]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"names": [
|
|
||||||
"main.out[15][1]"
|
|
||||||
],
|
|
||||||
"triggerComponents": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"constraints": [],
|
|
||||||
"templates": {
|
|
||||||
"EscalarMulW4Table": "function(ctx) {\n ctx.setVar(\"dbl\", [], ctx.getVar(\"base\",[]));\n for (ctx.setVar(\"i\", [], \"0\");bigInt(ctx.getVar(\"i\",[])).lt(bigInt(bigInt(ctx.getVar(\"k\",[])).mul(bigInt(\"4\")).mod(__P__))) ? 1 : 0;(ctx.setVar(\"i\", [], bigInt(ctx.getVar(\"i\",[])).add(bigInt(\"1\")).mod(__P__))).add(__P__).sub(bigInt(1)).mod(__P__)) { \n {\n ctx.setVar(\"dbl\", [], ctx.callFunction(\"pointAdd\", [ctx.getVar(\"dbl\",[\"0\"]),ctx.getVar(\"dbl\",[\"1\"]),ctx.getVar(\"dbl\",[\"0\"]),ctx.getVar(\"dbl\",[\"1\"])]));\n }\n\n }\n ctx.setSignal(\"out\", [\"0\",\"0\"], \"0\");\n ctx.assert(ctx.getSignal(\"out\", [\"0\",\"0\"]), \"0\");\n ctx.setSignal(\"out\", [\"0\",\"1\"], \"1\");\n ctx.assert(ctx.getSignal(\"out\", [\"0\",\"1\"]), \"1\");\n for (ctx.setVar(\"i\", [], \"1\");bigInt(ctx.getVar(\"i\",[])).lt(bigInt(\"16\")) ? 1 : 0;(ctx.setVar(\"i\", [], bigInt(ctx.getVar(\"i\",[])).add(bigInt(\"1\")).mod(__P__))).add(__P__).sub(bigInt(1)).mod(__P__)) { \n {\n ctx.setVar(\"p\", [], ctx.callFunction(\"pointAdd\", [ctx.getSignal(\"out\", [bigInt(ctx.getVar(\"i\",[])).add(__P__).sub(bigInt(\"1\")).mod(__P__),\"0\"]),ctx.getSignal(\"out\", [bigInt(ctx.getVar(\"i\",[])).add(__P__).sub(bigInt(\"1\")).mod(__P__),\"1\"]),ctx.getVar(\"dbl\",[\"0\"]),ctx.getVar(\"dbl\",[\"1\"])]));\n ctx.setSignal(\"out\", [ctx.getVar(\"i\",[]),\"0\"], ctx.getVar(\"p\",[\"0\"]));\n ctx.assert(ctx.getSignal(\"out\", [ctx.getVar(\"i\",[]),\"0\"]), ctx.getVar(\"p\",[\"0\"]));\n ctx.setSignal(\"out\", [ctx.getVar(\"i\",[]),\"1\"], ctx.getVar(\"p\",[\"1\"]));\n ctx.assert(ctx.getSignal(\"out\", [ctx.getVar(\"i\",[]),\"1\"]), ctx.getVar(\"p\",[\"1\"]));\n }\n\n }\n}\n"
|
|
||||||
},
|
|
||||||
"functions": {
|
|
||||||
"pointAdd": {
|
|
||||||
"params": [
|
|
||||||
"x1",
|
|
||||||
"y1",
|
|
||||||
"x2",
|
|
||||||
"y2"
|
|
||||||
],
|
|
||||||
"func": "function(ctx) {\n ctx.setVar(\"a\", [], \"168700\");\n ctx.setVar(\"d\", [], \"168696\");\n ctx.setVar(\"res\", [\"0\"], bigInt(bigInt(bigInt(ctx.getVar(\"x1\",[])).mul(bigInt(ctx.getVar(\"y2\",[]))).mod(__P__)).add(bigInt(bigInt(ctx.getVar(\"y1\",[])).mul(bigInt(ctx.getVar(\"x2\",[]))).mod(__P__))).mod(__P__)).mul( bigInt(bigInt(\"1\").add(bigInt(bigInt(bigInt(bigInt(bigInt(ctx.getVar(\"d\",[])).mul(bigInt(ctx.getVar(\"x1\",[]))).mod(__P__)).mul(bigInt(ctx.getVar(\"x2\",[]))).mod(__P__)).mul(bigInt(ctx.getVar(\"y1\",[]))).mod(__P__)).mul(bigInt(ctx.getVar(\"y2\",[]))).mod(__P__))).mod(__P__)).inverse(__P__) ).mod(__P__));\n ctx.setVar(\"res\", [\"1\"], bigInt(bigInt(bigInt(ctx.getVar(\"y1\",[])).mul(bigInt(ctx.getVar(\"y2\",[]))).mod(__P__)).add(__P__).sub(bigInt(bigInt(bigInt(ctx.getVar(\"a\",[])).mul(bigInt(ctx.getVar(\"x1\",[]))).mod(__P__)).mul(bigInt(ctx.getVar(\"x2\",[]))).mod(__P__))).mod(__P__)).mul( bigInt(bigInt(\"1\").add(__P__).sub(bigInt(bigInt(bigInt(bigInt(bigInt(ctx.getVar(\"d\",[])).mul(bigInt(ctx.getVar(\"x1\",[]))).mod(__P__)).mul(bigInt(ctx.getVar(\"x2\",[]))).mod(__P__)).mul(bigInt(ctx.getVar(\"y1\",[]))).mod(__P__)).mul(bigInt(ctx.getVar(\"y2\",[]))).mod(__P__))).mod(__P__)).inverse(__P__) ).mod(__P__));\n return ctx.getVar(\"res\",[]);;\n}\n"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nPrvInputs": 0,
|
|
||||||
"nPubInputs": 0,
|
|
||||||
"nInputs": 0,
|
|
||||||
"nOutputs": 0,
|
|
||||||
"nVars": 1,
|
|
||||||
"nConstants": 32,
|
|
||||||
"nSignals": 33
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
template BabyAdd() {
|
|
||||||
signal input x1;
|
|
||||||
signal input y1;
|
|
||||||
signal input x2;
|
|
||||||
signal input y2;
|
|
||||||
signal output xout;
|
|
||||||
signal output yout;
|
|
||||||
|
|
||||||
signal beta;
|
|
||||||
signal gamma;
|
|
||||||
signal delta;
|
|
||||||
signal epsilon;
|
|
||||||
signal tau;
|
|
||||||
|
|
||||||
var a = 168700;
|
|
||||||
var d = 168696;
|
|
||||||
|
|
||||||
beta <== x1*y2;
|
|
||||||
gamma <== y1*x2;
|
|
||||||
delta <== y1*y2;
|
|
||||||
epsilon <== x1*x2;
|
|
||||||
tau <== delta * epsilon;
|
|
||||||
|
|
||||||
xout <-- (beta + gamma) / (1+ d*tau);
|
|
||||||
(1+ d*tau) * xout === (beta + gamma);
|
|
||||||
|
|
||||||
yout <-- (delta - a * epsilon) / (1-d*tau);
|
|
||||||
(1-d*tau)*yout === (delta - a * epsilon);
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
templete Verfier() {
|
|
||||||
signal input hMsg[256];
|
|
||||||
|
|
||||||
signal input Ax;
|
|
||||||
signal input Ay;
|
|
||||||
|
|
||||||
signal input Rx;
|
|
||||||
signal input Ry;
|
|
||||||
|
|
||||||
signal input s[256];
|
|
||||||
|
|
||||||
|
|
||||||
componet exps = Exp();
|
|
||||||
component exph = Exp();
|
|
||||||
|
|
||||||
component adder = BabyAdd();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
function pointAdd(x1,y1,x2,y2) {
|
|
||||||
var a = 168700;
|
|
||||||
var d = 168696;
|
|
||||||
|
|
||||||
var res[2];
|
|
||||||
res[0] = (x1*y2 + y1*x2) / (1 + d*x1*x2*y1*y2);
|
|
||||||
res[1] = (y1*y2 - a*x1*x2) / (1 - d*x1*x2*y1*y2);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
template EscalarMulW4Table(base, k) {
|
|
||||||
signal output out[16][2];
|
|
||||||
|
|
||||||
var i;
|
|
||||||
var p[2];
|
|
||||||
|
|
||||||
var dbl = base;
|
|
||||||
|
|
||||||
for (i=0; i<k*4; i++) {
|
|
||||||
dbl = pointAdd(dbl[0], dbl[1], dbl[0], dbl[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
out[0][0] <== 0;
|
|
||||||
out[0][1] <== 1;
|
|
||||||
for (i=1; i<16; i++) {
|
|
||||||
p = pointAdd(out[i-1][0], out[i-1][1], dbl[0], dbl[1]);
|
|
||||||
out[i][0] <== p[0];
|
|
||||||
out[i][1] <== p[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
|
|
||||||
include "escalarmul.circom";
|
|
||||||
|
|
||||||
component Pedersen(n) {
|
|
||||||
signal input in[n];
|
|
||||||
signal output out[2];
|
|
||||||
|
|
||||||
var nexps = ((n-1) \ 253) + 1;
|
|
||||||
var nlastbits = n - (nexps-1)*253;
|
|
||||||
|
|
||||||
component escalarMuls[nexps];
|
|
||||||
|
|
||||||
var PBASE = [
|
|
||||||
[17777552123799933955779906779655732241715742912184938656739573121738514868268,
|
|
||||||
2626589144620713026669568689430873010625803728049924121243784502389097019475],
|
|
||||||
[17777552123799933955779906779655732241715742912184938656739573121738514868268,
|
|
||||||
2626589144620713026669568689430873010625803728049924121243784502389097019475],
|
|
||||||
[17777552123799933955779906779655732241715742912184938656739573121738514868268,
|
|
||||||
2626589144620713026669568689430873010625803728049924121243784502389097019475],
|
|
||||||
[17777552123799933955779906779655732241715742912184938656739573121738514868268,
|
|
||||||
2626589144620713026669568689430873010625803728049924121243784502389097019475],
|
|
||||||
[17777552123799933955779906779655732241715742912184938656739573121738514868268,
|
|
||||||
2626589144620713026669568689430873010625803728049924121243784502389097019475]
|
|
||||||
];
|
|
||||||
|
|
||||||
var i;
|
|
||||||
var j;
|
|
||||||
for (i=0; i<nexps; i++) {
|
|
||||||
var nexpbits = (i == nexps-1) ? nlastbits : 253;
|
|
||||||
escalarMuls[i] = EscalarMul(nexpbits, PBASE[i][0], PBAS[i][1]);
|
|
||||||
|
|
||||||
for (j=0; j<nexpbits; j++) {
|
|
||||||
escalarMuls[i].in[j] <== in[253*i + j];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i==0) {
|
|
||||||
escalarMuls[i].inp[0] <== 0;
|
|
||||||
escalarMuls[i].inp[1] <== 0;
|
|
||||||
} else {
|
|
||||||
escalarMuls[i].inp[0] <== escalarMuls[i-1].out[0];
|
|
||||||
escalarMuls[i].inp[1] <== escalarMuls[i-1].out[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
escalarMuls[nexps-1].out[0] ==> out[0];
|
|
||||||
escalarMuls[nexps-1].out[1] ==> out[1];
|
|
||||||
}
|
|
||||||
32
circuits/aliascheck.circom
Normal file
32
circuits/aliascheck.circom
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "compconstant.circom";
|
||||||
|
|
||||||
|
|
||||||
|
template AliasCheck() {
|
||||||
|
|
||||||
|
signal input in[254];
|
||||||
|
|
||||||
|
component compConstant = CompConstant(-1);
|
||||||
|
|
||||||
|
for (var i=0; i<254; i++) in[i] ==> compConstant.in[i];
|
||||||
|
|
||||||
|
compConstant.out === 0;
|
||||||
|
}
|
||||||
79
circuits/babyjub.circom
Normal file
79
circuits/babyjub.circom
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template BabyAdd() {
|
||||||
|
signal input x1;
|
||||||
|
signal input y1;
|
||||||
|
signal input x2;
|
||||||
|
signal input y2;
|
||||||
|
signal output xout;
|
||||||
|
signal output yout;
|
||||||
|
|
||||||
|
signal beta;
|
||||||
|
signal gamma;
|
||||||
|
signal delta;
|
||||||
|
signal tau;
|
||||||
|
|
||||||
|
var a = 168700;
|
||||||
|
var d = 168696;
|
||||||
|
|
||||||
|
beta <== x1*y2;
|
||||||
|
gamma <== y1*x2;
|
||||||
|
delta <== (-a*x1+y1)*(x2 + y2);
|
||||||
|
tau <== beta * gamma;
|
||||||
|
|
||||||
|
xout <-- (beta + gamma) / (1+ d*tau);
|
||||||
|
(1+ d*tau) * xout === (beta + gamma);
|
||||||
|
|
||||||
|
yout <-- (delta + a*beta - gamma) / (1-d*tau);
|
||||||
|
(1-d*tau)*yout === (delta + a*beta - gamma);
|
||||||
|
}
|
||||||
|
|
||||||
|
template BabyDbl() {
|
||||||
|
signal input x;
|
||||||
|
signal input y;
|
||||||
|
signal output xout;
|
||||||
|
signal output yout;
|
||||||
|
|
||||||
|
component adder = BabyAdd();
|
||||||
|
adder.x1 <== x;
|
||||||
|
adder.y1 <== y;
|
||||||
|
adder.x2 <== x;
|
||||||
|
adder.y2 <== y;
|
||||||
|
|
||||||
|
adder.xout ==> xout;
|
||||||
|
adder.yout ==> yout;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template BabyCheck() {
|
||||||
|
signal input x;
|
||||||
|
signal input y;
|
||||||
|
|
||||||
|
signal x2;
|
||||||
|
signal y2;
|
||||||
|
|
||||||
|
var a = 168700;
|
||||||
|
var d = 168696;
|
||||||
|
|
||||||
|
x2 <== x*x;
|
||||||
|
y2 <== y*y;
|
||||||
|
|
||||||
|
a*x2 + y2 === 1 + d*x2*y2;
|
||||||
|
}
|
||||||
71
circuits/binsub.circom
Normal file
71
circuits/binsub.circom
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
This component creates a binary substraction.
|
||||||
|
|
||||||
|
|
||||||
|
Main Constraint:
|
||||||
|
(in[0][0] * 2^0 + in[0][1] * 2^1 + ..... + in[0][n-1] * 2^(n-1)) +
|
||||||
|
+ 2^n
|
||||||
|
- (in[1][0] * 2^0 + in[1][1] * 2^1 + ..... + in[1][n-1] * 2^(n-1))
|
||||||
|
===
|
||||||
|
out[0] * 2^0 + out[1] * 2^1 + + out[n-1] *2^(n-1) + aux
|
||||||
|
|
||||||
|
|
||||||
|
out[0] * (out[0] - 1) === 0
|
||||||
|
out[1] * (out[0] - 1) === 0
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
out[n-1] * (out[n-1] - 1) === 0
|
||||||
|
aux * (aux-1) == 0
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
template BinSub(n) {
|
||||||
|
signal input in[2][n];
|
||||||
|
signal output out[n];
|
||||||
|
|
||||||
|
signal aux;
|
||||||
|
|
||||||
|
var lin = 2**n;
|
||||||
|
var lout = 0;
|
||||||
|
|
||||||
|
for (var i=0; i<n; i++) {
|
||||||
|
lin = lin + in[0][i]*(2**i);
|
||||||
|
lin = lin - in[1][i]*(2**i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i=0; i<n; i++) {
|
||||||
|
out[i] <-- (lin >> i) & 1;
|
||||||
|
|
||||||
|
// Ensure out is binary
|
||||||
|
out[i] * (out[i] - 1) === 0;
|
||||||
|
|
||||||
|
lout = lout + out[i]*(2**i);
|
||||||
|
}
|
||||||
|
|
||||||
|
aux <-- (lin >> n) & 1;
|
||||||
|
aux*(aux-1) === 0;
|
||||||
|
lout = lout + aux*(2**n);
|
||||||
|
|
||||||
|
// Ensure the sum;
|
||||||
|
lin === lout;
|
||||||
|
}
|
||||||
93
circuits/binsum.circom
Normal file
93
circuits/binsum.circom
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Binary Sum
|
||||||
|
==========
|
||||||
|
|
||||||
|
This component creates a binary sum componet of ops operands and n bits each operand.
|
||||||
|
|
||||||
|
e is Number of carries: Depends on the number of operands in the input.
|
||||||
|
|
||||||
|
Main Constraint:
|
||||||
|
in[0][0] * 2^0 + in[0][1] * 2^1 + ..... + in[0][n-1] * 2^(n-1) +
|
||||||
|
+ in[1][0] * 2^0 + in[1][1] * 2^1 + ..... + in[1][n-1] * 2^(n-1) +
|
||||||
|
+ ..
|
||||||
|
+ in[ops-1][0] * 2^0 + in[ops-1][1] * 2^1 + ..... + in[ops-1][n-1] * 2^(n-1) +
|
||||||
|
===
|
||||||
|
out[0] * 2^0 + out[1] * 2^1 + + out[n+e-1] *2(n+e-1)
|
||||||
|
|
||||||
|
To waranty binary outputs:
|
||||||
|
|
||||||
|
out[0] * (out[0] - 1) === 0
|
||||||
|
out[1] * (out[0] - 1) === 0
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
out[n+e-1] * (out[n+e-1] - 1) == 0
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
This function calculates the number of extra bits in the output to do the full sum.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function nbits(a) {
|
||||||
|
var n = 1;
|
||||||
|
var r = 0;
|
||||||
|
while (n-1<a) {
|
||||||
|
r++;
|
||||||
|
n *= 2;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template BinSum(n, ops) {
|
||||||
|
var nout = nbits((2**n -1)*ops);
|
||||||
|
signal input in[ops][n];
|
||||||
|
signal output out[nout];
|
||||||
|
|
||||||
|
var lin = 0;
|
||||||
|
var lout = 0;
|
||||||
|
|
||||||
|
var k;
|
||||||
|
var j;
|
||||||
|
|
||||||
|
for (k=0; k<n; k++) {
|
||||||
|
for (j=0; j<ops; j++) {
|
||||||
|
lin += in[j][k] * 2**k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k=0; k<nout; k++) {
|
||||||
|
out[k] <-- (lin >> k) & 1;
|
||||||
|
|
||||||
|
// Ensure out is binary
|
||||||
|
out[k] * (out[k] - 1) === 0;
|
||||||
|
|
||||||
|
lout += out[k] * 2**k;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the sum;
|
||||||
|
|
||||||
|
lin === lout;
|
||||||
|
}
|
||||||
101
circuits/bitify.circom
Normal file
101
circuits/bitify.circom
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "comparators.circom";
|
||||||
|
include "aliascheck.circom";
|
||||||
|
|
||||||
|
|
||||||
|
template Num2Bits(n) {
|
||||||
|
signal input in;
|
||||||
|
signal output out[n];
|
||||||
|
var lc1=0;
|
||||||
|
|
||||||
|
for (var i = 0; i<n; i++) {
|
||||||
|
out[i] <-- (in >> i) & 1;
|
||||||
|
out[i] * (out[i] -1 ) === 0;
|
||||||
|
lc1 += out[i] * 2**i;
|
||||||
|
}
|
||||||
|
|
||||||
|
lc1 === in;
|
||||||
|
}
|
||||||
|
|
||||||
|
template Num2Bits_strict() {
|
||||||
|
signal input in;
|
||||||
|
signal output out[254];
|
||||||
|
|
||||||
|
component aliasCheck = AliasCheck();
|
||||||
|
component n2b = Num2Bits(254);
|
||||||
|
in ==> n2b.in;
|
||||||
|
|
||||||
|
for (var i=0; i<254; i++) {
|
||||||
|
n2b.out[i] ==> out[i];
|
||||||
|
n2b.out[i] ==> aliasCheck.in[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template Bits2Num(n) {
|
||||||
|
signal input in[n];
|
||||||
|
signal output out;
|
||||||
|
var lc1=0;
|
||||||
|
|
||||||
|
for (var i = 0; i<n; i++) {
|
||||||
|
lc1 += in[i] * 2**i;
|
||||||
|
}
|
||||||
|
|
||||||
|
lc1 ==> out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template Bits2Num_strict() {
|
||||||
|
signal input in[n];
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
component aliasCheck = AliasCheck();
|
||||||
|
component b2n = Bits2Num(254);
|
||||||
|
|
||||||
|
for (var i=0; i<254; i++) {
|
||||||
|
in[i] ==> b2n.in[i];
|
||||||
|
in[i] ==> aliasCheck.in[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
b2n.out ==> out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template Num2BitsNeg(n) {
|
||||||
|
signal input in;
|
||||||
|
signal output out[n];
|
||||||
|
var lc1=0;
|
||||||
|
|
||||||
|
component isZero;
|
||||||
|
|
||||||
|
isZero = IsZero();
|
||||||
|
|
||||||
|
var neg = n == 0 ? 0 : 2**n - in;
|
||||||
|
|
||||||
|
for (var i = 0; i<n; i++) {
|
||||||
|
out[i] <-- (neg >> i) & 1;
|
||||||
|
out[i] * (out[i] -1 ) === 0;
|
||||||
|
lc1 += out[i] * 2**i;
|
||||||
|
}
|
||||||
|
|
||||||
|
in ==> isZero.in;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
lc1 + isZero.out * 2**n === 2**n - in;
|
||||||
|
}
|
||||||
85
circuits/comparators.circom
Normal file
85
circuits/comparators.circom
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "bitify.circom";
|
||||||
|
include "binsum.circom";
|
||||||
|
|
||||||
|
template IsZero() {
|
||||||
|
signal input in;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
signal inv;
|
||||||
|
|
||||||
|
inv <-- in!=0 ? 1/in : 0;
|
||||||
|
|
||||||
|
out <== -in*inv +1;
|
||||||
|
in*out === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template IsEqual() {
|
||||||
|
signal input in[2];
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
component isz = IsZero();
|
||||||
|
|
||||||
|
in[1] - in[0] ==> isz.in;
|
||||||
|
|
||||||
|
isz.out ==> out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template ForceEqualIfEnabled() {
|
||||||
|
signal input enabled;
|
||||||
|
signal input in[2];
|
||||||
|
|
||||||
|
component isz = IsZero();
|
||||||
|
|
||||||
|
in[1] - in[0] ==> isz.in;
|
||||||
|
|
||||||
|
(1 - isz.out)*enabled === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// N is the number of bits the input have.
|
||||||
|
// The MSF is the sign bit.
|
||||||
|
template LessThan(n) {
|
||||||
|
signal input in[2];
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
component num2Bits0;
|
||||||
|
component num2Bits1;
|
||||||
|
|
||||||
|
component adder;
|
||||||
|
|
||||||
|
adder = BinSum(n, 2);
|
||||||
|
|
||||||
|
num2Bits0 = Num2Bits(n);
|
||||||
|
num2Bits1 = Num2BitsNeg(n);
|
||||||
|
|
||||||
|
in[0] ==> num2Bits0.in;
|
||||||
|
in[1] ==> num2Bits1.in;
|
||||||
|
|
||||||
|
var i;
|
||||||
|
for (i=0;i<n;i++) {
|
||||||
|
num2Bits0.out[i] ==> adder.in[0][i];
|
||||||
|
num2Bits1.out[i] ==> adder.in[1][i];
|
||||||
|
}
|
||||||
|
|
||||||
|
adder.out[n-1] ==> out;
|
||||||
|
}
|
||||||
74
circuits/compconstant.circom
Normal file
74
circuits/compconstant.circom
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "bitify.circom";
|
||||||
|
|
||||||
|
// Returns 1 if in (in binary) > ct
|
||||||
|
|
||||||
|
template CompConstant(ct) {
|
||||||
|
signal input in[254];
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
signal parts[127];
|
||||||
|
signal sout;
|
||||||
|
|
||||||
|
var clsb;
|
||||||
|
var cmsb;
|
||||||
|
var slsb;
|
||||||
|
var smsb;
|
||||||
|
|
||||||
|
var sum=0;
|
||||||
|
|
||||||
|
var b = (1 << 128) -1;
|
||||||
|
var a = 1;
|
||||||
|
var e = 1;
|
||||||
|
var i;
|
||||||
|
|
||||||
|
for (i=0;i<127; i++) {
|
||||||
|
clsb = (ct >> (i*2)) & 1;
|
||||||
|
cmsb = (ct >> (i*2+1)) & 1;
|
||||||
|
slsb = in[i*2];
|
||||||
|
smsb = in[i*2+1];
|
||||||
|
|
||||||
|
|
||||||
|
if ((cmsb==0)&(clsb==0)) {
|
||||||
|
parts[i] <== -b*smsb*slsb + b*smsb + b*slsb;
|
||||||
|
} else if ((cmsb==0)&(clsb==1)) {
|
||||||
|
parts[i] <== a*smsb*slsb - a*slsb + b*smsb - a*smsb + a;
|
||||||
|
} else if ((cmsb==1)&(clsb==0)) {
|
||||||
|
parts[i] <== b*smsb*slsb - a*smsb + a;
|
||||||
|
} else {
|
||||||
|
parts[i] <== -a*smsb*slsb + a;
|
||||||
|
}
|
||||||
|
|
||||||
|
sum = sum + parts[i];
|
||||||
|
|
||||||
|
b = b -e;
|
||||||
|
a = a +e;
|
||||||
|
e = e*2;
|
||||||
|
}
|
||||||
|
|
||||||
|
sout <== sum;
|
||||||
|
|
||||||
|
component num2bits = Num2Bits(135);
|
||||||
|
|
||||||
|
num2bits.in <== sout;
|
||||||
|
|
||||||
|
out <== num2bits.out[127];
|
||||||
|
}
|
||||||
138
circuits/eddsa.circom
Normal file
138
circuits/eddsa.circom
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "compconstant.circom";
|
||||||
|
include "pointbits.circom";
|
||||||
|
include "pedersen.circom";
|
||||||
|
include "escalarmulany.circom";
|
||||||
|
include "escalarmulfix.circom";
|
||||||
|
|
||||||
|
template EdDSAVerifier(n) {
|
||||||
|
signal input msg[n];
|
||||||
|
|
||||||
|
signal input A[256];
|
||||||
|
signal input R8[256];
|
||||||
|
signal input S[256];
|
||||||
|
|
||||||
|
signal Ax;
|
||||||
|
signal Ay;
|
||||||
|
|
||||||
|
signal R8x;
|
||||||
|
signal R8y;
|
||||||
|
|
||||||
|
var i;
|
||||||
|
|
||||||
|
// Ensure S<Subgroup Order
|
||||||
|
|
||||||
|
component compConstant = CompConstant(2736030358979909402780800718157159386076813972158567259200215660948447373040);
|
||||||
|
|
||||||
|
for (i=0; i<254; i++) {
|
||||||
|
S[i] ==> compConstant.in[i];
|
||||||
|
}
|
||||||
|
compConstant.out === 0;
|
||||||
|
S[254] === 0;
|
||||||
|
S[255] === 0;
|
||||||
|
|
||||||
|
// Convert A to Field elements (And verify A)
|
||||||
|
|
||||||
|
component bits2pointA = Bits2Point_Strict();
|
||||||
|
|
||||||
|
for (i=0; i<256; i++) {
|
||||||
|
bits2pointA.in[i] <== A[i];
|
||||||
|
}
|
||||||
|
Ax <== bits2pointA.out[0];
|
||||||
|
Ay <== bits2pointA.out[1];
|
||||||
|
|
||||||
|
// Convert R8 to Field elements (And verify R8)
|
||||||
|
|
||||||
|
component bits2pointR8 = Bits2Point_Strict();
|
||||||
|
|
||||||
|
for (i=0; i<256; i++) {
|
||||||
|
bits2pointR8.in[i] <== R8[i];
|
||||||
|
}
|
||||||
|
R8x <== bits2pointR8.out[0];
|
||||||
|
R8y <== bits2pointR8.out[1];
|
||||||
|
|
||||||
|
// Calculate the h = H(R,A, msg)
|
||||||
|
|
||||||
|
component hash = Pedersen(512+n);
|
||||||
|
|
||||||
|
for (i=0; i<256; i++) {
|
||||||
|
hash.in[i] <== R8[i];
|
||||||
|
hash.in[256+i] <== A[i];
|
||||||
|
}
|
||||||
|
for (i=0; i<n; i++) {
|
||||||
|
hash.in[512+i] <== msg[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
component point2bitsH = Point2Bits_Strict();
|
||||||
|
point2bitsH.in[0] <== hash.out[0];
|
||||||
|
point2bitsH.in[1] <== hash.out[1];
|
||||||
|
|
||||||
|
// Calculate second part of the right side: right2 = h*8*A
|
||||||
|
|
||||||
|
// Multiply by 8 by adding it 3 times. This also ensure that the result is in
|
||||||
|
// the subgroup.
|
||||||
|
component dbl1 = BabyDbl();
|
||||||
|
dbl1.x <== Ax;
|
||||||
|
dbl1.y <== Ay;
|
||||||
|
component dbl2 = BabyDbl();
|
||||||
|
dbl2.x <== dbl1.xout;
|
||||||
|
dbl2.y <== dbl1.yout;
|
||||||
|
component dbl3 = BabyDbl();
|
||||||
|
dbl3.x <== dbl2.xout;
|
||||||
|
dbl3.y <== dbl2.yout;
|
||||||
|
|
||||||
|
// We check that A is not zero.
|
||||||
|
component isZero = IsZero();
|
||||||
|
isZero.in <== dbl3.x;
|
||||||
|
isZero.out === 0;
|
||||||
|
|
||||||
|
component mulAny = EscalarMulAny(256);
|
||||||
|
for (i=0; i<256; i++) {
|
||||||
|
mulAny.e[i] <== point2bitsH.out[i];
|
||||||
|
}
|
||||||
|
mulAny.p[0] <== dbl3.xout;
|
||||||
|
mulAny.p[1] <== dbl3.yout;
|
||||||
|
|
||||||
|
|
||||||
|
// Compute the right side: right = R8 + right2
|
||||||
|
|
||||||
|
component addRight = BabyAdd();
|
||||||
|
addRight.x1 <== R8x;
|
||||||
|
addRight.y1 <== R8y;
|
||||||
|
addRight.x2 <== mulAny.out[0];
|
||||||
|
addRight.y2 <== mulAny.out[1];
|
||||||
|
|
||||||
|
// Calculate left side of equation left = S*B8
|
||||||
|
|
||||||
|
var BASE8 = [
|
||||||
|
17777552123799933955779906779655732241715742912184938656739573121738514868268,
|
||||||
|
2626589144620713026669568689430873010625803728049924121243784502389097019475
|
||||||
|
];
|
||||||
|
component mulFix = EscalarMulFix(256, BASE8);
|
||||||
|
for (i=0; i<256; i++) {
|
||||||
|
mulFix.e[i] <== S[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the comparation left == right
|
||||||
|
|
||||||
|
mulFix.out[0] === addRight.xout;
|
||||||
|
mulFix.out[1] === addRight.yout;
|
||||||
|
}
|
||||||
123
circuits/eddsamimc.circom
Normal file
123
circuits/eddsamimc.circom
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "compconstant.circom";
|
||||||
|
include "pointbits.circom";
|
||||||
|
include "mimc.circom";
|
||||||
|
include "bitify.circom";
|
||||||
|
include "escalarmulany.circom";
|
||||||
|
include "escalarmulfix.circom";
|
||||||
|
|
||||||
|
template EdDSAMiMCVerifier() {
|
||||||
|
signal input enabled;
|
||||||
|
signal input Ax;
|
||||||
|
signal input Ay;
|
||||||
|
|
||||||
|
signal input S;
|
||||||
|
signal input R8x;
|
||||||
|
signal input R8y;
|
||||||
|
|
||||||
|
signal input M;
|
||||||
|
|
||||||
|
var i;
|
||||||
|
|
||||||
|
// Ensure S<Subgroup Order
|
||||||
|
|
||||||
|
component snum2bits = Num2Bits(253);
|
||||||
|
snum2bits.in <== S;
|
||||||
|
|
||||||
|
component compConstant = CompConstant(2736030358979909402780800718157159386076813972158567259200215660948447373040);
|
||||||
|
|
||||||
|
for (i=0; i<253; i++) {
|
||||||
|
snum2bits.out[i] ==> compConstant.in[i];
|
||||||
|
}
|
||||||
|
compConstant.in[253] <== 0;
|
||||||
|
compConstant.out === 0;
|
||||||
|
|
||||||
|
// Calculate the h = H(R,A, msg)
|
||||||
|
|
||||||
|
component hash = MultiMiMC7(5, 91);
|
||||||
|
hash.in[0] <== R8x;
|
||||||
|
hash.in[1] <== R8y;
|
||||||
|
hash.in[2] <== Ax;
|
||||||
|
hash.in[3] <== Ay;
|
||||||
|
hash.in[4] <== M;
|
||||||
|
hash.k <== 0;
|
||||||
|
|
||||||
|
component h2bits = Num2Bits_strict();
|
||||||
|
h2bits.in <== hash.out;
|
||||||
|
|
||||||
|
// Calculate second part of the right side: right2 = h*8*A
|
||||||
|
|
||||||
|
// Multiply by 8 by adding it 3 times. This also ensure that the result is in
|
||||||
|
// the subgroup.
|
||||||
|
component dbl1 = BabyDbl();
|
||||||
|
dbl1.x <== Ax;
|
||||||
|
dbl1.y <== Ay;
|
||||||
|
component dbl2 = BabyDbl();
|
||||||
|
dbl2.x <== dbl1.xout;
|
||||||
|
dbl2.y <== dbl1.yout;
|
||||||
|
component dbl3 = BabyDbl();
|
||||||
|
dbl3.x <== dbl2.xout;
|
||||||
|
dbl3.y <== dbl2.yout;
|
||||||
|
|
||||||
|
// We check that A is not zero.
|
||||||
|
component isZero = IsZero();
|
||||||
|
isZero.in <== dbl3.x;
|
||||||
|
isZero.out === 0;
|
||||||
|
|
||||||
|
component mulAny = EscalarMulAny(254);
|
||||||
|
for (i=0; i<254; i++) {
|
||||||
|
mulAny.e[i] <== h2bits.out[i];
|
||||||
|
}
|
||||||
|
mulAny.p[0] <== dbl3.xout;
|
||||||
|
mulAny.p[1] <== dbl3.yout;
|
||||||
|
|
||||||
|
|
||||||
|
// Compute the right side: right = R8 + right2
|
||||||
|
|
||||||
|
component addRight = BabyAdd();
|
||||||
|
addRight.x1 <== R8x;
|
||||||
|
addRight.y1 <== R8y;
|
||||||
|
addRight.x2 <== mulAny.out[0];
|
||||||
|
addRight.y2 <== mulAny.out[1];
|
||||||
|
|
||||||
|
// Calculate left side of equation left = S*B8
|
||||||
|
|
||||||
|
var BASE8 = [
|
||||||
|
17777552123799933955779906779655732241715742912184938656739573121738514868268,
|
||||||
|
2626589144620713026669568689430873010625803728049924121243784502389097019475
|
||||||
|
];
|
||||||
|
component mulFix = EscalarMulFix(253, BASE8);
|
||||||
|
for (i=0; i<253; i++) {
|
||||||
|
mulFix.e[i] <== snum2bits.out[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the comparation left == right if enabled;
|
||||||
|
|
||||||
|
component eqCheckX = ForceEqualIfEnabled();
|
||||||
|
eqCheckX.enabled <== enabled;
|
||||||
|
eqCheckX.in[0] <== mulFix.out[0];
|
||||||
|
eqCheckX.in[1] <== addRight.xout;
|
||||||
|
|
||||||
|
component eqCheckY = ForceEqualIfEnabled();
|
||||||
|
eqCheckY.enabled <== enabled;
|
||||||
|
eqCheckY.in[0] <== mulFix.out[1];
|
||||||
|
eqCheckY.in[1] <== addRight.yout;
|
||||||
|
}
|
||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
┏━━━━━━━━━━━┓
|
┏━━━━━━━━━━━┓
|
||||||
192
circuits/escalarmulany.circom
Normal file
192
circuits/escalarmulany.circom
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "montgomery.circom";
|
||||||
|
include "babyjub.circom";
|
||||||
|
|
||||||
|
template Multiplexor2() {
|
||||||
|
signal input sel;
|
||||||
|
signal input in[2][2];
|
||||||
|
signal output out[2];
|
||||||
|
|
||||||
|
out[0] <== (in[1][0] - in[0][0])*sel + in[0][0];
|
||||||
|
out[1] <== (in[1][1] - in[0][1])*sel + in[0][1];
|
||||||
|
}
|
||||||
|
|
||||||
|
template BitElementMulAny() {
|
||||||
|
signal input sel;
|
||||||
|
signal input dblIn[2];
|
||||||
|
signal input addIn[2];
|
||||||
|
signal output dblOut[2];
|
||||||
|
signal output addOut[2];
|
||||||
|
|
||||||
|
component doubler = MontgomeryDouble();
|
||||||
|
component adder = MontgomeryAdd();
|
||||||
|
component selector = Multiplexor2();
|
||||||
|
|
||||||
|
|
||||||
|
sel ==> selector.sel;
|
||||||
|
|
||||||
|
dblIn[0] ==> doubler.in[0];
|
||||||
|
dblIn[1] ==> doubler.in[1];
|
||||||
|
doubler.out[0] ==> adder.in1[0];
|
||||||
|
doubler.out[1] ==> adder.in1[1];
|
||||||
|
addIn[0] ==> adder.in2[0];
|
||||||
|
addIn[1] ==> adder.in2[1];
|
||||||
|
addIn[0] ==> selector.in[0][0];
|
||||||
|
addIn[1] ==> selector.in[0][1];
|
||||||
|
adder.out[0] ==> selector.in[1][0];
|
||||||
|
adder.out[1] ==> selector.in[1][1];
|
||||||
|
|
||||||
|
doubler.out[0] ==> dblOut[0];
|
||||||
|
doubler.out[1] ==> dblOut[1];
|
||||||
|
selector.out[0] ==> addOut[0];
|
||||||
|
selector.out[1] ==> addOut[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// p is montgomery point
|
||||||
|
// n must be <= 248
|
||||||
|
// returns out in twisted edwards
|
||||||
|
// Double is in montgomery to be linked;
|
||||||
|
|
||||||
|
template SegmentMulAny(n) {
|
||||||
|
signal input e[n];
|
||||||
|
signal input p[2];
|
||||||
|
signal output out[2];
|
||||||
|
signal output dbl[2];
|
||||||
|
|
||||||
|
component bits[n-1];
|
||||||
|
|
||||||
|
component e2m = Edwards2Montgomery();
|
||||||
|
|
||||||
|
p[0] ==> e2m.in[0];
|
||||||
|
p[1] ==> e2m.in[1];
|
||||||
|
|
||||||
|
var i;
|
||||||
|
|
||||||
|
bits[0] = BitElementMulAny();
|
||||||
|
e2m.out[0] ==> bits[0].dblIn[0]
|
||||||
|
e2m.out[1] ==> bits[0].dblIn[1]
|
||||||
|
e2m.out[0] ==> bits[0].addIn[0]
|
||||||
|
e2m.out[1] ==> bits[0].addIn[1]
|
||||||
|
e[1] ==> bits[0].sel;
|
||||||
|
|
||||||
|
for (i=1; i<n-1; i++) {
|
||||||
|
bits[i] = BitElementMulAny();
|
||||||
|
|
||||||
|
bits[i-1].dblOut[0] ==> bits[i].dblIn[0]
|
||||||
|
bits[i-1].dblOut[1] ==> bits[i].dblIn[1]
|
||||||
|
bits[i-1].addOut[0] ==> bits[i].addIn[0]
|
||||||
|
bits[i-1].addOut[1] ==> bits[i].addIn[1]
|
||||||
|
e[i+1] ==> bits[i].sel;
|
||||||
|
}
|
||||||
|
|
||||||
|
bits[n-2].dblOut[0] ==> dbl[0];
|
||||||
|
bits[n-2].dblOut[1] ==> dbl[1];
|
||||||
|
|
||||||
|
component m2e = Montgomery2Edwards();
|
||||||
|
|
||||||
|
bits[n-2].addOut[0] ==> m2e.in[0];
|
||||||
|
bits[n-2].addOut[1] ==> m2e.in[1];
|
||||||
|
|
||||||
|
component eadder = BabyAdd();
|
||||||
|
|
||||||
|
m2e.out[0] ==> eadder.x1;
|
||||||
|
m2e.out[1] ==> eadder.y1;
|
||||||
|
-p[0] ==> eadder.x2;
|
||||||
|
p[1] ==> eadder.y2;
|
||||||
|
|
||||||
|
component lastSel = Multiplexor2();
|
||||||
|
|
||||||
|
e[0] ==> lastSel.sel;
|
||||||
|
eadder.xout ==> lastSel.in[0][0];
|
||||||
|
eadder.yout ==> lastSel.in[0][1];
|
||||||
|
m2e.out[0] ==> lastSel.in[1][0];
|
||||||
|
m2e.out[1] ==> lastSel.in[1][1];
|
||||||
|
|
||||||
|
lastSel.out[0] ==> out[0];
|
||||||
|
lastSel.out[1] ==> out[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function assumes that p is in the subgroup and it is different to 0
|
||||||
|
|
||||||
|
template EscalarMulAny(n) {
|
||||||
|
signal input e[n]; // Input in binary format
|
||||||
|
signal input p[2]; // Point (Twisted format)
|
||||||
|
signal output out[2]; // Point (Twisted format)
|
||||||
|
|
||||||
|
var nsegments = (n-1)\148 +1;
|
||||||
|
var nlastsegment = n - (nsegments-1)*148;
|
||||||
|
|
||||||
|
component segments[nsegments];
|
||||||
|
component doublers[nsegments-1];
|
||||||
|
component m2e[nsegments-1];
|
||||||
|
component adders[nsegments-1];
|
||||||
|
|
||||||
|
var s;
|
||||||
|
var i;
|
||||||
|
var nseg;
|
||||||
|
|
||||||
|
for (s=0; s<nsegments; s++) {
|
||||||
|
|
||||||
|
nseg = (s < nsegments-1) ? 148 : nlastsegment;
|
||||||
|
|
||||||
|
segments[s] = SegmentMulAny(nseg);
|
||||||
|
|
||||||
|
for (i=0; i<nseg; i++) {
|
||||||
|
e[s*148+i] ==> segments[s].e[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s==0) {
|
||||||
|
p[0] ==> segments[s].p[0];
|
||||||
|
p[1] ==> segments[s].p[1];
|
||||||
|
} else {
|
||||||
|
doublers[s-1] = MontgomeryDouble();
|
||||||
|
m2e[s-1] = Montgomery2Edwards();
|
||||||
|
adders[s-1] = BabyAdd();
|
||||||
|
|
||||||
|
segments[s-1].dbl[0] ==> doublers[s-1].in[0];
|
||||||
|
segments[s-1].dbl[1] ==> doublers[s-1].in[1];
|
||||||
|
|
||||||
|
doublers[s-1].out[0] ==> m2e[s-1].in[0];
|
||||||
|
doublers[s-1].out[1] ==> m2e[s-1].in[1];
|
||||||
|
|
||||||
|
m2e[s-1].out[0] ==> segments[s].p[0];
|
||||||
|
m2e[s-1].out[1] ==> segments[s].p[1];
|
||||||
|
|
||||||
|
if (s==1) {
|
||||||
|
segments[s-1].out[0] ==> adders[s-1].x1;
|
||||||
|
segments[s-1].out[1] ==> adders[s-1].y1;
|
||||||
|
} else {
|
||||||
|
adders[s-2].xout ==> adders[s-1].x1;
|
||||||
|
adders[s-2].yout ==> adders[s-1].y1;
|
||||||
|
}
|
||||||
|
segments[s].out[0] ==> adders[s-1].x2;
|
||||||
|
segments[s].out[1] ==> adders[s-1].y2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nsegments == 1) {
|
||||||
|
segments[0].out[0] ==> out[0];
|
||||||
|
segments[0].out[1] ==> out[1];
|
||||||
|
} else {
|
||||||
|
adders[nsegments-2].xout ==> out[0];
|
||||||
|
adders[nsegments-2].yout ==> out[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
277
circuits/escalarmulfix.circom
Normal file
277
circuits/escalarmulfix.circom
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "mux3.circom";
|
||||||
|
include "montgomery.circom";
|
||||||
|
include "babyjub.circom";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Window of 3 elements, it calculates
|
||||||
|
out = base + base*in[0] + 2*base*in[1] + 4*base*in[2]
|
||||||
|
out4 = 4*base
|
||||||
|
|
||||||
|
The result should be compensated.
|
||||||
|
*/
|
||||||
|
template WindowMulFix() {
|
||||||
|
signal input in[3];
|
||||||
|
signal input base[2];
|
||||||
|
signal output out[2];
|
||||||
|
signal output out8[2]; // Returns 8*Base (To be linked)
|
||||||
|
|
||||||
|
component mux = MultiMux3(2);
|
||||||
|
|
||||||
|
mux.s[0] <== in[0];
|
||||||
|
mux.s[1] <== in[1];
|
||||||
|
mux.s[2] <== in[2];
|
||||||
|
|
||||||
|
component dbl2 = MontgomeryDouble();
|
||||||
|
component adr3 = MontgomeryAdd();
|
||||||
|
component adr4 = MontgomeryAdd();
|
||||||
|
component adr5 = MontgomeryAdd();
|
||||||
|
component adr6 = MontgomeryAdd();
|
||||||
|
component adr7 = MontgomeryAdd();
|
||||||
|
component adr8 = MontgomeryAdd();
|
||||||
|
|
||||||
|
// in[0] -> 1*BASE
|
||||||
|
|
||||||
|
mux.c[0][0] <== base[0];
|
||||||
|
mux.c[1][0] <== base[1];
|
||||||
|
|
||||||
|
// in[1] -> 2*BASE
|
||||||
|
dbl2.in[0] <== base[0];
|
||||||
|
dbl2.in[1] <== base[1];
|
||||||
|
mux.c[0][1] <== dbl2.out[0];
|
||||||
|
mux.c[1][1] <== dbl2.out[1];
|
||||||
|
|
||||||
|
// in[2] -> 3*BASE
|
||||||
|
adr3.in1[0] <== base[0];
|
||||||
|
adr3.in1[1] <== base[1];
|
||||||
|
adr3.in2[0] <== dbl2.out[0];
|
||||||
|
adr3.in2[1] <== dbl2.out[1];
|
||||||
|
mux.c[0][2] <== adr3.out[0];
|
||||||
|
mux.c[1][2] <== adr3.out[1];
|
||||||
|
|
||||||
|
// in[3] -> 4*BASE
|
||||||
|
adr4.in1[0] <== base[0];
|
||||||
|
adr4.in1[1] <== base[1];
|
||||||
|
adr4.in2[0] <== adr3.out[0];
|
||||||
|
adr4.in2[1] <== adr3.out[1];
|
||||||
|
mux.c[0][3] <== adr4.out[0];
|
||||||
|
mux.c[1][3] <== adr4.out[1];
|
||||||
|
|
||||||
|
// in[4] -> 5*BASE
|
||||||
|
adr5.in1[0] <== base[0];
|
||||||
|
adr5.in1[1] <== base[1];
|
||||||
|
adr5.in2[0] <== adr4.out[0];
|
||||||
|
adr5.in2[1] <== adr4.out[1];
|
||||||
|
mux.c[0][4] <== adr5.out[0];
|
||||||
|
mux.c[1][4] <== adr5.out[1];
|
||||||
|
|
||||||
|
// in[5] -> 6*BASE
|
||||||
|
adr6.in1[0] <== base[0];
|
||||||
|
adr6.in1[1] <== base[1];
|
||||||
|
adr6.in2[0] <== adr5.out[0];
|
||||||
|
adr6.in2[1] <== adr5.out[1];
|
||||||
|
mux.c[0][5] <== adr6.out[0];
|
||||||
|
mux.c[1][5] <== adr6.out[1];
|
||||||
|
|
||||||
|
// in[6] -> 7*BASE
|
||||||
|
adr7.in1[0] <== base[0];
|
||||||
|
adr7.in1[1] <== base[1];
|
||||||
|
adr7.in2[0] <== adr6.out[0];
|
||||||
|
adr7.in2[1] <== adr6.out[1];
|
||||||
|
mux.c[0][6] <== adr7.out[0];
|
||||||
|
mux.c[1][6] <== adr7.out[1];
|
||||||
|
|
||||||
|
// in[7] -> 8*BASE
|
||||||
|
adr8.in1[0] <== base[0];
|
||||||
|
adr8.in1[1] <== base[1];
|
||||||
|
adr8.in2[0] <== adr7.out[0];
|
||||||
|
adr8.in2[1] <== adr7.out[1];
|
||||||
|
mux.c[0][7] <== adr8.out[0];
|
||||||
|
mux.c[1][7] <== adr8.out[1];
|
||||||
|
|
||||||
|
out8[0] <== adr8.out[0];
|
||||||
|
out8[1] <== adr8.out[1];
|
||||||
|
|
||||||
|
out[0] <== mux.out[0];
|
||||||
|
out[1] <== mux.out[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
This component does a multiplication of a escalar times a fix base
|
||||||
|
Signals:
|
||||||
|
e: The scalar in bits
|
||||||
|
base: the base point in edwards format
|
||||||
|
out: The result
|
||||||
|
dbl: Point in Edwards to be linked to the next segment.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template SegmentMulFix(nWindows) {
|
||||||
|
signal input e[nWindows*3];
|
||||||
|
signal input base[2];
|
||||||
|
signal output out[2];
|
||||||
|
signal output dbl[2];
|
||||||
|
|
||||||
|
var i;
|
||||||
|
var j;
|
||||||
|
|
||||||
|
// Convert the base to montgomery
|
||||||
|
|
||||||
|
component e2m = Edwards2Montgomery();
|
||||||
|
e2m.in[0] <== base[0];
|
||||||
|
e2m.in[1] <== base[1];
|
||||||
|
|
||||||
|
component windows[nWindows];
|
||||||
|
component adders[nWindows-1];
|
||||||
|
component cadders[nWindows-1];
|
||||||
|
for (i=0; i<nWindows; i++) {
|
||||||
|
windows[i] = WindowMulFix();
|
||||||
|
if (i==0) {
|
||||||
|
windows[i].base[0] <== e2m.out[0];
|
||||||
|
windows[i].base[1] <== e2m.out[1];
|
||||||
|
} else {
|
||||||
|
windows[i].base[0] <== windows[i-1].out8[0];
|
||||||
|
windows[i].base[1] <== windows[i-1].out8[1];
|
||||||
|
|
||||||
|
adders[i-1] = MontgomeryAdd();
|
||||||
|
cadders[i-1] = MontgomeryAdd();
|
||||||
|
if (i==1) {
|
||||||
|
adders[i-1].in1[0] <== windows[0].out[0];
|
||||||
|
adders[i-1].in1[1] <== windows[0].out[1];
|
||||||
|
cadders[i-1].in1[0] <== e2m.out[0];
|
||||||
|
cadders[i-1].in1[1] <== e2m.out[1];
|
||||||
|
} else {
|
||||||
|
adders[i-1].in1[0] <== adders[i-2].out[0];
|
||||||
|
adders[i-1].in1[1] <== adders[i-2].out[1];
|
||||||
|
cadders[i-1].in1[0] <== cadders[i-2].out[0];
|
||||||
|
cadders[i-1].in1[1] <== cadders[i-2].out[1];
|
||||||
|
}
|
||||||
|
adders[i-1].in2[0] <== windows[i].out[0];
|
||||||
|
adders[i-1].in2[1] <== windows[i].out[1];
|
||||||
|
cadders[i-1].in2[0] <== windows[i-1].out8[0];
|
||||||
|
cadders[i-1].in2[1] <== windows[i-1].out8[1];
|
||||||
|
}
|
||||||
|
for (j=0; j<3; j++) {
|
||||||
|
windows[i].in[j] <== e[3*i+j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component m2e = Montgomery2Edwards();
|
||||||
|
component cm2e = Montgomery2Edwards();
|
||||||
|
|
||||||
|
if (nWindows > 1) {
|
||||||
|
m2e.in[0] <== adders[nWindows-2].out[0];
|
||||||
|
m2e.in[1] <== adders[nWindows-2].out[1];
|
||||||
|
cm2e.in[0] <== cadders[nWindows-2].out[0];
|
||||||
|
cm2e.in[1] <== cadders[nWindows-2].out[1];
|
||||||
|
} else {
|
||||||
|
m2e.in[0] <== windows[0].out[0];
|
||||||
|
m2e.in[1] <== windows[0].out[1];
|
||||||
|
cm2e.in[0] <== e2m.out[0];
|
||||||
|
cm2e.in[1] <== e2m.out[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
component cAdd = BabyAdd();
|
||||||
|
cAdd.x1 <== m2e.out[0];
|
||||||
|
cAdd.y1 <== m2e.out[1];
|
||||||
|
cAdd.x2 <== -cm2e.out[0];
|
||||||
|
cAdd.y2 <== cm2e.out[1];
|
||||||
|
|
||||||
|
|
||||||
|
cAdd.xout ==> out[0];
|
||||||
|
cAdd.yout ==> out[1];
|
||||||
|
|
||||||
|
windows[nWindows-1].out8[0] ==> dbl[0];
|
||||||
|
windows[nWindows-1].out8[1] ==> dbl[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
This component multiplies a escalar times a fixed point BASE (twisted edwards format)
|
||||||
|
Signals
|
||||||
|
e: The escalar in binary format
|
||||||
|
out: The output point in twisted edwards
|
||||||
|
*/
|
||||||
|
template EscalarMulFix(n, BASE) {
|
||||||
|
signal input e[n]; // Input in binary format
|
||||||
|
signal output out[2]; // Point (Twisted format)
|
||||||
|
|
||||||
|
var nsegments = (n-1)\249 +1;
|
||||||
|
var nlastsegment = n - (nsegments-1)*249;
|
||||||
|
|
||||||
|
component segments[nsegments];
|
||||||
|
|
||||||
|
component m2e[nsegments-1];
|
||||||
|
component adders[nsegments-1];
|
||||||
|
|
||||||
|
var s;
|
||||||
|
var i;
|
||||||
|
var nseg;
|
||||||
|
var nWindows
|
||||||
|
|
||||||
|
for (s=0; s<nsegments; s++) {
|
||||||
|
|
||||||
|
nseg = (s < nsegments-1) ? 249 : nlastsegment;
|
||||||
|
nWindows = ((nseg - 1)\3)+1;
|
||||||
|
|
||||||
|
segments[s] = SegmentMulFix(nWindows);
|
||||||
|
|
||||||
|
for (i=0; i<nseg; i++) {
|
||||||
|
segments[s].e[i] <== e[s*249+i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = nseg; i<nWindows*3; i++) {
|
||||||
|
segments[s].e[i] <== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s==0) {
|
||||||
|
segments[s].base[0] <== BASE[0];
|
||||||
|
segments[s].base[1] <== BASE[1];
|
||||||
|
} else {
|
||||||
|
m2e[s-1] = Montgomery2Edwards();
|
||||||
|
adders[s-1] = BabyAdd();
|
||||||
|
|
||||||
|
segments[s-1].dbl[0] ==> m2e[s-1].in[0];
|
||||||
|
segments[s-1].dbl[1] ==> m2e[s-1].in[1];
|
||||||
|
|
||||||
|
m2e[s-1].out[0] ==> segments[s].base[0];
|
||||||
|
m2e[s-1].out[1] ==> segments[s].base[1];
|
||||||
|
|
||||||
|
if (s==1) {
|
||||||
|
segments[s-1].out[0] ==> adders[s-1].x1;
|
||||||
|
segments[s-1].out[1] ==> adders[s-1].y1;
|
||||||
|
} else {
|
||||||
|
adders[s-2].xout ==> adders[s-1].x1;
|
||||||
|
adders[s-2].yout ==> adders[s-1].y1;
|
||||||
|
}
|
||||||
|
segments[s].out[0] ==> adders[s-1].x2;
|
||||||
|
segments[s].out[1] ==> adders[s-1].y2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nsegments == 1) {
|
||||||
|
segments[0].out[0] ==> out[0];
|
||||||
|
segments[0].out[1] ==> out[1];
|
||||||
|
} else {
|
||||||
|
adders[nsegments-2].xout ==> out[0];
|
||||||
|
adders[nsegments-2].yout ==> out[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
49
circuits/escalarmulw4table.circom
Normal file
49
circuits/escalarmulw4table.circom
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function pointAdd(x1,y1,x2,y2) {
|
||||||
|
var a = 168700;
|
||||||
|
var d = 168696;
|
||||||
|
|
||||||
|
var res[2];
|
||||||
|
res[0] = (x1*y2 + y1*x2) / (1 + d*x1*x2*y1*y2);
|
||||||
|
res[1] = (y1*y2 - a*x1*x2) / (1 - d*x1*x2*y1*y2);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
template EscalarMulW4Table(base, k) {
|
||||||
|
signal output out[16][2];
|
||||||
|
|
||||||
|
var i;
|
||||||
|
var p[2];
|
||||||
|
|
||||||
|
var dbl = base;
|
||||||
|
|
||||||
|
for (i=0; i<k*4; i++) {
|
||||||
|
dbl = pointAdd(dbl[0], dbl[1], dbl[0], dbl[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
out[0][0] <== 0;
|
||||||
|
out[0][1] <== 1;
|
||||||
|
for (i=1; i<16; i++) {
|
||||||
|
p = pointAdd(out[i-1][0], out[i-1][1], dbl[0], dbl[1]);
|
||||||
|
out[i][0] <== p[0];
|
||||||
|
out[i][1] <== p[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
92
circuits/gates.circom
Normal file
92
circuits/gates.circom
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template XOR() {
|
||||||
|
signal input a;
|
||||||
|
signal input b;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
out <== a + b - 2*a*b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template AND() {
|
||||||
|
signal input a;
|
||||||
|
signal input b;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
out <== a*b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template OR() {
|
||||||
|
signal input a;
|
||||||
|
signal input b;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
out <== a + b - a*b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template NOT() {
|
||||||
|
signal input in;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
out <== 1 + in - 2*in;
|
||||||
|
}
|
||||||
|
|
||||||
|
template NAND() {
|
||||||
|
signal input a;
|
||||||
|
signal input b;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
out <== 1 - a*b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template NOR() {
|
||||||
|
signal input a;
|
||||||
|
signal input b;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
out <== a*b + 1 - a - b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template MultiAND(n) {
|
||||||
|
signal input in[n];
|
||||||
|
signal output out;
|
||||||
|
if (n==1) {
|
||||||
|
out <== in[0];
|
||||||
|
} else if (n==2) {
|
||||||
|
component and1 = AND();
|
||||||
|
and1.a <== in[0];
|
||||||
|
and1.b <== in[1];
|
||||||
|
out <== and1.out;
|
||||||
|
} else {
|
||||||
|
component and2 = AND();
|
||||||
|
component ands[2];
|
||||||
|
var n1 = n\2;
|
||||||
|
var n2 = n-n\2;
|
||||||
|
ands[0] = MultiAND(n1);
|
||||||
|
ands[1] = MultiAND(n2);
|
||||||
|
for (var i=0; i<n1; i++) ands[0].in[i] <== in[i];
|
||||||
|
for (var i=0; i<n2; i++) ands[1].in[i] <== in[n1+i];
|
||||||
|
and2.a <== ands[0].out;
|
||||||
|
and2.b <== ands[1].out;
|
||||||
|
out <== and2.out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
155
circuits/mimc.circom
Normal file
155
circuits/mimc.circom
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template MiMC7(nrounds) {
|
||||||
|
signal input x_in;
|
||||||
|
signal input k;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
var c = [
|
||||||
|
0,
|
||||||
|
20888961410941983456478427210666206549300505294776164667214940546594746570981,
|
||||||
|
15265126113435022738560151911929040668591755459209400716467504685752745317193,
|
||||||
|
8334177627492981984476504167502758309043212251641796197711684499645635709656,
|
||||||
|
1374324219480165500871639364801692115397519265181803854177629327624133579404,
|
||||||
|
11442588683664344394633565859260176446561886575962616332903193988751292992472,
|
||||||
|
2558901189096558760448896669327086721003508630712968559048179091037845349145,
|
||||||
|
11189978595292752354820141775598510151189959177917284797737745690127318076389,
|
||||||
|
3262966573163560839685415914157855077211340576201936620532175028036746741754,
|
||||||
|
17029914891543225301403832095880481731551830725367286980611178737703889171730,
|
||||||
|
4614037031668406927330683909387957156531244689520944789503628527855167665518,
|
||||||
|
19647356996769918391113967168615123299113119185942498194367262335168397100658,
|
||||||
|
5040699236106090655289931820723926657076483236860546282406111821875672148900,
|
||||||
|
2632385916954580941368956176626336146806721642583847728103570779270161510514,
|
||||||
|
17691411851977575435597871505860208507285462834710151833948561098560743654671,
|
||||||
|
11482807709115676646560379017491661435505951727793345550942389701970904563183,
|
||||||
|
8360838254132998143349158726141014535383109403565779450210746881879715734773,
|
||||||
|
12663821244032248511491386323242575231591777785787269938928497649288048289525,
|
||||||
|
3067001377342968891237590775929219083706800062321980129409398033259904188058,
|
||||||
|
8536471869378957766675292398190944925664113548202769136103887479787957959589,
|
||||||
|
19825444354178182240559170937204690272111734703605805530888940813160705385792,
|
||||||
|
16703465144013840124940690347975638755097486902749048533167980887413919317592,
|
||||||
|
13061236261277650370863439564453267964462486225679643020432589226741411380501,
|
||||||
|
10864774797625152707517901967943775867717907803542223029967000416969007792571,
|
||||||
|
10035653564014594269791753415727486340557376923045841607746250017541686319774,
|
||||||
|
3446968588058668564420958894889124905706353937375068998436129414772610003289,
|
||||||
|
4653317306466493184743870159523234588955994456998076243468148492375236846006,
|
||||||
|
8486711143589723036499933521576871883500223198263343024003617825616410932026,
|
||||||
|
250710584458582618659378487568129931785810765264752039738223488321597070280,
|
||||||
|
2104159799604932521291371026105311735948154964200596636974609406977292675173,
|
||||||
|
16313562605837709339799839901240652934758303521543693857533755376563489378839,
|
||||||
|
6032365105133504724925793806318578936233045029919447519826248813478479197288,
|
||||||
|
14025118133847866722315446277964222215118620050302054655768867040006542798474,
|
||||||
|
7400123822125662712777833064081316757896757785777291653271747396958201309118,
|
||||||
|
1744432620323851751204287974553233986555641872755053103823939564833813704825,
|
||||||
|
8316378125659383262515151597439205374263247719876250938893842106722210729522,
|
||||||
|
6739722627047123650704294650168547689199576889424317598327664349670094847386,
|
||||||
|
21211457866117465531949733809706514799713333930924902519246949506964470524162,
|
||||||
|
13718112532745211817410303291774369209520657938741992779396229864894885156527,
|
||||||
|
5264534817993325015357427094323255342713527811596856940387954546330728068658,
|
||||||
|
18884137497114307927425084003812022333609937761793387700010402412840002189451,
|
||||||
|
5148596049900083984813839872929010525572543381981952060869301611018636120248,
|
||||||
|
19799686398774806587970184652860783461860993790013219899147141137827718662674,
|
||||||
|
19240878651604412704364448729659032944342952609050243268894572835672205984837,
|
||||||
|
10546185249390392695582524554167530669949955276893453512788278945742408153192,
|
||||||
|
5507959600969845538113649209272736011390582494851145043668969080335346810411,
|
||||||
|
18177751737739153338153217698774510185696788019377850245260475034576050820091,
|
||||||
|
19603444733183990109492724100282114612026332366576932662794133334264283907557,
|
||||||
|
10548274686824425401349248282213580046351514091431715597441736281987273193140,
|
||||||
|
1823201861560942974198127384034483127920205835821334101215923769688644479957,
|
||||||
|
11867589662193422187545516240823411225342068709600734253659804646934346124945,
|
||||||
|
18718569356736340558616379408444812528964066420519677106145092918482774343613,
|
||||||
|
10530777752259630125564678480897857853807637120039176813174150229243735996839,
|
||||||
|
20486583726592018813337145844457018474256372770211860618687961310422228379031,
|
||||||
|
12690713110714036569415168795200156516217175005650145422920562694422306200486,
|
||||||
|
17386427286863519095301372413760745749282643730629659997153085139065756667205,
|
||||||
|
2216432659854733047132347621569505613620980842043977268828076165669557467682,
|
||||||
|
6309765381643925252238633914530877025934201680691496500372265330505506717193,
|
||||||
|
20806323192073945401862788605803131761175139076694468214027227878952047793390,
|
||||||
|
4037040458505567977365391535756875199663510397600316887746139396052445718861,
|
||||||
|
19948974083684238245321361840704327952464170097132407924861169241740046562673,
|
||||||
|
845322671528508199439318170916419179535949348988022948153107378280175750024,
|
||||||
|
16222384601744433420585982239113457177459602187868460608565289920306145389382,
|
||||||
|
10232118865851112229330353999139005145127746617219324244541194256766741433339,
|
||||||
|
6699067738555349409504843460654299019000594109597429103342076743347235369120,
|
||||||
|
6220784880752427143725783746407285094967584864656399181815603544365010379208,
|
||||||
|
6129250029437675212264306655559561251995722990149771051304736001195288083309,
|
||||||
|
10773245783118750721454994239248013870822765715268323522295722350908043393604,
|
||||||
|
4490242021765793917495398271905043433053432245571325177153467194570741607167,
|
||||||
|
19596995117319480189066041930051006586888908165330319666010398892494684778526,
|
||||||
|
837850695495734270707668553360118467905109360511302468085569220634750561083,
|
||||||
|
11803922811376367215191737026157445294481406304781326649717082177394185903907,
|
||||||
|
10201298324909697255105265958780781450978049256931478989759448189112393506592,
|
||||||
|
13564695482314888817576351063608519127702411536552857463682060761575100923924,
|
||||||
|
9262808208636973454201420823766139682381973240743541030659775288508921362724,
|
||||||
|
173271062536305557219323722062711383294158572562695717740068656098441040230,
|
||||||
|
18120430890549410286417591505529104700901943324772175772035648111937818237369,
|
||||||
|
20484495168135072493552514219686101965206843697794133766912991150184337935627,
|
||||||
|
19155651295705203459475805213866664350848604323501251939850063308319753686505,
|
||||||
|
11971299749478202793661982361798418342615500543489781306376058267926437157297,
|
||||||
|
18285310723116790056148596536349375622245669010373674803854111592441823052978,
|
||||||
|
7069216248902547653615508023941692395371990416048967468982099270925308100727,
|
||||||
|
6465151453746412132599596984628739550147379072443683076388208843341824127379,
|
||||||
|
16143532858389170960690347742477978826830511669766530042104134302796355145785,
|
||||||
|
19362583304414853660976404410208489566967618125972377176980367224623492419647,
|
||||||
|
1702213613534733786921602839210290505213503664731919006932367875629005980493,
|
||||||
|
10781825404476535814285389902565833897646945212027592373510689209734812292327,
|
||||||
|
4212716923652881254737947578600828255798948993302968210248673545442808456151,
|
||||||
|
7594017890037021425366623750593200398174488805473151513558919864633711506220,
|
||||||
|
18979889247746272055963929241596362599320706910852082477600815822482192194401,
|
||||||
|
13602139229813231349386885113156901793661719180900395818909719758150455500533
|
||||||
|
];
|
||||||
|
|
||||||
|
var t;
|
||||||
|
signal t2[nrounds];
|
||||||
|
signal t4[nrounds];
|
||||||
|
signal t6[nrounds];
|
||||||
|
signal t7[nrounds-1];
|
||||||
|
|
||||||
|
for (var i=0; i<nrounds; i++) {
|
||||||
|
t = (i==0) ? k+x_in : k + t7[i-1] + c[i];
|
||||||
|
t2[i] <== t*t;
|
||||||
|
t4[i] <== t2[i]*t2[i];
|
||||||
|
t6[i] <== t4[i]*t2[i];
|
||||||
|
if (i<nrounds-1) {
|
||||||
|
t7[i] <== t6[i]*t;
|
||||||
|
} else {
|
||||||
|
out <== t6[i]*t + k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template MultiMiMC7(nInputs, nRounds) {
|
||||||
|
signal input in[nInputs];
|
||||||
|
signal input k;
|
||||||
|
signal output out;
|
||||||
|
signal r[nInputs +1];
|
||||||
|
|
||||||
|
component mims[nInputs];
|
||||||
|
|
||||||
|
r[0] <== k;
|
||||||
|
for (var i=0; i<nInputs; i++) {
|
||||||
|
mims[i] = MiMC7(nRounds);
|
||||||
|
mims[i].x_in <== in[i];
|
||||||
|
mims[i].k <== r[i];
|
||||||
|
r[i+1] <== r[i] + in[i] + mims[i].out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out <== r[nInputs];
|
||||||
|
}
|
||||||
141
circuits/montgomery.circom
Normal file
141
circuits/montgomery.circom
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Source: https://en.wikipedia.org/wiki/Montgomery_curve
|
||||||
|
|
||||||
|
1 + y 1 + y
|
||||||
|
[u, v] = [ ------- , ---------- ]
|
||||||
|
1 - y (1 - y)x
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
template Edwards2Montgomery() {
|
||||||
|
signal input in[2];
|
||||||
|
signal output out[2];
|
||||||
|
|
||||||
|
out[0] <-- (1 + in[1]) / (1 - in[1]);
|
||||||
|
out[1] <-- out[0] / in[0];
|
||||||
|
|
||||||
|
|
||||||
|
out[0] * (1-in[1]) === (1 + in[1]);
|
||||||
|
out[1] * in[0] === out[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
u u - 1
|
||||||
|
[x, y] = [ ---, ------- ]
|
||||||
|
v u + 1
|
||||||
|
|
||||||
|
*/
|
||||||
|
template Montgomery2Edwards() {
|
||||||
|
signal input in[2];
|
||||||
|
signal output out[2];
|
||||||
|
|
||||||
|
out[0] <-- in[0] / in[1];
|
||||||
|
out[1] <-- (in[0] - 1) / (in[0] + 1);
|
||||||
|
|
||||||
|
out[0] * in[1] === in[0];
|
||||||
|
out[1] * (in[0] + 1) === in[0] - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
x2 - x1
|
||||||
|
lamda = ---------
|
||||||
|
y2 - y1
|
||||||
|
|
||||||
|
x3 + A + x1 + x2
|
||||||
|
x3 = B * lamda^2 - A - x1 -x2 => lamda^2 = ------------------
|
||||||
|
B
|
||||||
|
|
||||||
|
y3 = (2*x1 + x2 + A)*lamda - B*lamda^3 - y1 =>
|
||||||
|
|
||||||
|
|
||||||
|
=> y3 = lamda * ( 2*x1 + x2 + A - x3 - A - x1 - x2) - y1 =>
|
||||||
|
|
||||||
|
=> y3 = lamda * ( x1 - x3 ) - y1
|
||||||
|
|
||||||
|
----------
|
||||||
|
|
||||||
|
y2 - y1
|
||||||
|
lamda = ---------
|
||||||
|
x2 - x1
|
||||||
|
|
||||||
|
x3 = B * lamda^2 - A - x1 -x2
|
||||||
|
|
||||||
|
y3 = lamda * ( x1 - x3 ) - y1
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
template MontgomeryAdd() {
|
||||||
|
signal input in1[2];
|
||||||
|
signal input in2[2];
|
||||||
|
signal output out[2];
|
||||||
|
|
||||||
|
var a = 168700;
|
||||||
|
var d = 168696;
|
||||||
|
|
||||||
|
var A = (2 * (a + d)) / (a - d);
|
||||||
|
var B = 4 / (a - d);
|
||||||
|
|
||||||
|
signal lamda;
|
||||||
|
|
||||||
|
lamda <-- (in2[1] - in1[1]) / (in2[0] - in1[0]);
|
||||||
|
lamda * (in2[0] - in1[0]) === (in2[1] - in1[1]);
|
||||||
|
|
||||||
|
out[0] <== B*lamda*lamda - A - in1[0] -in2[0];
|
||||||
|
out[1] <== lamda * (in1[0] - out[0]) - in1[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
x1_2 = x1*x1
|
||||||
|
|
||||||
|
3*x1_2 + 2*A*x1 + 1
|
||||||
|
lamda = ---------------------
|
||||||
|
2*B*y1
|
||||||
|
|
||||||
|
x3 = B * lamda^2 - A - x1 -x1
|
||||||
|
|
||||||
|
y3 = lamda * ( x1 - x3 ) - y1
|
||||||
|
|
||||||
|
*/
|
||||||
|
template MontgomeryDouble() {
|
||||||
|
signal input in[2];
|
||||||
|
signal output out[2];
|
||||||
|
|
||||||
|
var a = 168700;
|
||||||
|
var d = 168696;
|
||||||
|
|
||||||
|
var A = (2 * (a + d)) / (a - d);
|
||||||
|
var B = 4 / (a - d);
|
||||||
|
|
||||||
|
signal lamda;
|
||||||
|
signal x1_2;
|
||||||
|
|
||||||
|
x1_2 <== in[0] * in[0];
|
||||||
|
|
||||||
|
lamda <-- (3*x1_2 + 2*A*in[0] + 1 ) / (2*B*in[1]);
|
||||||
|
lamda * (2*B*in[1]) === (3*x1_2 + 2*A*in[0] + 1 );
|
||||||
|
|
||||||
|
out[0] <== B*lamda*lamda - A - 2*in[0];
|
||||||
|
out[1] <== lamda * (in[0] - out[0]) - in[1];
|
||||||
|
}
|
||||||
112
circuits/multiplexer.circom
Normal file
112
circuits/multiplexer.circom
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// --> Assignation without constraint
|
||||||
|
// <-- Assignation without constraint
|
||||||
|
// === Constraint
|
||||||
|
// <== Assignation with constraint
|
||||||
|
// ==> Assignation with constraint
|
||||||
|
// All variables are members of the field F[p]
|
||||||
|
// https://github.com/zcash-hackworks/sapling-crypto
|
||||||
|
// https://github.com/ebfull/bellman
|
||||||
|
|
||||||
|
/*
|
||||||
|
function log2(a) {
|
||||||
|
if (a==0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
let n = 1;
|
||||||
|
let r = 1;
|
||||||
|
while (n<a) {
|
||||||
|
r++;
|
||||||
|
n *= 2;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
template EscalarProduct(w) {
|
||||||
|
signal input in1[w];
|
||||||
|
signal input in2[w];
|
||||||
|
signal output out;
|
||||||
|
signal aux[w];
|
||||||
|
var lc = 0;
|
||||||
|
for (var i=0; i<w; i++) {
|
||||||
|
aux[i] <== in1[i]*in2[i];
|
||||||
|
lc = lc + aux[i];
|
||||||
|
}
|
||||||
|
out <== lc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template Decoder(w) {
|
||||||
|
signal input inp;
|
||||||
|
signal output out[w];
|
||||||
|
signal output success;
|
||||||
|
var lc=0;
|
||||||
|
|
||||||
|
for (var i=0; i<w; i++) {
|
||||||
|
out[i] <-- (inp == i) ? 1 : 0;
|
||||||
|
out[i] * (inp-i) === 0;
|
||||||
|
lc = lc + out[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
lc ==> success;
|
||||||
|
success * (success -1) === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template Multiplexor(wIn, nIn) {
|
||||||
|
signal input inp[nIn][wIn];
|
||||||
|
signal input sel;
|
||||||
|
signal output out[wIn];
|
||||||
|
component Decoder(nIn) dec;
|
||||||
|
component EscalarProduct(nIn) ep[wIn];
|
||||||
|
sel ==> dec.inp;
|
||||||
|
for (var j=0; j<wIn; j++) {
|
||||||
|
for (var k=0; k<nIn; k++) {
|
||||||
|
inp[k][j] ==> ep[j].in1[k];
|
||||||
|
dec.out[k] ==> ep[j].in2[k];
|
||||||
|
}
|
||||||
|
ep[j].out ==> out[j];
|
||||||
|
}
|
||||||
|
dec.success === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
component Multiplexor(8,3) main;
|
||||||
|
|
||||||
|
|
||||||
74
circuits/mux3.circom
Normal file
74
circuits/mux3.circom
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template MultiMux3(n) {
|
||||||
|
signal input c[n][8]; // Constants
|
||||||
|
signal input s[3]; // Selector
|
||||||
|
signal output out[n];
|
||||||
|
|
||||||
|
signal a210[n];
|
||||||
|
signal a21[n];
|
||||||
|
signal a20[n];
|
||||||
|
signal a2[n];
|
||||||
|
|
||||||
|
signal a10[n];
|
||||||
|
signal a1[n];
|
||||||
|
signal a0[n];
|
||||||
|
signal a[n];
|
||||||
|
|
||||||
|
// 4 constrains for the intermediary variables
|
||||||
|
signal s10;
|
||||||
|
s10 <== s[1] * s[0];
|
||||||
|
|
||||||
|
for (var i=0; i<n; i++) {
|
||||||
|
|
||||||
|
a210[i] <== ( c[i][ 7]-c[i][ 6]-c[i][ 5]+c[i][ 4] - c[i][ 3]+c[i][ 2]+c[i][ 1]-c[i][ 0] ) * s10;
|
||||||
|
a21[i] <== ( c[i][ 6]-c[i][ 4]-c[i][ 2]+c[i][ 0] ) * s[1];
|
||||||
|
a20[i] <== ( c[i][ 5]-c[i][ 4]-c[i][ 1]+c[i][ 0] ) * s[0];
|
||||||
|
a2[i] <== ( c[i][ 4]-c[i][ 0] );
|
||||||
|
|
||||||
|
a10[i] <== ( c[i][ 3]-c[i][ 2]-c[i][ 1]+c[i][ 0] ) * s10;
|
||||||
|
a1[i] <== ( c[i][ 2]-c[i][ 0] ) * s[1];
|
||||||
|
a0[i] <== ( c[i][ 1]-c[i][ 0] ) * s[0];
|
||||||
|
a[i] <== ( c[i][ 0] )
|
||||||
|
|
||||||
|
out[i] <== ( a210[i] + a21[i] + a20[i] + a2[i] ) * s[2] +
|
||||||
|
( a10[i] + a1[i] + a0[i] + a[i] );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template Mux3() {
|
||||||
|
var i;
|
||||||
|
signal input c[8]; // Constants
|
||||||
|
signal input s[3]; // Selector
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
component mux = MultiMux3(1);
|
||||||
|
|
||||||
|
for (i=0; i<8; i++) {
|
||||||
|
mux.c[0][i] <== c[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<3; i++) {
|
||||||
|
s[i] ==> mux.s[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
mux.out[0] ==> out;
|
||||||
|
}
|
||||||
@@ -1,6 +1,21 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
template MultiMux4(n) {
|
template MultiMux4(n) {
|
||||||
signal input c[n][16]; // Constants
|
signal input c[n][16]; // Constants
|
||||||
255
circuits/pedersen.circom
Normal file
255
circuits/pedersen.circom
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "montgomery.circom";
|
||||||
|
include "mux3.circom";
|
||||||
|
include "babyjub.circom";
|
||||||
|
|
||||||
|
template Window4() {
|
||||||
|
signal input in[4];
|
||||||
|
signal input base[2];
|
||||||
|
signal output out[2];
|
||||||
|
signal output out8[2]; // Returns 8*Base (To be linked)
|
||||||
|
|
||||||
|
component mux = MultiMux3(2);
|
||||||
|
|
||||||
|
mux.s[0] <== in[0];
|
||||||
|
mux.s[1] <== in[1];
|
||||||
|
mux.s[2] <== in[2];
|
||||||
|
|
||||||
|
component dbl2 = MontgomeryDouble();
|
||||||
|
component adr3 = MontgomeryAdd();
|
||||||
|
component adr4 = MontgomeryAdd();
|
||||||
|
component adr5 = MontgomeryAdd();
|
||||||
|
component adr6 = MontgomeryAdd();
|
||||||
|
component adr7 = MontgomeryAdd();
|
||||||
|
component adr8 = MontgomeryAdd();
|
||||||
|
|
||||||
|
// in[0] -> 1*BASE
|
||||||
|
|
||||||
|
mux.c[0][0] <== base[0];
|
||||||
|
mux.c[1][0] <== base[1];
|
||||||
|
|
||||||
|
// in[1] -> 2*BASE
|
||||||
|
dbl2.in[0] <== base[0];
|
||||||
|
dbl2.in[1] <== base[1];
|
||||||
|
mux.c[0][1] <== dbl2.out[0];
|
||||||
|
mux.c[1][1] <== dbl2.out[1];
|
||||||
|
|
||||||
|
// in[2] -> 3*BASE
|
||||||
|
adr3.in1[0] <== base[0];
|
||||||
|
adr3.in1[1] <== base[1];
|
||||||
|
adr3.in2[0] <== dbl2.out[0];
|
||||||
|
adr3.in2[1] <== dbl2.out[1];
|
||||||
|
mux.c[0][2] <== adr3.out[0];
|
||||||
|
mux.c[1][2] <== adr3.out[1];
|
||||||
|
|
||||||
|
// in[3] -> 4*BASE
|
||||||
|
adr4.in1[0] <== base[0];
|
||||||
|
adr4.in1[1] <== base[1];
|
||||||
|
adr4.in2[0] <== adr3.out[0];
|
||||||
|
adr4.in2[1] <== adr3.out[1];
|
||||||
|
mux.c[0][3] <== adr4.out[0];
|
||||||
|
mux.c[1][3] <== adr4.out[1];
|
||||||
|
|
||||||
|
// in[4] -> 5*BASE
|
||||||
|
adr5.in1[0] <== base[0];
|
||||||
|
adr5.in1[1] <== base[1];
|
||||||
|
adr5.in2[0] <== adr4.out[0];
|
||||||
|
adr5.in2[1] <== adr4.out[1];
|
||||||
|
mux.c[0][4] <== adr5.out[0];
|
||||||
|
mux.c[1][4] <== adr5.out[1];
|
||||||
|
|
||||||
|
// in[5] -> 6*BASE
|
||||||
|
adr6.in1[0] <== base[0];
|
||||||
|
adr6.in1[1] <== base[1];
|
||||||
|
adr6.in2[0] <== adr5.out[0];
|
||||||
|
adr6.in2[1] <== adr5.out[1];
|
||||||
|
mux.c[0][5] <== adr6.out[0];
|
||||||
|
mux.c[1][5] <== adr6.out[1];
|
||||||
|
|
||||||
|
// in[6] -> 7*BASE
|
||||||
|
adr7.in1[0] <== base[0];
|
||||||
|
adr7.in1[1] <== base[1];
|
||||||
|
adr7.in2[0] <== adr6.out[0];
|
||||||
|
adr7.in2[1] <== adr6.out[1];
|
||||||
|
mux.c[0][6] <== adr7.out[0];
|
||||||
|
mux.c[1][6] <== adr7.out[1];
|
||||||
|
|
||||||
|
// in[7] -> 8*BASE
|
||||||
|
adr8.in1[0] <== base[0];
|
||||||
|
adr8.in1[1] <== base[1];
|
||||||
|
adr8.in2[0] <== adr7.out[0];
|
||||||
|
adr8.in2[1] <== adr7.out[1];
|
||||||
|
mux.c[0][7] <== adr8.out[0];
|
||||||
|
mux.c[1][7] <== adr8.out[1];
|
||||||
|
|
||||||
|
out8[0] <== adr8.out[0];
|
||||||
|
out8[1] <== adr8.out[1];
|
||||||
|
|
||||||
|
out[0] <== mux.out[0];
|
||||||
|
out[1] <== - mux.out[1]*2*in[3] + mux.out[1]; // Negate y if in[3] is one
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template Segment(nWindows) {
|
||||||
|
signal input in[nWindows*4];
|
||||||
|
signal input base[2];
|
||||||
|
signal output out[2];
|
||||||
|
|
||||||
|
var i;
|
||||||
|
var j;
|
||||||
|
|
||||||
|
// Convert the base to montgomery
|
||||||
|
|
||||||
|
component e2m = Edwards2Montgomery();
|
||||||
|
e2m.in[0] <== base[0];
|
||||||
|
e2m.in[1] <== base[1];
|
||||||
|
|
||||||
|
component windows[nWindows];
|
||||||
|
component doublers1[nWindows-1];
|
||||||
|
component doublers2[nWindows-1];
|
||||||
|
component adders[nWindows-1];
|
||||||
|
for (i=0; i<nWindows; i++) {
|
||||||
|
windows[i] = Window4();
|
||||||
|
if (i==0) {
|
||||||
|
windows[i].base[0] <== e2m.out[0];
|
||||||
|
windows[i].base[1] <== e2m.out[1];
|
||||||
|
} else {
|
||||||
|
doublers1[i-1] = MontgomeryDouble();
|
||||||
|
doublers2[i-1] = MontgomeryDouble();
|
||||||
|
doublers1[i-1].in[0] <== windows[i-1].out8[0];
|
||||||
|
doublers1[i-1].in[1] <== windows[i-1].out8[1];
|
||||||
|
doublers2[i-1].in[0] <== doublers1[i-1].out[0];
|
||||||
|
doublers2[i-1].in[1] <== doublers1[i-1].out[1];
|
||||||
|
|
||||||
|
windows[i].base[0] <== doublers2[i-1].out[0];
|
||||||
|
windows[i].base[1] <== doublers2[i-1].out[1];
|
||||||
|
|
||||||
|
adders[i-1] = MontgomeryAdd();
|
||||||
|
if (i==1) {
|
||||||
|
adders[i-1].in1[0] <== windows[0].out[0];
|
||||||
|
adders[i-1].in1[1] <== windows[0].out[1];
|
||||||
|
} else {
|
||||||
|
adders[i-1].in1[0] <== adders[i-2].out[0];
|
||||||
|
adders[i-1].in1[1] <== adders[i-2].out[1];
|
||||||
|
}
|
||||||
|
adders[i-1].in2[0] <== windows[i].out[0];
|
||||||
|
adders[i-1].in2[1] <== windows[i].out[1];
|
||||||
|
}
|
||||||
|
for (j=0; j<4; j++) {
|
||||||
|
windows[i].in[j] <== in[4*i+j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component m2e = Montgomery2Edwards();
|
||||||
|
|
||||||
|
if (nWindows > 1) {
|
||||||
|
m2e.in[0] <== adders[nWindows-2].out[0];
|
||||||
|
m2e.in[1] <== adders[nWindows-2].out[1];
|
||||||
|
} else {
|
||||||
|
m2e.in[0] <== windows[0].out[0];
|
||||||
|
m2e.in[1] <== windows[0].out[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
out[0] <== m2e.out[0];
|
||||||
|
out[1] <== m2e.out[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
template Pedersen(n) {
|
||||||
|
signal input in[n];
|
||||||
|
signal output out[2];
|
||||||
|
|
||||||
|
var BASE = [
|
||||||
|
[10457101036533406547632367118273992217979173478358440826365724437999023779287,19824078218392094440610104313265183977899662750282163392862422243483260492317],
|
||||||
|
[2671756056509184035029146175565761955751135805354291559563293617232983272177,2663205510731142763556352975002641716101654201788071096152948830924149045094],
|
||||||
|
[5802099305472655231388284418920769829666717045250560929368476121199858275951,5980429700218124965372158798884772646841287887664001482443826541541529227896],
|
||||||
|
[7107336197374528537877327281242680114152313102022415488494307685842428166594,2857869773864086953506483169737724679646433914307247183624878062391496185654],
|
||||||
|
[20265828622013100949498132415626198973119240347465898028410217039057588424236,1160461593266035632937973507065134938065359936056410650153315956301179689506],
|
||||||
|
[1487999857809287756929114517587739322941449154962237464737694709326309567994,14017256862867289575056460215526364897734808720610101650676790868051368668003],
|
||||||
|
[14618644331049802168996997831720384953259095788558646464435263343433563860015,13115243279999696210147231297848654998887864576952244320558158620692603342236],
|
||||||
|
[6814338563135591367010655964669793483652536871717891893032616415581401894627,13660303521961041205824633772157003587453809761793065294055279768121314853695],
|
||||||
|
[3571615583211663069428808372184817973703476260057504149923239576077102575715,11981351099832644138306422070127357074117642951423551606012551622164230222506],
|
||||||
|
[18597552580465440374022635246985743886550544261632147935254624835147509493269,6753322320275422086923032033899357299485124665258735666995435957890214041481]
|
||||||
|
]
|
||||||
|
|
||||||
|
var nSegments = ((n-1)\200)+1;
|
||||||
|
|
||||||
|
component segments[nSegments];
|
||||||
|
|
||||||
|
var i;
|
||||||
|
var j;
|
||||||
|
var nBits;
|
||||||
|
var nWindows;
|
||||||
|
for (i=0; i<nSegments; i++) {
|
||||||
|
nBits = (i == (nSegments-1)) ? n - (nSegments-1)*200 : 200;
|
||||||
|
nWindows = ((nBits - 1)\4)+1;
|
||||||
|
segments[i] = Segment(nWindows);
|
||||||
|
segments[i].base[0] <== BASE[i][0];
|
||||||
|
segments[i].base[1] <== BASE[i][1];
|
||||||
|
for (j = 0; j<nBits; j++) {
|
||||||
|
segments[i].in[j] <== in[i*200+j];
|
||||||
|
}
|
||||||
|
// Fill padding bits
|
||||||
|
for (j = nBits; j < nWindows*4; j++) {
|
||||||
|
segments[i].in[j] <== 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component adders[nSegments-1];
|
||||||
|
|
||||||
|
for (i=0; i<nSegments-1; i++) {
|
||||||
|
adders[i] = BabyAdd();
|
||||||
|
if (i==0) {
|
||||||
|
adders[i].x1 <== segments[0].out[0];
|
||||||
|
adders[i].y1 <== segments[0].out[1];
|
||||||
|
adders[i].x2 <== segments[1].out[0];
|
||||||
|
adders[i].y2 <== segments[1].out[1];
|
||||||
|
} else {
|
||||||
|
adders[i].x1 <== adders[i-1].xout;
|
||||||
|
adders[i].y1 <== adders[i-1].yout;
|
||||||
|
adders[i].x2 <== segments[i+1].out[0];
|
||||||
|
adders[i].y2 <== segments[i+1].out[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
coponent packPoint = PackPoint();
|
||||||
|
|
||||||
|
if (nSegments>1) {
|
||||||
|
packPoint.in[0] <== adders[nSegments-2].xout;
|
||||||
|
packPoint.in[1] <== adders[nSegments-2].yout;
|
||||||
|
} else {
|
||||||
|
packPoint.in[0] <== segments[0].out[0];
|
||||||
|
packPoint.in[1] <== segments[0].out[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
out[0] <== packPoint.out[0];
|
||||||
|
out[1] <== packPoint.out[1];
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (nSegments>1) {
|
||||||
|
out[0] <== adders[nSegments-2].xout;
|
||||||
|
out[1] <== adders[nSegments-2].yout;
|
||||||
|
} else {
|
||||||
|
out[0] <== segments[0].out[0];
|
||||||
|
out[1] <== segments[0].out[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
66
circuits/pedersen_old.circom
Normal file
66
circuits/pedersen_old.circom
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "escalarmul.circom";
|
||||||
|
|
||||||
|
template Pedersen(n) {
|
||||||
|
signal input in[n];
|
||||||
|
signal output out[2];
|
||||||
|
|
||||||
|
var nexps = ((n-1) \ 250) + 1;
|
||||||
|
var nlastbits = n - (nexps-1)*250;
|
||||||
|
|
||||||
|
component escalarMuls[nexps];
|
||||||
|
|
||||||
|
var PBASE = [
|
||||||
|
[10457101036533406547632367118273992217979173478358440826365724437999023779287,19824078218392094440610104313265183977899662750282163392862422243483260492317],
|
||||||
|
[2671756056509184035029146175565761955751135805354291559563293617232983272177,2663205510731142763556352975002641716101654201788071096152948830924149045094],
|
||||||
|
[5802099305472655231388284418920769829666717045250560929368476121199858275951,5980429700218124965372158798884772646841287887664001482443826541541529227896],
|
||||||
|
[7107336197374528537877327281242680114152313102022415488494307685842428166594,2857869773864086953506483169737724679646433914307247183624878062391496185654],
|
||||||
|
[20265828622013100949498132415626198973119240347465898028410217039057588424236,1160461593266035632937973507065134938065359936056410650153315956301179689506],
|
||||||
|
[1487999857809287756929114517587739322941449154962237464737694709326309567994,14017256862867289575056460215526364897734808720610101650676790868051368668003],
|
||||||
|
[14618644331049802168996997831720384953259095788558646464435263343433563860015,13115243279999696210147231297848654998887864576952244320558158620692603342236],
|
||||||
|
[6814338563135591367010655964669793483652536871717891893032616415581401894627,13660303521961041205824633772157003587453809761793065294055279768121314853695],
|
||||||
|
[3571615583211663069428808372184817973703476260057504149923239576077102575715,11981351099832644138306422070127357074117642951423551606012551622164230222506],
|
||||||
|
[18597552580465440374022635246985743886550544261632147935254624835147509493269,6753322320275422086923032033899357299485124665258735666995435957890214041481]
|
||||||
|
];
|
||||||
|
|
||||||
|
var i;
|
||||||
|
var j;
|
||||||
|
var nexpbits;
|
||||||
|
for (i=0; i<nexps; i++) {
|
||||||
|
nexpbits = (i == nexps-1) ? nlastbits : 250;
|
||||||
|
escalarMuls[i] = EscalarMul(nexpbits, PBASE[i]);
|
||||||
|
|
||||||
|
for (j=0; j<nexpbits; j++) {
|
||||||
|
escalarMuls[i].in[j] <== in[250*i + j];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i==0) {
|
||||||
|
escalarMuls[i].inp[0] <== 0;
|
||||||
|
escalarMuls[i].inp[1] <== 1;
|
||||||
|
} else {
|
||||||
|
escalarMuls[i].inp[0] <== escalarMuls[i-1].out[0];
|
||||||
|
escalarMuls[i].inp[1] <== escalarMuls[i-1].out[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
escalarMuls[nexps-1].out[0] ==> out[0];
|
||||||
|
escalarMuls[nexps-1].out[1] ==> out[1];
|
||||||
|
}
|
||||||
163
circuits/pointbits.circom
Normal file
163
circuits/pointbits.circom
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "bitify.circom";
|
||||||
|
include "aliascheck.circom";
|
||||||
|
include "compconstant.circom";
|
||||||
|
include "babyjub.circom";
|
||||||
|
|
||||||
|
|
||||||
|
function sqrt(n) {
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that have solution
|
||||||
|
var res = n ** ((-1) >> 1);
|
||||||
|
// if (res!=1) assert(false, "SQRT does not exists");
|
||||||
|
if (res!=1) return 0;
|
||||||
|
|
||||||
|
var m = 28;
|
||||||
|
var c = 19103219067921713944291392827692070036145651957329286315305642004821462161904;
|
||||||
|
var t = n ** 81540058820840996586704275553141814055101440848469862132140264610111;
|
||||||
|
var r = n ** ((81540058820840996586704275553141814055101440848469862132140264610111+1)>>1);
|
||||||
|
var sq;
|
||||||
|
var i;
|
||||||
|
var b;
|
||||||
|
var j;
|
||||||
|
|
||||||
|
while ((r != 0)&&(t != 1)) {
|
||||||
|
sq = t*t;
|
||||||
|
i = 1;
|
||||||
|
while (sq!=1) {
|
||||||
|
i++;
|
||||||
|
sq = sq*sq;
|
||||||
|
}
|
||||||
|
|
||||||
|
// b = c ^ m-i-1
|
||||||
|
b = c;
|
||||||
|
for (j=0; j< m-i-1; j ++) b = b*b;
|
||||||
|
|
||||||
|
m = i;
|
||||||
|
c = b*b;
|
||||||
|
t = t*c;
|
||||||
|
r = r*b;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r > ((-1) >> 1)) {
|
||||||
|
r = -r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template Bits2Point() {
|
||||||
|
signal input in[256];
|
||||||
|
signal output out[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
template Bits2Point_Strict() {
|
||||||
|
signal input in[256];
|
||||||
|
signal output out[2];
|
||||||
|
|
||||||
|
var i;
|
||||||
|
|
||||||
|
// Check aliasing
|
||||||
|
component aliasCheckY = AliasCheck();
|
||||||
|
for (i=0; i<254; i++) {
|
||||||
|
aliasCheckY.in[i] <== in[i];
|
||||||
|
}
|
||||||
|
in[254] === 0;
|
||||||
|
|
||||||
|
component b2nY = Bits2Num(254);
|
||||||
|
for (i=0; i<254; i++) {
|
||||||
|
b2nY.in[i] <== in[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
out[1] <== b2nY.out;
|
||||||
|
|
||||||
|
var a = 168700;
|
||||||
|
var d = 168696;
|
||||||
|
|
||||||
|
var y2 = out[1] * out[1];
|
||||||
|
|
||||||
|
var x = sqrt( (1-y2)/(a - d*y2) );
|
||||||
|
|
||||||
|
if (in[255] == 1) x = -x;
|
||||||
|
|
||||||
|
out[0] <-- x;
|
||||||
|
|
||||||
|
component babyCheck = BabyCheck();
|
||||||
|
babyCheck.x <== out[0];
|
||||||
|
babyCheck.y <== out[1];
|
||||||
|
|
||||||
|
component n2bX = Num2Bits(254);
|
||||||
|
n2bX.in <== out[0];
|
||||||
|
component aliasCheckX = AliasCheck();
|
||||||
|
for (i=0; i<254; i++) {
|
||||||
|
aliasCheckX.in[i] <== n2bX.out[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
component signCalc = CompConstant(10944121435919637611123202872628637544274182200208017171849102093287904247808);
|
||||||
|
for (i=0; i<254; i++) {
|
||||||
|
signCalc.in[i] <== n2bX.out[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
signCalc.out === in[255];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template Point2Bits() {
|
||||||
|
signal input in[2];
|
||||||
|
signal output out[256];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template Point2Bits_Strict() {
|
||||||
|
signal input in[2];
|
||||||
|
signal output out[256];
|
||||||
|
|
||||||
|
var i;
|
||||||
|
|
||||||
|
component n2bX = Num2Bits(254);
|
||||||
|
n2bX.in <== in[0];
|
||||||
|
component n2bY = Num2Bits(254);
|
||||||
|
n2bY.in <== in[1];
|
||||||
|
|
||||||
|
component aliasCheckX = AliasCheck();
|
||||||
|
component aliasCheckY = AliasCheck();
|
||||||
|
for (i=0; i<254; i++) {
|
||||||
|
aliasCheckX.in[i] <== n2bX.out[i];
|
||||||
|
aliasCheckY.in[i] <== n2bY.out[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
component signCalc = CompConstant(10944121435919637611123202872628637544274182200208017171849102093287904247808);
|
||||||
|
for (i=0; i<254; i++) {
|
||||||
|
signCalc.in[i] <== n2bX.out[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<254; i++) {
|
||||||
|
out[i] <== n2bY.out[i];
|
||||||
|
}
|
||||||
|
out[254] <== 0;
|
||||||
|
out[255] <== signCalc.out;
|
||||||
|
}
|
||||||
46
circuits/sha256/ch.circom
Normal file
46
circuits/sha256/ch.circom
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Ch
|
||||||
|
|
||||||
|
000 0
|
||||||
|
001 1
|
||||||
|
010 0
|
||||||
|
011 1
|
||||||
|
100 0
|
||||||
|
101 0
|
||||||
|
110 1
|
||||||
|
111 1
|
||||||
|
|
||||||
|
out = a&b ^ (!a)&c =>
|
||||||
|
|
||||||
|
out = a*(b-c) + c
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
template Ch(n) {
|
||||||
|
signal input a[n];
|
||||||
|
signal input b[n];
|
||||||
|
signal input c[n];
|
||||||
|
signal output out[n];
|
||||||
|
|
||||||
|
for (var k=0; k<n; k++) {
|
||||||
|
out[k] <== a[k] * (b[k]-c[k]) + c[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
52
circuits/sha256/constants.circom
Normal file
52
circuits/sha256/constants.circom
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template H(x) {
|
||||||
|
signal output out[32];
|
||||||
|
var c = [0x6a09e667,
|
||||||
|
0xbb67ae85,
|
||||||
|
0x3c6ef372,
|
||||||
|
0xa54ff53a,
|
||||||
|
0x510e527f,
|
||||||
|
0x9b05688c,
|
||||||
|
0x1f83d9ab,
|
||||||
|
0x5be0cd19];
|
||||||
|
|
||||||
|
for (var i=0; i<32; i++) {
|
||||||
|
out[i] <== (c[x] >> i) & 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template K(x) {
|
||||||
|
signal output out[32];
|
||||||
|
var c = [
|
||||||
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||||
|
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||||
|
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||||
|
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||||
|
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||||
|
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||||
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||||
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||||
|
];
|
||||||
|
|
||||||
|
for (var i=0; i<32; i++) {
|
||||||
|
out[i] <== (c[x] >> i) & 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
34
circuits/sha256/main.circom
Normal file
34
circuits/sha256/main.circom
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "sha256_2.jaz";
|
||||||
|
|
||||||
|
template Main() {
|
||||||
|
signal private input a;
|
||||||
|
signal private input b;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
component sha256_2 = SHA256_2();
|
||||||
|
|
||||||
|
sha256_2.a <== a;
|
||||||
|
sha256_2.b <== a;
|
||||||
|
out <== sha256_2.out;
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = Main();
|
||||||
44
circuits/sha256/maj.circom
Normal file
44
circuits/sha256/maj.circom
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Maj function for sha256
|
||||||
|
|
||||||
|
out = a&b ^ a&c ^ b&c =>
|
||||||
|
|
||||||
|
out = a*b + a*c + b*c - 2*a*b*c =>
|
||||||
|
|
||||||
|
out = a*( b + c - 2*b*c ) + b*c =>
|
||||||
|
|
||||||
|
mid = b*c
|
||||||
|
out = a*( b + c - 2*mid ) + mid
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
template Maj(n) {
|
||||||
|
signal input a[n];
|
||||||
|
signal input b[n];
|
||||||
|
signal input c[n];
|
||||||
|
signal output out[n];
|
||||||
|
signal mid[n];
|
||||||
|
|
||||||
|
for (var k=0; k<n; k++) {
|
||||||
|
mid[k] <== b[k]*c[k];
|
||||||
|
out[k] <== a[k] * (b[k]+c[k]-2*mid[k]) + mid[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
27
circuits/sha256/rotate.circom
Normal file
27
circuits/sha256/rotate.circom
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template RotR(n, r) {
|
||||||
|
signal input in[n];
|
||||||
|
signal output out[n];
|
||||||
|
|
||||||
|
for (var i=0; i<n; i++) {
|
||||||
|
out[i] <== in[ (i+r)%n ];
|
||||||
|
}
|
||||||
|
}
|
||||||
67
circuits/sha256/sha256_2.circom
Normal file
67
circuits/sha256/sha256_2.circom
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "sha256compression.circom";
|
||||||
|
include "../bitify.circom"
|
||||||
|
|
||||||
|
template Sha256_2() {
|
||||||
|
signal input a;
|
||||||
|
signal input b;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
component bits2num = Bits2Num(216);
|
||||||
|
component num2bits[2];
|
||||||
|
|
||||||
|
num2bits[0] = Num2Bits(216);
|
||||||
|
num2bits[1] = Num2Bits(216);
|
||||||
|
|
||||||
|
num2bits[0].in <== a;
|
||||||
|
num2bits[1].in <== b;
|
||||||
|
|
||||||
|
component sha256compression = Sha256compression() ;
|
||||||
|
|
||||||
|
var i;
|
||||||
|
|
||||||
|
for (i=0; i<216; i++) {
|
||||||
|
sha256compression.inp[i] <== num2bits[0].out[215-i];
|
||||||
|
sha256compression.inp[i+216] <== num2bits[1].out[215-i];
|
||||||
|
}
|
||||||
|
|
||||||
|
sha256compression.inp[432] <== 1;
|
||||||
|
|
||||||
|
for (i=433; i<503; i++) {
|
||||||
|
sha256compression.inp[i] <== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sha256compression.inp[503] <== 1;
|
||||||
|
sha256compression.inp[504] <== 1;
|
||||||
|
sha256compression.inp[505] <== 0;
|
||||||
|
sha256compression.inp[506] <== 1;
|
||||||
|
sha256compression.inp[507] <== 1;
|
||||||
|
sha256compression.inp[508] <== 0;
|
||||||
|
sha256compression.inp[509] <== 0;
|
||||||
|
sha256compression.inp[510] <== 0;
|
||||||
|
sha256compression.inp[511] <== 0;
|
||||||
|
|
||||||
|
for (i=0; i<216; i++) {
|
||||||
|
bits2num.in[i] <== sha256compression.out[255-i];
|
||||||
|
}
|
||||||
|
|
||||||
|
out <== bits2num.out;
|
||||||
|
}
|
||||||
164
circuits/sha256/sha256compression.circom
Normal file
164
circuits/sha256/sha256compression.circom
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "constants.circom";
|
||||||
|
include "t1.circom";
|
||||||
|
include "t2.circom";
|
||||||
|
include "../binsum.circom";
|
||||||
|
include "sigmaplus.circom";
|
||||||
|
|
||||||
|
template Sha256compression() {
|
||||||
|
signal input inp[512];
|
||||||
|
signal output out[256];
|
||||||
|
signal a[65][32];
|
||||||
|
signal b[65][32];
|
||||||
|
signal c[65][32];
|
||||||
|
signal d[65][32];
|
||||||
|
signal e[65][32];
|
||||||
|
signal f[65][32];
|
||||||
|
signal g[65][32];
|
||||||
|
signal h[65][32];
|
||||||
|
signal w[64][32];
|
||||||
|
|
||||||
|
var i;
|
||||||
|
|
||||||
|
component sigmaPlus[48];
|
||||||
|
for (i=0; i<48; i++) sigmaPlus[i] = SigmaPlus();
|
||||||
|
|
||||||
|
component ct_k[64];
|
||||||
|
for (i=0; i<64; i++) ct_k[i] = K(i);
|
||||||
|
|
||||||
|
component ha0 = H(0);
|
||||||
|
component hb0 = H(1);
|
||||||
|
component hc0 = H(2);
|
||||||
|
component hd0 = H(3);
|
||||||
|
component he0 = H(4);
|
||||||
|
component hf0 = H(5);
|
||||||
|
component hg0 = H(6);
|
||||||
|
component hh0 = H(7);
|
||||||
|
|
||||||
|
component t1[64];
|
||||||
|
for (i=0; i<64; i++) t1[i] = T1();
|
||||||
|
|
||||||
|
component t2[64];
|
||||||
|
for (i=0; i<64; i++) t2[i] = T2();
|
||||||
|
|
||||||
|
component suma[64];
|
||||||
|
for (i=0; i<64; i++) suma[i] = BinSum(32, 2);
|
||||||
|
|
||||||
|
component sume[64];
|
||||||
|
for (i=0; i<64; i++) sume[i] = BinSum(32, 2);
|
||||||
|
|
||||||
|
component fsum[8];
|
||||||
|
for (i=0; i<8; i++) fsum[i] = BinSum(32, 2);
|
||||||
|
|
||||||
|
var k;
|
||||||
|
var t;
|
||||||
|
|
||||||
|
for (t=0; t<64; t++) {
|
||||||
|
if (t<16) {
|
||||||
|
for (k=0; k<32; k++) {
|
||||||
|
w[t][k] <== inp[t*32+31-k];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (k=0; k<32; k++) {
|
||||||
|
sigmaPlus[t-16].in2[k] <== w[t-2][k];
|
||||||
|
sigmaPlus[t-16].in7[k] <== w[t-7][k];
|
||||||
|
sigmaPlus[t-16].in15[k] <== w[t-15][k];
|
||||||
|
sigmaPlus[t-16].in16[k] <== w[t-16][k];
|
||||||
|
w[t][k] <== sigmaPlus[t-16].out[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k=0; k<32; k++ ) {
|
||||||
|
a[0][k] <== ha0.out[k]
|
||||||
|
b[0][k] <== hb0.out[k]
|
||||||
|
c[0][k] <== hc0.out[k]
|
||||||
|
d[0][k] <== hd0.out[k]
|
||||||
|
e[0][k] <== he0.out[k]
|
||||||
|
f[0][k] <== hf0.out[k]
|
||||||
|
g[0][k] <== hg0.out[k]
|
||||||
|
h[0][k] <== hh0.out[k]
|
||||||
|
}
|
||||||
|
|
||||||
|
for (t = 0; t<64; t++) {
|
||||||
|
for (k=0; k<32; k++) {
|
||||||
|
t1[t].h[k] <== h[t][k];
|
||||||
|
t1[t].e[k] <== e[t][k];
|
||||||
|
t1[t].f[k] <== f[t][k];
|
||||||
|
t1[t].g[k] <== g[t][k];
|
||||||
|
t1[t].k[k] <== ct_k[t].out[k];
|
||||||
|
t1[t].w[k] <== w[t][k];
|
||||||
|
|
||||||
|
t2[t].a[k] <== a[t][k];
|
||||||
|
t2[t].b[k] <== b[t][k];
|
||||||
|
t2[t].c[k] <== c[t][k];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k=0; k<32; k++) {
|
||||||
|
sume[t].in[0][k] <== d[t][k];
|
||||||
|
sume[t].in[1][k] <== t1[t].out[k];
|
||||||
|
|
||||||
|
suma[t].in[0][k] <== t1[t].out[k];
|
||||||
|
suma[t].in[1][k] <== t2[t].out[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k=0; k<32; k++) {
|
||||||
|
h[t+1][k] <== g[t][k];
|
||||||
|
g[t+1][k] <== f[t][k];
|
||||||
|
f[t+1][k] <== e[t][k];
|
||||||
|
e[t+1][k] <== sume[t].out[k];
|
||||||
|
d[t+1][k] <== c[t][k];
|
||||||
|
c[t+1][k] <== b[t][k];
|
||||||
|
b[t+1][k] <== a[t][k];
|
||||||
|
a[t+1][k] <== suma[t].out[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k=0; k<32; k++) {
|
||||||
|
fsum[0].in[0][k] <== ha0.out[k];
|
||||||
|
fsum[0].in[1][k] <== a[64][k];
|
||||||
|
fsum[1].in[0][k] <== hb0.out[k];
|
||||||
|
fsum[1].in[1][k] <== b[64][k];
|
||||||
|
fsum[2].in[0][k] <== hc0.out[k];
|
||||||
|
fsum[2].in[1][k] <== c[64][k];
|
||||||
|
fsum[3].in[0][k] <== hd0.out[k];
|
||||||
|
fsum[3].in[1][k] <== d[64][k];
|
||||||
|
fsum[4].in[0][k] <== he0.out[k];
|
||||||
|
fsum[4].in[1][k] <== e[64][k];
|
||||||
|
fsum[5].in[0][k] <== hf0.out[k];
|
||||||
|
fsum[5].in[1][k] <== f[64][k];
|
||||||
|
fsum[6].in[0][k] <== hg0.out[k];
|
||||||
|
fsum[6].in[1][k] <== g[64][k];
|
||||||
|
fsum[7].in[0][k] <== hh0.out[k];
|
||||||
|
fsum[7].in[1][k] <== h[64][k];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k=0; k<32; k++) {
|
||||||
|
out[31-k] <== fsum[0].out[k];
|
||||||
|
out[32+31-k] <== fsum[1].out[k];
|
||||||
|
out[64+31-k] <== fsum[2].out[k];
|
||||||
|
out[96+31-k] <== fsum[3].out[k];
|
||||||
|
out[128+31-k] <== fsum[4].out[k];
|
||||||
|
out[160+31-k] <== fsum[5].out[k];
|
||||||
|
out[192+31-k] <== fsum[6].out[k];
|
||||||
|
out[224+31-k] <== fsum[7].out[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
32
circuits/sha256/shift.circom
Normal file
32
circuits/sha256/shift.circom
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template ShR(n, r) {
|
||||||
|
signal input in[n];
|
||||||
|
signal output out[n];
|
||||||
|
|
||||||
|
for (var i=0; i<n; i++) {
|
||||||
|
if (i+r >= n) {
|
||||||
|
out[i] <== 0;
|
||||||
|
} else {
|
||||||
|
out[i] <== in[ i+r ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
68
circuits/sha256/sigma.circom
Normal file
68
circuits/sha256/sigma.circom
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "xor3.circom";
|
||||||
|
include "rotate.circom";
|
||||||
|
include "shift.circom";
|
||||||
|
|
||||||
|
template SmallSigma(ra, rb, rc) {
|
||||||
|
signal input in[32];
|
||||||
|
signal output out[32];
|
||||||
|
|
||||||
|
component xor3 = Xor3(32);
|
||||||
|
|
||||||
|
component rota = RotR(32, ra);
|
||||||
|
component rotb = RotR(32, rb);
|
||||||
|
component shrc = ShR(32, rc);
|
||||||
|
|
||||||
|
for (var k=0; k<32; k++) {
|
||||||
|
rota.in[k] <== in[k];
|
||||||
|
rotb.in[k] <== in[k];
|
||||||
|
shrc.in[k] <== in[k];
|
||||||
|
|
||||||
|
xor3.a[k] <== rota.out[k];
|
||||||
|
xor3.b[k] <== rotb.out[k];
|
||||||
|
xor3.c[k] <== shrc.out[k];
|
||||||
|
|
||||||
|
out[k] <== xor3.out[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template BigSigma(ra, rb, rc) {
|
||||||
|
signal input in[32];
|
||||||
|
signal output out[32];
|
||||||
|
|
||||||
|
component xor3 = Xor3(32);
|
||||||
|
|
||||||
|
component rota = RotR(32, ra);
|
||||||
|
component rotb = RotR(32, rb);
|
||||||
|
component rotc = RotR(32, rc);
|
||||||
|
|
||||||
|
for (var k=0; k<32; k++) {
|
||||||
|
rota.in[k] <== in[k];
|
||||||
|
rotb.in[k] <== in[k];
|
||||||
|
rotc.in[k] <== in[k];
|
||||||
|
|
||||||
|
xor3.a[k] <== rota.out[k];
|
||||||
|
xor3.b[k] <== rotb.out[k];
|
||||||
|
xor3.c[k] <== rotc.out[k];
|
||||||
|
|
||||||
|
out[k] <== xor3.out[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
45
circuits/sha256/sigmaplus.circom
Normal file
45
circuits/sha256/sigmaplus.circom
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "../binsum.circom"
|
||||||
|
include "sigma.circom"
|
||||||
|
|
||||||
|
template SigmaPlus() {
|
||||||
|
signal input in2[32];
|
||||||
|
signal input in7[32];
|
||||||
|
signal input in15[32];
|
||||||
|
signal input in16[32];
|
||||||
|
signal output out[32];
|
||||||
|
|
||||||
|
component sum = BinSum(32, 4);
|
||||||
|
component sigma1 = SmallSigma(17,19,10);
|
||||||
|
component sigma0 = SmallSigma(7, 18, 3);
|
||||||
|
|
||||||
|
for (var k=0; k<32; k++) {
|
||||||
|
sigma1.in[k] <== in2[k];
|
||||||
|
sigma0.in[k] <== in15[k];
|
||||||
|
|
||||||
|
sum.in[0][k] <== sigma1.out[k];
|
||||||
|
sum.in[1][k] <== in7[k];
|
||||||
|
sum.in[2][k] <== sigma0.out[k];
|
||||||
|
sum.in[3][k] <== in16[k];
|
||||||
|
|
||||||
|
out[k] <== sum.out[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
52
circuits/sha256/t1.circom
Normal file
52
circuits/sha256/t1.circom
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "../binsum.circom";
|
||||||
|
include "sigma.circom";
|
||||||
|
include "ch.circom";
|
||||||
|
|
||||||
|
template T1() {
|
||||||
|
signal input h[32];
|
||||||
|
signal input e[32];
|
||||||
|
signal input f[32];
|
||||||
|
signal input g[32];
|
||||||
|
signal input k[32];
|
||||||
|
signal input w[32];
|
||||||
|
signal output out[32];
|
||||||
|
|
||||||
|
component sum = BinSum(32, 5);
|
||||||
|
component ch = Ch(32);
|
||||||
|
|
||||||
|
component bigsigma1 = BigSigma(6, 11, 25);
|
||||||
|
|
||||||
|
for (var ki=0; ki<32; ki++) {
|
||||||
|
bigsigma1.in[ki] <== e[ki];
|
||||||
|
ch.a[ki] <== e[ki];
|
||||||
|
ch.b[ki] <== f[ki];
|
||||||
|
ch.c[ki] <== g[ki]
|
||||||
|
|
||||||
|
sum.in[0][ki] <== h[ki];
|
||||||
|
sum.in[1][ki] <== bigsigma1.out[ki];
|
||||||
|
sum.in[2][ki] <== ch.out[ki];
|
||||||
|
sum.in[3][ki] <== k[ki];
|
||||||
|
sum.in[4][ki] <== w[ki];
|
||||||
|
|
||||||
|
out[ki] <== sum.out[ki];
|
||||||
|
}
|
||||||
|
}
|
||||||
47
circuits/sha256/t2.circom
Normal file
47
circuits/sha256/t2.circom
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "../binsum.circom";
|
||||||
|
include "sigma.circom";
|
||||||
|
include "maj.circom"
|
||||||
|
|
||||||
|
template T2() {
|
||||||
|
signal input a[32];
|
||||||
|
signal input b[32];
|
||||||
|
signal input c[32];
|
||||||
|
signal output out[32];
|
||||||
|
|
||||||
|
component sum = BinSum(32, 2);
|
||||||
|
|
||||||
|
component bigsigma0 = BigSigma(2, 13, 22);
|
||||||
|
component maj = Maj(32);
|
||||||
|
|
||||||
|
for (var k=0; k<32; k++) {
|
||||||
|
|
||||||
|
bigsigma0.in[k] <== a[k];
|
||||||
|
maj.a[k] <== a[k];
|
||||||
|
maj.b[k] <== b[k];
|
||||||
|
maj.c[k] <== c[k];
|
||||||
|
|
||||||
|
sum.in[0][k] <== bigsigma0.out[k];
|
||||||
|
sum.in[1][k] <== maj.out[k];
|
||||||
|
|
||||||
|
out[k] <== sum.out[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
44
circuits/sha256/xor3.circom
Normal file
44
circuits/sha256/xor3.circom
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Xor3 function for sha256
|
||||||
|
|
||||||
|
out = a ^ b ^ c =>
|
||||||
|
|
||||||
|
out = a+b+c - 2*a*b - 2*a*c - 2*b*c + 4*a*b*c =>
|
||||||
|
|
||||||
|
out = a*( 1 - 2*b - 2*c + 4*b*c ) + b + c - 2*b*c =>
|
||||||
|
|
||||||
|
mid = b*c
|
||||||
|
out = a*( 1 - 2*b -2*c + 4*mid ) + b + c - 2 * mid
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
template Xor3(n) {
|
||||||
|
signal input a[n];
|
||||||
|
signal input b[n];
|
||||||
|
signal input c[n];
|
||||||
|
signal output out[n];
|
||||||
|
signal mid[n];
|
||||||
|
|
||||||
|
for (var k=0; k<n; k++) {
|
||||||
|
mid[k] <== b[k]*c[k];
|
||||||
|
out[k] <== a[k] * (1 -2*b[k] -2*c[k] +4*mid[k]) + b[k] + c[k] -2*mid[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
35
circuits/sign.circom
Normal file
35
circuits/sign.circom
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "compconstant.circom";
|
||||||
|
|
||||||
|
template Sign() {
|
||||||
|
signal input in[254];
|
||||||
|
signal output sign;
|
||||||
|
|
||||||
|
component comp = CompConstant(10944121435919637611123202872628637544274182200208017171849102093287904247808);
|
||||||
|
|
||||||
|
var i;
|
||||||
|
|
||||||
|
for (i=0; i<254; i++) {
|
||||||
|
comp.in[i] <== in[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
sign <== comp.out;
|
||||||
|
}
|
||||||
57
circuits/smt/smthash.circom
Normal file
57
circuits/smt/smthash.circom
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include "../mimc.circom";
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Hash1 = H(1 | key | value)
|
||||||
|
*/
|
||||||
|
|
||||||
|
template SMTHash1() {
|
||||||
|
signal input key;
|
||||||
|
signal input value;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
component h = MultiMiMC7(2, 91); // Constant
|
||||||
|
h.in[0] <== key;
|
||||||
|
h.in[1] <== value;
|
||||||
|
h.k <== 1;
|
||||||
|
|
||||||
|
out <== h.out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This component is used to create the 2 nodes.
|
||||||
|
|
||||||
|
Hash2 = H(Hl | Hr)
|
||||||
|
*/
|
||||||
|
|
||||||
|
template SMTHash2() {
|
||||||
|
signal input L;
|
||||||
|
signal input R;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
component h = MultiMiMC7(2, 91); // Constant
|
||||||
|
h.in[0] <== L;
|
||||||
|
h.in[1] <== R;
|
||||||
|
h.k <== 0;
|
||||||
|
|
||||||
|
out <== h.out;
|
||||||
|
}
|
||||||
100
circuits/smt/smtlevins.circom
Normal file
100
circuits/smt/smtlevins.circom
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This component finds the level where the oldInsert is done.
|
||||||
|
The rules are:
|
||||||
|
|
||||||
|
levIns[i] == 1 if its level and all the child levels have a sibling of 0 and
|
||||||
|
the parent level has a sibling != 0. Considere that the root level always has
|
||||||
|
a parent with a sibling != 0.
|
||||||
|
|
||||||
|
|
||||||
|
┌──────────────┐
|
||||||
|
│ │
|
||||||
|
│ │───▶ levIns[0] <== (1-done[i])
|
||||||
|
│ │
|
||||||
|
└──────────────┘
|
||||||
|
▲
|
||||||
|
│
|
||||||
|
│
|
||||||
|
done[0]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
done[i-1] <== levIns[i] + done[i]
|
||||||
|
▲
|
||||||
|
│
|
||||||
|
│
|
||||||
|
┌───────────┐ ┌──────────────┐
|
||||||
|
│ │ │ │
|
||||||
|
sibling[i-1]───▶│IsZero[i-1]│─▶│ │───▶ levIns[i] <== (1-done[i])*(1-isZero[i-1].out)
|
||||||
|
│ │ │ │
|
||||||
|
└───────────┘ └──────────────┘
|
||||||
|
▲
|
||||||
|
│
|
||||||
|
│
|
||||||
|
done[i]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
done[n-2] <== levIns[n-1]
|
||||||
|
▲
|
||||||
|
│
|
||||||
|
│
|
||||||
|
┌───────────┐ ┌──────────────┐
|
||||||
|
│ │ │ │
|
||||||
|
sibling[n-2]───▶│IsZero[n-2]│─▶│ │────▶ levIns[n-1] <== (1-isZero[n-2].out)
|
||||||
|
│ │ │ │
|
||||||
|
└───────────┘ └──────────────┘
|
||||||
|
|
||||||
|
┌───────────┐
|
||||||
|
│ │
|
||||||
|
sibling[n-1]───▶│IsZero[n-1]│────▶ === 0
|
||||||
|
│ │
|
||||||
|
└───────────┘
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
template SMTLevIns(nLevels) {
|
||||||
|
signal input enabled;
|
||||||
|
signal input siblings[nLevels];
|
||||||
|
signal output levIns[nLevels];
|
||||||
|
signal done[nLevels-1]; // Indicates if the insLevel has aready been detected.
|
||||||
|
|
||||||
|
component isZero[nLevels];
|
||||||
|
|
||||||
|
for (var i=0; i<nLevels; i++) {
|
||||||
|
isZero[i] = IsZero();
|
||||||
|
isZero[i].in <== siblings[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// The last level must always have a sibling of 0. If not, then it cannot be inserted.
|
||||||
|
(isZero[nLevels-1].out - 1) * enabled === 0;
|
||||||
|
|
||||||
|
levIns[nLevels-1] <== (1-isZero[nLevels-2].out);
|
||||||
|
done[nLevels-2] <== levIns[nLevels-1];
|
||||||
|
for (var i=nLevels-2; i>0; i--) {
|
||||||
|
levIns[i] <== (1-done[i])*(1-isZero[i-1].out)
|
||||||
|
done[i-1] <== levIns[i] + done[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
levIns[0] <== (1-done[0]);
|
||||||
|
}
|
||||||
258
circuits/smt/smtprocessor.circom
Normal file
258
circuits/smt/smtprocessor.circom
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
SMTProcessor: Sparse Merkle Tree processor is a component to verify an insert/update/delete elements
|
||||||
|
into the Sparse Merkle tree.
|
||||||
|
|
||||||
|
|
||||||
|
Insert to an empty leaf
|
||||||
|
=======================
|
||||||
|
|
||||||
|
STATE OLD STATE NEW STATE
|
||||||
|
===== ========= =========
|
||||||
|
|
||||||
|
oldRoot newRoot
|
||||||
|
▲ ▲
|
||||||
|
│ │
|
||||||
|
┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
|
||||||
|
top │Sibling├────▶┃ Hash ┃◀─┐ │Sibling├────▶┃ Hash ┃◀─┐
|
||||||
|
└───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓ ┌───────┐
|
||||||
|
top ┌─────▶┃ Hash ┃◀──┤Sibling│ ┌─────▶┃ Hash ┃◀──┤Sibling│
|
||||||
|
│ ┗━━━━━━━┛ └───────┘ │ ┗━━━━━━━┛ └───────┘
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
|
||||||
|
top │Sibling├──▶┃ Hash ┃◀─────┐ │Sibling├──▶┃ Hash ┃◀─────┐
|
||||||
|
└───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
┌────┴────┐ ┌────┴────┐
|
||||||
|
old0 │ 0 │ │New1Leaf │
|
||||||
|
└─────────┘ └─────────┘
|
||||||
|
|
||||||
|
|
||||||
|
┏━━━━━━━┓ ┏━━━━━━━┓
|
||||||
|
na ┃ Hash ┃ ┃ Hash ┃
|
||||||
|
┗━━━━━━━┛ ┗━━━━━━━┛
|
||||||
|
|
||||||
|
|
||||||
|
┏━━━━━━━┓ ┏━━━━━━━┓
|
||||||
|
na ┃ Hash ┃ ┃ Hash ┃
|
||||||
|
┗━━━━━━━┛ ┗━━━━━━━┛
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Insert to a used leaf.
|
||||||
|
=====================
|
||||||
|
|
||||||
|
STATE OLD STATE NEW STATE
|
||||||
|
===== ========= =========
|
||||||
|
|
||||||
|
|
||||||
|
oldRoot newRoot
|
||||||
|
▲ ▲
|
||||||
|
│ │
|
||||||
|
┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
|
||||||
|
top │Sibling├────▶┃ Hash ┃◀─┐ │Sibling├────▶┃ Hash ┃◀─┐
|
||||||
|
└───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓ ┌───────┐
|
||||||
|
top ┌─────▶┃ Hash ┃◀──┤Sibling│ ┌─────▶┃ Hash ┃◀──┤Sibling│
|
||||||
|
│ ┗━━━━━━━┛ └───────┘ │ ┗━━━━━━━┛ └───────┘
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
|
||||||
|
top │Sibling├──▶┃ Hash ┃◀─────┐ │Sibling├──▶┃ Hash ┃◀─────┐
|
||||||
|
└───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
┌────┴────┐ ┏━━━┻━━━┓ ┌───────┐
|
||||||
|
bot │Old1Leaf │ ┌─────▶┃ Hash ┃◀──┼─ 0 │
|
||||||
|
└─────────┘ │ ┗━━━━━━━┛ └───────┘
|
||||||
|
│
|
||||||
|
│
|
||||||
|
┏━━━━━━━┓ ┌───────┐ ┏━━━┻━━━┓
|
||||||
|
bot ┃ Hash ┃ │ 0 ─┼──▶┃ Hash ┃◀─────┐
|
||||||
|
┗━━━━━━━┛ └───────┘ ┗━━━━━━━┛ │
|
||||||
|
│
|
||||||
|
│
|
||||||
|
┏━━━━━━━┓ ┏━━━┻━━━┓ ┌───────┐
|
||||||
|
bot ┃ Hash ┃ ┌─────▶┃ Hash ┃◀──│ 0 │
|
||||||
|
┗━━━━━━━┛ │ ┗━━━━━━━┛ └───────┘
|
||||||
|
│
|
||||||
|
│
|
||||||
|
┏━━━━━━━┓ ┌─────────┐ ┏━━━┻━━━┓ ┌─────────┐
|
||||||
|
new1 ┃ Hash ┃ │Old1Leaf ├──▶┃ Hash ┃◀──│New1Leaf │
|
||||||
|
┗━━━━━━━┛ └─────────┘ ┗━━━━━━━┛ └─────────┘
|
||||||
|
|
||||||
|
|
||||||
|
┏━━━━━━━┓ ┏━━━━━━━┓
|
||||||
|
na ┃ Hash ┃ ┃ Hash ┃
|
||||||
|
┗━━━━━━━┛ ┗━━━━━━━┛
|
||||||
|
|
||||||
|
|
||||||
|
┏━━━━━━━┓ ┏━━━━━━━┓
|
||||||
|
na ┃ Hash ┃ ┃ Hash ┃
|
||||||
|
┗━━━━━━━┛ ┗━━━━━━━┛
|
||||||
|
|
||||||
|
|
||||||
|
Fnction
|
||||||
|
fnc[0] fnc[1]
|
||||||
|
0 0 NOP
|
||||||
|
0 1 UPDATE
|
||||||
|
1 0 INSERT
|
||||||
|
1 1 DELETE
|
||||||
|
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
include "../gates.circom";
|
||||||
|
include "../bitify.circom";
|
||||||
|
include "../comparators.circom";
|
||||||
|
include "../switcher.circom";
|
||||||
|
include "smtlevins.circom";
|
||||||
|
include "smtprocessorlevel.circom";
|
||||||
|
include "smtprocessorsm.circom";
|
||||||
|
include "smthash.circom";
|
||||||
|
|
||||||
|
template SMTProcessor(nLevels) {
|
||||||
|
signal input oldRoot;
|
||||||
|
signal output newRoot;
|
||||||
|
signal input siblings[nLevels];
|
||||||
|
signal input oldKey;
|
||||||
|
signal input oldValue;
|
||||||
|
signal input isOld0;
|
||||||
|
signal input newKey;
|
||||||
|
signal input newValue;
|
||||||
|
signal input fnc[2];
|
||||||
|
|
||||||
|
signal enabled;
|
||||||
|
|
||||||
|
enabled <== fnc[0] + fnc[1] - fnc[0]*fnc[1]
|
||||||
|
|
||||||
|
component hash1Old = SMTHash1();
|
||||||
|
hash1Old.key <== oldKey;
|
||||||
|
hash1Old.value <== oldValue;
|
||||||
|
|
||||||
|
component hash1New = SMTHash1();
|
||||||
|
hash1New.key <== newKey;
|
||||||
|
hash1New.value <== newValue;
|
||||||
|
|
||||||
|
component n2bOld = Num2Bits_strict();
|
||||||
|
component n2bNew = Num2Bits_strict();
|
||||||
|
|
||||||
|
n2bOld.in <== oldKey;
|
||||||
|
n2bNew.in <== newKey;
|
||||||
|
|
||||||
|
component smtLevIns = SMTLevIns(nLevels);
|
||||||
|
for (var i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i];
|
||||||
|
smtLevIns.enabled <== enabled;
|
||||||
|
|
||||||
|
component xors[nLevels];
|
||||||
|
for (var i=0; i<nLevels; i++) {
|
||||||
|
xors[i] = XOR();
|
||||||
|
xors[i].a <== n2bOld.out[i];
|
||||||
|
xors[i].b <== n2bNew.out[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
component sm[nLevels];
|
||||||
|
for (var i=0; i<nLevels; i++) {
|
||||||
|
sm[i] = SMTProcessorSM();
|
||||||
|
if (i==0) {
|
||||||
|
sm[i].prev_top <== enabled;
|
||||||
|
sm[i].prev_old0 <== 0;
|
||||||
|
sm[i].prev_bot <== 0;
|
||||||
|
sm[i].prev_new1 <== 0;
|
||||||
|
sm[i].prev_na <== 1-enabled;
|
||||||
|
sm[i].prev_upd <== 0;
|
||||||
|
} else {
|
||||||
|
sm[i].prev_top <== sm[i-1].st_top;
|
||||||
|
sm[i].prev_old0 <== sm[i-1].st_old0;
|
||||||
|
sm[i].prev_bot <== sm[i-1].st_bot;
|
||||||
|
sm[i].prev_new1 <== sm[i-1].st_new1;
|
||||||
|
sm[i].prev_na <== sm[i-1].st_na;
|
||||||
|
sm[i].prev_upd <== sm[i-1].st_upd;
|
||||||
|
}
|
||||||
|
sm[i].is0 <== isOld0;
|
||||||
|
sm[i].xor <== xors[i].out;
|
||||||
|
sm[i].fnc[0] <== fnc[0];
|
||||||
|
sm[i].fnc[1] <== fnc[1];
|
||||||
|
sm[i].levIns <== smtLevIns.levIns[i];
|
||||||
|
}
|
||||||
|
sm[nLevels-1].st_na + sm[nLevels-1].st_new1 + sm[nLevels-1].st_old0 +sm[nLevels-1].st_upd === 1;
|
||||||
|
|
||||||
|
component levels[nLevels];
|
||||||
|
for (var i=nLevels-1; i != -1; i--) {
|
||||||
|
levels[i] = SMTProcessorLevel();
|
||||||
|
|
||||||
|
levels[i].st_top <== sm[i].st_top;
|
||||||
|
levels[i].st_old0 <== sm[i].st_old0;
|
||||||
|
levels[i].st_bot <== sm[i].st_bot;
|
||||||
|
levels[i].st_new1 <== sm[i].st_new1;
|
||||||
|
levels[i].st_na <== sm[i].st_na;
|
||||||
|
levels[i].st_upd <== sm[i].st_upd;
|
||||||
|
|
||||||
|
levels[i].sibling <== siblings[i];
|
||||||
|
levels[i].old1leaf <== hash1Old.out;
|
||||||
|
levels[i].new1leaf <== hash1New.out;
|
||||||
|
|
||||||
|
levels[i].newlrbit <== n2bNew.out[i];
|
||||||
|
if (i==nLevels-1) {
|
||||||
|
levels[i].oldChild <== 0;
|
||||||
|
levels[i].newChild <== 0;
|
||||||
|
} else {
|
||||||
|
levels[i].oldChild <== levels[i+1].oldRoot;
|
||||||
|
levels[i].newChild <== levels[i+1].newRoot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component topSwitcher = Switcher();
|
||||||
|
|
||||||
|
topSwitcher.sel <== fnc[0]*fnc[1];
|
||||||
|
topSwitcher.L <== levels[0].oldRoot;
|
||||||
|
topSwitcher.R <== levels[0].newRoot;
|
||||||
|
|
||||||
|
component checkOldInput = ForceEqualIfEnabled();
|
||||||
|
checkOldInput.enabled <== enabled;
|
||||||
|
checkOldInput.in[0] <== oldRoot;
|
||||||
|
checkOldInput.in[1] <== topSwitcher.outL;
|
||||||
|
|
||||||
|
newRoot <== enabled * (topSwitcher.outR - oldRoot) + oldRoot;
|
||||||
|
|
||||||
|
// topSwitcher.outL === oldRoot*enabled;
|
||||||
|
// topSwitcher.outR === newRoot*enabled;
|
||||||
|
|
||||||
|
// Ckeck keys are equal if updating
|
||||||
|
component areKeyEquals = IsEqual();
|
||||||
|
areKeyEquals.in[0] <== oldKey;
|
||||||
|
areKeyEquals.in[1] <== newKey;
|
||||||
|
|
||||||
|
component keysOk = MultiAND(3);
|
||||||
|
keysOk.in[0] <== 1-fnc[0];
|
||||||
|
keysOk.in[1] <== fnc[1];
|
||||||
|
keysOk.in[2] <== 1-areKeyEquals.out;
|
||||||
|
|
||||||
|
keysOk.out === 0;
|
||||||
|
}
|
||||||
94
circuits/smt/smtprocessorlevel.circom
Normal file
94
circuits/smt/smtprocessorlevel.circom
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******
|
||||||
|
|
||||||
|
SMTProcessorLevel
|
||||||
|
|
||||||
|
This circuit has 2 hash
|
||||||
|
|
||||||
|
Outputs according to the state.
|
||||||
|
|
||||||
|
State oldRoot newRoot
|
||||||
|
===== ======= =======
|
||||||
|
top H'(oldChild, sibling) H'(newChild, sibling)
|
||||||
|
old0 0 new1leaf
|
||||||
|
bot old1leaf H'(newChild, 0)
|
||||||
|
new1 old1leaf H'(new1leaf, old1leaf)
|
||||||
|
na 0 0
|
||||||
|
|
||||||
|
upd old1leaf new1leaf
|
||||||
|
|
||||||
|
H' is the Hash function with the inputs shifted acordingly.
|
||||||
|
|
||||||
|
*****/
|
||||||
|
|
||||||
|
|
||||||
|
template SMTProcessorLevel() {
|
||||||
|
signal input st_top;
|
||||||
|
signal input st_old0;
|
||||||
|
signal input st_bot;
|
||||||
|
signal input st_new1;
|
||||||
|
signal input st_na;
|
||||||
|
signal input st_upd;
|
||||||
|
|
||||||
|
signal output oldRoot;
|
||||||
|
signal output newRoot;
|
||||||
|
signal input sibling;
|
||||||
|
signal input old1leaf;
|
||||||
|
signal input new1leaf;
|
||||||
|
signal input newlrbit;
|
||||||
|
signal input oldChild;
|
||||||
|
signal input newChild;
|
||||||
|
|
||||||
|
signal aux[4];
|
||||||
|
|
||||||
|
component oldProofHash = SMTHash2();
|
||||||
|
component newProofHash = SMTHash2();
|
||||||
|
|
||||||
|
component oldSwitcher = Switcher();
|
||||||
|
component newSwitcher = Switcher();
|
||||||
|
|
||||||
|
// Old side
|
||||||
|
|
||||||
|
oldSwitcher.L <== oldChild;
|
||||||
|
oldSwitcher.R <== sibling;
|
||||||
|
|
||||||
|
oldSwitcher.sel <== newlrbit;
|
||||||
|
oldProofHash.L <== oldSwitcher.outL;
|
||||||
|
oldProofHash.R <== oldSwitcher.outR;
|
||||||
|
|
||||||
|
aux[0] <== old1leaf * (st_bot + st_new1 + st_upd);
|
||||||
|
oldRoot <== aux[0] + oldProofHash.out * st_top;
|
||||||
|
|
||||||
|
// New side
|
||||||
|
|
||||||
|
aux[1] <== newChild * ( st_top + st_bot);
|
||||||
|
newSwitcher.L <== aux[1] + new1leaf*st_new1;
|
||||||
|
|
||||||
|
aux[2] <== sibling*st_top;
|
||||||
|
newSwitcher.R <== aux[2] + old1leaf*st_new1;
|
||||||
|
|
||||||
|
newSwitcher.sel <== newlrbit;
|
||||||
|
newProofHash.L <== newSwitcher.outL;
|
||||||
|
newProofHash.R <== newSwitcher.outR;
|
||||||
|
|
||||||
|
aux[3] <== newProofHash.out * (st_top + st_bot + st_new1);
|
||||||
|
newRoot <== aux[3] + new1leaf * (st_old0 + st_upd);
|
||||||
|
}
|
||||||
164
circuits/smt/smtprocessorsm.circom
Normal file
164
circuits/smt/smtprocessorsm.circom
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
Each level on a SMTProcessor has a state.
|
||||||
|
|
||||||
|
The state of the level depends on the state of te botom level and on `xor` and
|
||||||
|
`is0` signals.
|
||||||
|
|
||||||
|
`isOldLev` 1 when is the level where oldLeaf is.
|
||||||
|
|
||||||
|
`xor` signal is 0 if the index bit at the current level is the same in the old
|
||||||
|
and the new index, and 1 if it is different.
|
||||||
|
|
||||||
|
`is0` signal, is 1 if we are inserting/deleting in an empty leaf and 0 if we
|
||||||
|
are inserting/deleting in a leaf that contains an element.
|
||||||
|
|
||||||
|
The states are:
|
||||||
|
|
||||||
|
top: While the index bits of the old and new insex in the top level is the same, whe are in the top state.
|
||||||
|
old0: When the we reach insert level, we go to old0 state
|
||||||
|
if `is0`=1.
|
||||||
|
btn: Once in insert level and `is0` =0 we go to btn or new1 level if xor=1
|
||||||
|
new1: This level is reached when xor=1. Here is where we insert/delete the hash of the
|
||||||
|
old and the new trees with just one element.
|
||||||
|
na: Not appliable. After processing it, we go to the na level.
|
||||||
|
|
||||||
|
|
||||||
|
Fnction
|
||||||
|
fnc[0] fnc[1]
|
||||||
|
0 0 NOP
|
||||||
|
0 1 UPDATE
|
||||||
|
1 0 INSERT
|
||||||
|
1 1 DELETE
|
||||||
|
|
||||||
|
|
||||||
|
###########
|
||||||
|
# #
|
||||||
|
┌────────────────────────────▶# upd #─────────────────────┐
|
||||||
|
│ ## ## │
|
||||||
|
│ ######### │
|
||||||
|
levIns=1 │ │
|
||||||
|
fnc[0]=0 │ │ any
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ ########### │
|
||||||
|
│ levIns=1 # # │
|
||||||
|
levIns=0 │ is0=1 ┌────────────▶# old0 #────────┐ │ any
|
||||||
|
┌─────┐ │ fnc[0]=1│ ## ## │ │ ┌──────┐
|
||||||
|
│ │ │ │ ######### │ any │ │ │
|
||||||
|
│ ▼ │ │ │ ▼ ▼ │
|
||||||
|
│ ########### │ │ ########### │
|
||||||
|
│ # # ────────────┘ └────────▶# #│
|
||||||
|
└──# top # # na #
|
||||||
|
## ## ───────────────────┐ levIns=1 ┌──▶## ##
|
||||||
|
######### │ is0=0 │ #########
|
||||||
|
│ │ fnc[0]=1 │
|
||||||
|
│ │ xor=1 ########### │ any
|
||||||
|
│ └──────────────────▶# # │
|
||||||
|
│ # new1 #──┘
|
||||||
|
│ ## ##
|
||||||
|
└────────────────────────────────┐ #########
|
||||||
|
levIns=1 │ ▲
|
||||||
|
is0=0 │ ┌─────┘
|
||||||
|
fnc[0]=1 │ ###########│ xor=1
|
||||||
|
xor=0 │ # #
|
||||||
|
▼# btn #
|
||||||
|
## ##
|
||||||
|
#########◀───────┐
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
└────────────┘
|
||||||
|
xor=0
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
template SMTProcessorSM() {
|
||||||
|
signal input xor;
|
||||||
|
signal input is0;
|
||||||
|
signal input levIns;
|
||||||
|
signal input fnc[2];
|
||||||
|
|
||||||
|
signal input prev_top;
|
||||||
|
signal input prev_old0;
|
||||||
|
signal input prev_bot;
|
||||||
|
signal input prev_new1;
|
||||||
|
signal input prev_na;
|
||||||
|
signal input prev_upd;
|
||||||
|
|
||||||
|
signal output st_top;
|
||||||
|
signal output st_old0;
|
||||||
|
signal output st_bot;
|
||||||
|
signal output st_new1;
|
||||||
|
signal output st_na;
|
||||||
|
signal output st_upd;
|
||||||
|
|
||||||
|
signal aux1;
|
||||||
|
signal aux2;
|
||||||
|
|
||||||
|
aux1 <== prev_top * levIns;
|
||||||
|
aux2 <== aux1*fnc[0]; // prev_top * levIns * fnc[0]
|
||||||
|
|
||||||
|
// st_top = prev_top*(1-levIns)
|
||||||
|
// = + prev_top
|
||||||
|
// - prev_top * levIns = aux1
|
||||||
|
|
||||||
|
st_top <== prev_top - aux1;
|
||||||
|
|
||||||
|
// st_old0 = prev_top * levIns * is0 * fnc[0]
|
||||||
|
// = + prev_top * levIns * is0 * fnc[0] = aux2 * is0
|
||||||
|
|
||||||
|
st_old0 <== aux2 * is0; // prev_top * levIns * is0 * fnc[0]
|
||||||
|
|
||||||
|
// st_new1 = prev_top * levIns * (1-is0)*fnc[0] * xor + prev_bot*xor =
|
||||||
|
// = + prev_top * levIns * fnc[0] * xor = aux2 * xor
|
||||||
|
// - prev_top * levIns * is0 * fnc[0] * xor = st_old0 * xor
|
||||||
|
// + prev_bot * xor = prev_bot * xor
|
||||||
|
|
||||||
|
st_new1 <== (aux2 - st_old0 + prev_bot)*xor;
|
||||||
|
|
||||||
|
|
||||||
|
// st_bot = prev_top * levIns * (1-is0)*fnc[0] * (1-xor) + prev_bot*(1-xor);
|
||||||
|
// = + prev_top * levIns * fnc[0]
|
||||||
|
// - prev_top * levIns * is0 * fnc[0]
|
||||||
|
// - prev_top * levIns * fnc[0] * xor
|
||||||
|
// + prev_top * levIns * is0 * fnc[0] * xor
|
||||||
|
// + prev_bot
|
||||||
|
// - prev_bot * xor
|
||||||
|
|
||||||
|
st_bot <== (1-xor) * (aux2 - st_old0 + prev_bot)
|
||||||
|
|
||||||
|
|
||||||
|
// st_upd = prev_top * (1-fnc[0]) *levIns;
|
||||||
|
// = + prev_top * levIns
|
||||||
|
// - prev_top * levIns * fnc[0]
|
||||||
|
|
||||||
|
st_upd <== aux1 - aux2
|
||||||
|
|
||||||
|
// st_na = prev_new1 + prev_old0 + prev_na + prev_upd;
|
||||||
|
// = + prev_new1
|
||||||
|
// + prev_old0
|
||||||
|
// + prev_na
|
||||||
|
// + prev_upd
|
||||||
|
|
||||||
|
st_na <== prev_new1 + prev_old0 + prev_na + prev_upd;
|
||||||
|
|
||||||
|
}
|
||||||
135
circuits/smt/smtverifier.circom
Normal file
135
circuits/smt/smtverifier.circom
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
SMTVerifier is a component to verify inclusion/exclusion of an element in the tree
|
||||||
|
|
||||||
|
|
||||||
|
fnc: 0 -> VERIFY INCLUSION
|
||||||
|
1 -> VERIFY NOT INCLUSION
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
include "../gates.circom";
|
||||||
|
include "../bitify.circom";
|
||||||
|
include "../comparators.circom";
|
||||||
|
include "../switcher.circom";
|
||||||
|
include "smtlevins.circom";
|
||||||
|
include "smtverifierlevel.circom";
|
||||||
|
include "smtverifiersm.circom";
|
||||||
|
include "smthash.circom";
|
||||||
|
|
||||||
|
template SMTVerifier(nLevels) {
|
||||||
|
signal input enabled;
|
||||||
|
signal input root;
|
||||||
|
signal input siblings[nLevels];
|
||||||
|
signal input oldKey;
|
||||||
|
signal input oldValue;
|
||||||
|
signal input isOld0;
|
||||||
|
signal input key;
|
||||||
|
signal input value;
|
||||||
|
signal input fnc;
|
||||||
|
|
||||||
|
component hash1Old = SMTHash1();
|
||||||
|
hash1Old.key <== oldKey;
|
||||||
|
hash1Old.value <== oldValue;
|
||||||
|
|
||||||
|
component hash1New = SMTHash1();
|
||||||
|
hash1New.key <== key;
|
||||||
|
hash1New.value <== value;
|
||||||
|
|
||||||
|
component n2bOld = Num2Bits_strict();
|
||||||
|
component n2bNew = Num2Bits_strict();
|
||||||
|
|
||||||
|
n2bOld.in <== oldKey;
|
||||||
|
n2bNew.in <== key;
|
||||||
|
|
||||||
|
component smtLevIns = SMTLevIns(nLevels);
|
||||||
|
for (var i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i];
|
||||||
|
smtLevIns.enabled <== enabled;
|
||||||
|
|
||||||
|
component sm[nLevels];
|
||||||
|
for (var i=0; i<nLevels; i++) {
|
||||||
|
sm[i] = SMTVerifierSM();
|
||||||
|
if (i==0) {
|
||||||
|
sm[i].prev_top <== enabled;
|
||||||
|
sm[i].prev_i0 <== 0;
|
||||||
|
sm[i].prev_inew <== 0;
|
||||||
|
sm[i].prev_iold <== 0;
|
||||||
|
sm[i].prev_na <== 1-enabled;
|
||||||
|
} else {
|
||||||
|
sm[i].prev_top <== sm[i-1].st_top;
|
||||||
|
sm[i].prev_i0 <== sm[i-1].st_i0;
|
||||||
|
sm[i].prev_inew <== sm[i-1].st_inew;
|
||||||
|
sm[i].prev_iold <== sm[i-1].st_iold;
|
||||||
|
sm[i].prev_na <== sm[i-1].st_na;
|
||||||
|
}
|
||||||
|
sm[i].is0 <== isOld0;
|
||||||
|
sm[i].fnc <== fnc;
|
||||||
|
sm[i].levIns <== smtLevIns.levIns[i];
|
||||||
|
}
|
||||||
|
sm[nLevels-1].st_na + sm[nLevels-1].st_iold + sm[nLevels-1].st_inew + sm[nLevels-1].st_i0 === 1;
|
||||||
|
|
||||||
|
component levels[nLevels];
|
||||||
|
for (var i=nLevels-1; i != -1; i--) {
|
||||||
|
levels[i] = SMTVerifierLevel();
|
||||||
|
|
||||||
|
levels[i].st_top <== sm[i].st_top;
|
||||||
|
levels[i].st_i0 <== sm[i].st_i0;
|
||||||
|
levels[i].st_inew <== sm[i].st_inew;
|
||||||
|
levels[i].st_iold <== sm[i].st_iold;
|
||||||
|
levels[i].st_na <== sm[i].st_na;
|
||||||
|
|
||||||
|
levels[i].sibling <== siblings[i];
|
||||||
|
levels[i].old1leaf <== hash1Old.out;
|
||||||
|
levels[i].new1leaf <== hash1New.out;
|
||||||
|
|
||||||
|
levels[i].lrbit <== n2bNew.out[i];
|
||||||
|
if (i==nLevels-1) {
|
||||||
|
levels[i].child <== 0;
|
||||||
|
} else {
|
||||||
|
levels[i].child <== levels[i+1].root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Check that if checking for non inclussuin and isOld0==0 then key!=old
|
||||||
|
component areKeyEquals = IsEqual();
|
||||||
|
areKeyEquals.in[0] <== oldKey;
|
||||||
|
areKeyEquals.in[1] <== key;
|
||||||
|
|
||||||
|
component keysOk = MultiAND(4);
|
||||||
|
keysOk.in[0] <== fnc;
|
||||||
|
keysOk.in[1] <== 1-isOld0;
|
||||||
|
keysOk.in[2] <== areKeyEquals.out;
|
||||||
|
keysOk.in[3] <== enabled;
|
||||||
|
|
||||||
|
keysOk.out === 0;
|
||||||
|
|
||||||
|
// Check the root
|
||||||
|
component checkRoot = ForceEqualIfEnabled();
|
||||||
|
checkRoot.enabled <== enabled;
|
||||||
|
checkRoot.in[0] <== levels[0].root;
|
||||||
|
checkRoot.in[1] <== root;
|
||||||
|
|
||||||
|
// levels[0].root === root;
|
||||||
|
|
||||||
|
}
|
||||||
71
circuits/smt/smtverifierlevel.circom
Normal file
71
circuits/smt/smtverifierlevel.circom
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******
|
||||||
|
|
||||||
|
SMTVerifierLevel
|
||||||
|
|
||||||
|
This circuit has 1 hash
|
||||||
|
|
||||||
|
Outputs according to the state.
|
||||||
|
|
||||||
|
State root
|
||||||
|
===== =======
|
||||||
|
top H'(child, sibling)
|
||||||
|
i0 0
|
||||||
|
iold old1leaf
|
||||||
|
inew new1leaf
|
||||||
|
na 0
|
||||||
|
|
||||||
|
H' is the Hash function with the inputs shifted acordingly.
|
||||||
|
|
||||||
|
*****/
|
||||||
|
|
||||||
|
|
||||||
|
template SMTVerifierLevel() {
|
||||||
|
signal input st_top;
|
||||||
|
signal input st_i0;
|
||||||
|
signal input st_iold;
|
||||||
|
signal input st_inew;
|
||||||
|
signal input st_na;
|
||||||
|
|
||||||
|
signal output root;
|
||||||
|
signal input sibling;
|
||||||
|
signal input old1leaf;
|
||||||
|
signal input new1leaf;
|
||||||
|
signal input lrbit;
|
||||||
|
signal input child;
|
||||||
|
|
||||||
|
signal aux[2];
|
||||||
|
|
||||||
|
component proofHash = SMTHash2();
|
||||||
|
component switcher = Switcher();
|
||||||
|
|
||||||
|
switcher.L <== child;
|
||||||
|
switcher.R <== sibling;
|
||||||
|
|
||||||
|
switcher.sel <== lrbit;
|
||||||
|
proofHash.L <== switcher.outL;
|
||||||
|
proofHash.R <== switcher.outR;
|
||||||
|
|
||||||
|
aux[0] <== proofHash.out * st_top;
|
||||||
|
aux[1] <== old1leaf*st_iold;
|
||||||
|
|
||||||
|
root <== aux[0] + aux[1] + new1leaf*st_inew;
|
||||||
|
}
|
||||||
105
circuits/smt/smtverifiersm.circom
Normal file
105
circuits/smt/smtverifiersm.circom
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Each level in the SMTVerifier has a state.
|
||||||
|
|
||||||
|
This is the state machine.
|
||||||
|
|
||||||
|
The signals are
|
||||||
|
|
||||||
|
levIns: 1 if we are in the level where the insertion should happen
|
||||||
|
xor: 1 if the bitKey of the old and new keys are different in this level
|
||||||
|
is0: Input that indicates that the oldKey is 0
|
||||||
|
fnc: 0 -> VERIFY INCLUSION
|
||||||
|
1 -> VERIFY NOT INCLUSION
|
||||||
|
|
||||||
|
err state is not a state itself. It's a lack of state.
|
||||||
|
|
||||||
|
The end of the last level will have to be `na`
|
||||||
|
|
||||||
|
levIns=0 any
|
||||||
|
┌────┐ ┌────┐
|
||||||
|
│ │ │ │
|
||||||
|
│ ▼ levIns=1 ▼ │
|
||||||
|
│ ########### is0=1 ########### ########### │
|
||||||
|
│ # # fnc=1 # # any # # │
|
||||||
|
└──# top # ─────────────────────▶# i0 #───────────────▶# na #──┘
|
||||||
|
## ## ──────────┐ ## ## ┌───────▶## ##
|
||||||
|
########─────────────┐│ ######### │┌────────▶#########
|
||||||
|
││ levIns=1 ││
|
||||||
|
││ is0=0 ########### ││
|
||||||
|
││ fnc=1 # # any│
|
||||||
|
│└──────────▶ # iold #────────┘│
|
||||||
|
│ ## ## │
|
||||||
|
│ ######### │
|
||||||
|
│ │
|
||||||
|
│ levIns=1 ########### │
|
||||||
|
│ fnc=0 # # any
|
||||||
|
└────────────▶# inew #─────────┘
|
||||||
|
## ##
|
||||||
|
#########
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
template SMTVerifierSM() {
|
||||||
|
signal input is0;
|
||||||
|
signal input levIns;
|
||||||
|
signal input fnc;
|
||||||
|
|
||||||
|
signal input prev_top;
|
||||||
|
signal input prev_i0;
|
||||||
|
signal input prev_iold;
|
||||||
|
signal input prev_inew;
|
||||||
|
signal input prev_na;
|
||||||
|
|
||||||
|
signal output st_top;
|
||||||
|
signal output st_i0;
|
||||||
|
signal output st_iold;
|
||||||
|
signal output st_inew;
|
||||||
|
signal output st_na;
|
||||||
|
|
||||||
|
signal prev_top_lev_ins;
|
||||||
|
signal prev_top_lev_ins_fnc;
|
||||||
|
|
||||||
|
prev_top_lev_ins <== prev_top * levIns;
|
||||||
|
prev_top_lev_ins_fnc <== prev_top_lev_ins*fnc; // prev_top * levIns * fnc
|
||||||
|
|
||||||
|
// st_top = prev_top * (1-levIns)
|
||||||
|
// = + prev_top
|
||||||
|
// - prev_top * levIns
|
||||||
|
st_top <== prev_top - prev_top_lev_ins;
|
||||||
|
|
||||||
|
// st_inew = prev_top * levIns * (1-fnc)
|
||||||
|
// = + prev_top * levIns
|
||||||
|
// - prev_top * levIns * fnc
|
||||||
|
st_inew <== prev_top_lev_ins - prev_top_lev_ins_fnc;
|
||||||
|
|
||||||
|
// st_iold = prev_top * levIns * (1-is0)*fnc
|
||||||
|
// = + prev_top * levIns * fnc
|
||||||
|
// - prev_top * levIns * fnc * is0
|
||||||
|
st_iold <== prev_top_lev_ins_fnc * (1 - is0);
|
||||||
|
|
||||||
|
// st_i0 = prev_top * levIns * is0
|
||||||
|
// = + prev_top * levIns * is0
|
||||||
|
st_i0 <== prev_top_lev_ins * is0;
|
||||||
|
|
||||||
|
st_na <== prev_na + prev_inew + prev_iold + prev_i0;
|
||||||
|
}
|
||||||
40
circuits/switcher.circom
Normal file
40
circuits/switcher.circom
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0KIMS association.
|
||||||
|
|
||||||
|
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||||
|
|
||||||
|
circom 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.
|
||||||
|
|
||||||
|
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Assume sel is binary.
|
||||||
|
|
||||||
|
If sel == 0 then outL = L and outR=R
|
||||||
|
If sel == 1 then outL = R and outR=L
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
template Switcher() {
|
||||||
|
signal input sel;
|
||||||
|
signal input L;
|
||||||
|
signal input R;
|
||||||
|
signal output outL;
|
||||||
|
signal output outR;
|
||||||
|
|
||||||
|
signal aux;
|
||||||
|
|
||||||
|
aux <== (R-L)*sel; // We create aux in order to have only one multiplication
|
||||||
|
outL <== aux + L;
|
||||||
|
outR <== -aux + R;
|
||||||
|
}
|
||||||
BIN
doc/rollup_tree.monopic
Normal file
BIN
doc/rollup_tree.monopic
Normal file
Binary file not shown.
BIN
doc/rollup_tx.monopic
Normal file
BIN
doc/rollup_tx.monopic
Normal file
Binary file not shown.
BIN
doc/root_transfer.monopic
Normal file
BIN
doc/root_transfer.monopic
Normal file
Binary file not shown.
BIN
doc/smt_diagram_0.monopic
Normal file
BIN
doc/smt_diagram_0.monopic
Normal file
Binary file not shown.
BIN
doc/smt_diagram_1.monopic
Normal file
BIN
doc/smt_diagram_1.monopic
Normal file
Binary file not shown.
BIN
doc/smt_hash.monopic
Normal file
BIN
doc/smt_hash.monopic
Normal file
Binary file not shown.
BIN
doc/smt_levins.monopic
Normal file
BIN
doc/smt_levins.monopic
Normal file
Binary file not shown.
BIN
doc/smt_sm.monopic
Normal file
BIN
doc/smt_sm.monopic
Normal file
Binary file not shown.
BIN
doc/smt_verifier_sm.monopic
Normal file
BIN
doc/smt_verifier_sm.monopic
Normal file
Binary file not shown.
BIN
doc/voting.monopic
Normal file
BIN
doc/voting.monopic
Normal file
Binary file not shown.
4
index.js
Normal file
4
index.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
exports.smt = require("./src/smt");
|
||||||
|
exports.eddsa = require("./src/eddsa");
|
||||||
|
exports.mimc7 = require("./src/mimc7");
|
||||||
|
exports.babyJub = require("./src/babyjub");
|
||||||
8785
package-lock.json
generated
8785
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "cirpedersen",
|
"name": "circomlib",
|
||||||
"version": "0.0.2",
|
"version": "0.0.6",
|
||||||
"description": "Pesersen Circuit for Circom",
|
"description": "Basic circuits library for Circom",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
"test": "test"
|
"test": "test"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "mocha"
|
"test": "mocha --max-old-space-size=4000"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"pedersen",
|
"pedersen",
|
||||||
@@ -17,15 +17,21 @@
|
|||||||
"circom",
|
"circom",
|
||||||
"zksnark"
|
"zksnark"
|
||||||
],
|
],
|
||||||
"author": "Jordi Baylina",
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/iden3/circomlib.git"
|
||||||
|
},
|
||||||
|
"author": "0Kims",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"blake-hash": "^1.1.0",
|
"blake-hash": "^1.1.0",
|
||||||
"circom": "0.0.20",
|
"snarkjs": "0.1.11",
|
||||||
"snarkjs": "0.1.6"
|
"web3": "^1.0.0-beta.36"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"circom": "0.0.24",
|
||||||
"eslint-plugin-mocha": "^5.2.0",
|
"eslint-plugin-mocha": "^5.2.0",
|
||||||
|
"ganache-cli": "^6.2.3",
|
||||||
"mocha": "^5.2.0"
|
"mocha": "^5.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
105
src/babyjub.js
Normal file
105
src/babyjub.js
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
const bn128 = require("snarkjs").bn128;
|
||||||
|
const bigInt = require("snarkjs").bigInt;
|
||||||
|
|
||||||
|
exports.addPoint = addPoint;
|
||||||
|
exports.mulPointEscalar = mulPointEscalar;
|
||||||
|
exports.inCurve = inCurve;
|
||||||
|
exports.inSubgroup = inSubgroup;
|
||||||
|
exports.packPoint = packPoint;
|
||||||
|
exports.unpackPoint = unpackPoint;
|
||||||
|
exports.Base8 = [
|
||||||
|
bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
||||||
|
bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475")
|
||||||
|
];
|
||||||
|
exports.order = bigInt("21888242871839275222246405745257275088614511777268538073601725287587578984328");
|
||||||
|
exports.subOrder = exports.order.shr(3);
|
||||||
|
exports.p = bn128.r;
|
||||||
|
|
||||||
|
|
||||||
|
function addPoint(a,b) {
|
||||||
|
const q = bn128.r;
|
||||||
|
const cta = bigInt("168700");
|
||||||
|
const d = bigInt("168696");
|
||||||
|
|
||||||
|
const res = [];
|
||||||
|
res[0] = bigInt((a[0]*b[1] + b[0]*a[1]) * bigInt(bigInt("1") + d*a[0]*b[0]*a[1]*b[1]).inverse(q)).affine(q);
|
||||||
|
res[1] = bigInt((a[1]*b[1] - cta*a[0]*b[0]) * bigInt(bigInt("1") - d*a[0]*b[0]*a[1]*b[1]).inverse(q)).affine(q);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mulPointEscalar(base, e) {
|
||||||
|
let res = [bigInt("0"),bigInt("1")];
|
||||||
|
let rem = bigInt(e);
|
||||||
|
let exp = base;
|
||||||
|
|
||||||
|
while (! rem.isZero()) {
|
||||||
|
if (rem.isOdd()) {
|
||||||
|
res = addPoint(res, exp);
|
||||||
|
}
|
||||||
|
exp = addPoint(exp, exp);
|
||||||
|
rem = rem.shr(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function inSubgroup(P) {
|
||||||
|
if (!inCurve(P)) return false;
|
||||||
|
const res= mulPointEscalar(P, exports.subOrder);
|
||||||
|
return (res[0].equals(bigInt(0))) && (res[1].equals(bigInt(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function inCurve(P) {
|
||||||
|
const F = bn128.Fr;
|
||||||
|
|
||||||
|
const a = bigInt("168700");
|
||||||
|
const d = bigInt("168696");
|
||||||
|
|
||||||
|
const x2 = F.square(P[0]);
|
||||||
|
const y2 = F.square(P[1]);
|
||||||
|
|
||||||
|
if (!F.equals(
|
||||||
|
F.add(F.mul(a, x2), y2),
|
||||||
|
F.add(F.one, F.mul(F.mul(x2, y2), d)))) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function packPoint(P) {
|
||||||
|
const buff = bigInt.leInt2Buff(P[1], 32);
|
||||||
|
if (P[0].greater(exports.p.shr(1))) {
|
||||||
|
buff[31] = buff[31] | 0x80;
|
||||||
|
}
|
||||||
|
return buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
function unpackPoint(_buff) {
|
||||||
|
const F = bn128.Fr;
|
||||||
|
|
||||||
|
const buff = Buffer.from(_buff);
|
||||||
|
let sign = false;
|
||||||
|
const P = new Array(2);
|
||||||
|
if (buff[31] & 0x80) {
|
||||||
|
sign = true;
|
||||||
|
buff[31] = buff[31] & 0x7F;
|
||||||
|
}
|
||||||
|
P[1] = bigInt.leBuff2int(buff);
|
||||||
|
if (P[1].greaterOrEquals(exports.p)) return null;
|
||||||
|
|
||||||
|
const a = bigInt("168700");
|
||||||
|
const d = bigInt("168696");
|
||||||
|
|
||||||
|
const y2 = F.square(P[1]);
|
||||||
|
|
||||||
|
let x = F.sqrt(F.div(
|
||||||
|
F.sub(F.one, y2),
|
||||||
|
F.sub(a, F.mul(d, y2))));
|
||||||
|
|
||||||
|
if (x == null) return null;
|
||||||
|
|
||||||
|
if (sign) x = F.neg(x);
|
||||||
|
|
||||||
|
P[0] = F.affine(x);
|
||||||
|
|
||||||
|
return P;
|
||||||
|
}
|
||||||
132
src/eddsa.js
Normal file
132
src/eddsa.js
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
const createBlakeHash = require("blake-hash");
|
||||||
|
const bigInt = require("snarkjs").bigInt;
|
||||||
|
const babyJub = require("./babyjub");
|
||||||
|
const pedersenHash = require("./pedersenHash").hash;
|
||||||
|
const mimc7 = require("./mimc7");
|
||||||
|
|
||||||
|
exports.prv2pub= prv2pub;
|
||||||
|
exports.sign = sign;
|
||||||
|
exports.signMiMC = signMiMC;
|
||||||
|
exports.verify = verify;
|
||||||
|
exports.verifyMiMC = verifyMiMC;
|
||||||
|
exports.packSignature = packSignature;
|
||||||
|
exports.unpackSignature = unpackSignature;
|
||||||
|
exports.pruneBuffer = pruneBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
function pruneBuffer(_buff) {
|
||||||
|
const buff = Buffer.from(_buff);
|
||||||
|
buff[0] = buff[0] & 0xF8;
|
||||||
|
buff[31] = buff[31] & 0x7F;
|
||||||
|
buff[31] = buff[31] | 0x40;
|
||||||
|
return buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
function prv2pub(prv) {
|
||||||
|
const sBuff = pruneBuffer(createBlakeHash("blake512").update(prv).digest().slice(0,32));
|
||||||
|
let s = bigInt.leBuff2int(sBuff);
|
||||||
|
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
|
||||||
|
return A;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sign(prv, msg) {
|
||||||
|
const h1 = createBlakeHash("blake512").update(prv).digest();
|
||||||
|
const sBuff = pruneBuffer(h1.slice(0,32));
|
||||||
|
const s = bigInt.leBuff2int(sBuff);
|
||||||
|
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
|
||||||
|
|
||||||
|
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msg])).digest();
|
||||||
|
let r = bigInt.leBuff2int(rBuff);
|
||||||
|
r = r.mod(babyJub.subOrder);
|
||||||
|
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
|
||||||
|
const R8p = babyJub.packPoint(R8);
|
||||||
|
const Ap = babyJub.packPoint(A);
|
||||||
|
const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
|
||||||
|
const hm = bigInt.leBuff2int(hmBuff);
|
||||||
|
const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
|
||||||
|
return {
|
||||||
|
R8: R8,
|
||||||
|
S: S
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function signMiMC(prv, msg) {
|
||||||
|
const h1 = createBlakeHash("blake512").update(prv).digest();
|
||||||
|
const sBuff = pruneBuffer(h1.slice(0,32));
|
||||||
|
const s = bigInt.leBuff2int(sBuff);
|
||||||
|
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
|
||||||
|
|
||||||
|
const msgBuff = bigInt.leInt2Buff(msg, 32);
|
||||||
|
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
|
||||||
|
let r = bigInt.leBuff2int(rBuff);
|
||||||
|
r = r.mod(babyJub.subOrder);
|
||||||
|
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
|
||||||
|
const hm = mimc7.multiHash([R8[0], R8[1], A[0], A[1], msg]);
|
||||||
|
const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
|
||||||
|
return {
|
||||||
|
R8: R8,
|
||||||
|
S: S
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function verify(msg, sig, A) {
|
||||||
|
// Check parameters
|
||||||
|
if (typeof sig != "object") return false;
|
||||||
|
if (!Array.isArray(sig.R8)) return false;
|
||||||
|
if (sig.R8.length!= 2) return false;
|
||||||
|
if (!babyJub.inCurve(sig.R8)) return false;
|
||||||
|
if (!Array.isArray(A)) return false;
|
||||||
|
if (A.length!= 2) return false;
|
||||||
|
if (!babyJub.inCurve(A)) return false;
|
||||||
|
if (sig.S>= babyJub.subOrder) return false;
|
||||||
|
|
||||||
|
const R8p = babyJub.packPoint(sig.R8);
|
||||||
|
const Ap = babyJub.packPoint(A);
|
||||||
|
const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
|
||||||
|
const hm = bigInt.leBuff2int(hmBuff);
|
||||||
|
|
||||||
|
const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
|
||||||
|
let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
|
||||||
|
Pright = babyJub.addPoint(sig.R8, Pright);
|
||||||
|
|
||||||
|
if (!Pleft[0].equals(Pright[0])) return false;
|
||||||
|
if (!Pleft[1].equals(Pright[1])) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function verifyMiMC(msg, sig, A) {
|
||||||
|
// Check parameters
|
||||||
|
if (typeof sig != "object") return false;
|
||||||
|
if (!Array.isArray(sig.R8)) return false;
|
||||||
|
if (sig.R8.length!= 2) return false;
|
||||||
|
if (!babyJub.inCurve(sig.R8)) return false;
|
||||||
|
if (!Array.isArray(A)) return false;
|
||||||
|
if (A.length!= 2) return false;
|
||||||
|
if (!babyJub.inCurve(A)) return false;
|
||||||
|
if (sig.S>= babyJub.subOrder) return false;
|
||||||
|
|
||||||
|
const hm = mimc7.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
|
||||||
|
|
||||||
|
const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
|
||||||
|
let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
|
||||||
|
Pright = babyJub.addPoint(sig.R8, Pright);
|
||||||
|
|
||||||
|
if (!Pleft[0].equals(Pright[0])) return false;
|
||||||
|
if (!Pleft[1].equals(Pright[1])) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function packSignature(sig) {
|
||||||
|
const R8p = babyJub.packPoint(sig.R8);
|
||||||
|
const Sp = bigInt.leInt2Buff(sig.S, 32);
|
||||||
|
return Buffer.concat([R8p, Sp]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function unpackSignature(sigBuff) {
|
||||||
|
return {
|
||||||
|
R8: babyJub.unpackPoint(sigBuff.slice(0,32)),
|
||||||
|
S: bigInt.leBuff2int(sigBuff.slice(32,64))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
193
src/evmasm.js
Normal file
193
src/evmasm.js
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
// Copyright (c) 2018 Jordi Baylina
|
||||||
|
// License: LGPL-3.0+
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
const Web3Utils = require("web3-utils");
|
||||||
|
|
||||||
|
class Contract {
|
||||||
|
constructor() {
|
||||||
|
this.code = [];
|
||||||
|
this.labels = {};
|
||||||
|
this.pendingLabels = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
createTxData() {
|
||||||
|
let C;
|
||||||
|
|
||||||
|
// Check all labels are defined
|
||||||
|
const pendingLabels = Object.keys(this.pendingLabels);
|
||||||
|
if (pendingLabels.length>0) {
|
||||||
|
throw new Error("Lables not defined: "+ pendingLabels.join(", "));
|
||||||
|
}
|
||||||
|
|
||||||
|
let setLoaderLength = 0;
|
||||||
|
let genLoadedLength = -1;
|
||||||
|
|
||||||
|
while (genLoadedLength!=setLoaderLength) {
|
||||||
|
setLoaderLength = genLoadedLength;
|
||||||
|
C = new module.exports();
|
||||||
|
C.codesize();
|
||||||
|
C.push(setLoaderLength);
|
||||||
|
C.push(0);
|
||||||
|
C.codecopy();
|
||||||
|
|
||||||
|
C.push(this.code.length);
|
||||||
|
C.push(0);
|
||||||
|
C.return();
|
||||||
|
genLoadedLength = C.code.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Web3Utils.bytesToHex(C.code.concat(this.code));
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() { this.code.push(0x00); }
|
||||||
|
add() { this.code.push(0x01); }
|
||||||
|
mul() { this.code.push(0x02); }
|
||||||
|
sub() { this.code.push(0x03); }
|
||||||
|
div() { this.code.push(0x04); }
|
||||||
|
sdiv() { this.code.push(0x05); }
|
||||||
|
mod() { this.code.push(0x06); }
|
||||||
|
smod() { this.code.push(0x07); }
|
||||||
|
addmod() { this.code.push(0x08); }
|
||||||
|
mulmod() { this.code.push(0x09); }
|
||||||
|
exp() { this.code.push(0x0a); }
|
||||||
|
signextend() { this.code.push(0x0b); }
|
||||||
|
|
||||||
|
lt() { this.code.push(0x10); }
|
||||||
|
gt() { this.code.push(0x11); }
|
||||||
|
slt() { this.code.push(0x12); }
|
||||||
|
sgt() { this.code.push(0x13); }
|
||||||
|
eq() { this.code.push(0x14); }
|
||||||
|
iszero() { this.code.push(0x15); }
|
||||||
|
and() { this.code.push(0x16); }
|
||||||
|
or() { this.code.push(0x17); }
|
||||||
|
shor() { this.code.push(0x18); }
|
||||||
|
not() { this.code.push(0x19); }
|
||||||
|
byte() { this.code.push(0x1a); }
|
||||||
|
|
||||||
|
keccak() { this.code.push(0x20); }
|
||||||
|
sha3() { this.code.push(0x20); } // alias
|
||||||
|
|
||||||
|
address() { this.code.push(0x30); }
|
||||||
|
balance() { this.code.push(0x31); }
|
||||||
|
origin() { this.code.push(0x32); }
|
||||||
|
caller() { this.code.push(0x33); }
|
||||||
|
callvalue() { this.code.push(0x34); }
|
||||||
|
calldataload() { this.code.push(0x35); }
|
||||||
|
calldatasize() { this.code.push(0x36); }
|
||||||
|
calldatacopy() { this.code.push(0x37); }
|
||||||
|
codesize() { this.code.push(0x38); }
|
||||||
|
codecopy() { this.code.push(0x39); }
|
||||||
|
gasprice() { this.code.push(0x3a); }
|
||||||
|
extcodesize() { this.code.push(0x3b); }
|
||||||
|
extcodecopy() { this.code.push(0x3c); }
|
||||||
|
returndatasize() { this.code.push(0x3d); }
|
||||||
|
returndatacopy() { this.code.push(0x3e); }
|
||||||
|
|
||||||
|
blockhash() { this.code.push(0x40); }
|
||||||
|
coinbase() { this.code.push(0x41); }
|
||||||
|
timestamp() { this.code.push(0x42); }
|
||||||
|
number() { this.code.push(0x43); }
|
||||||
|
difficulty() { this.code.push(0x44); }
|
||||||
|
gaslimit() { this.code.push(0x45); }
|
||||||
|
|
||||||
|
pop() { this.code.push(0x50); }
|
||||||
|
mload() { this.code.push(0x51); }
|
||||||
|
mstore() { this.code.push(0x52); }
|
||||||
|
mstore8() { this.code.push(0x53); }
|
||||||
|
sload() { this.code.push(0x54); }
|
||||||
|
sstore() { this.code.push(0x55); }
|
||||||
|
|
||||||
|
_pushLabel(label) {
|
||||||
|
if (typeof this.labels[label] != "undefined") {
|
||||||
|
this.push(this.labels[label]);
|
||||||
|
} else {
|
||||||
|
this.pendingLabels[label] = this.pendingLabels[label] || [];
|
||||||
|
this.pendingLabels[label].push(this.code.length);
|
||||||
|
this.push("0x000000");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_fillLabel(label) {
|
||||||
|
if (!this.pendingLabels[label]) return;
|
||||||
|
|
||||||
|
let dst = this.labels[label];
|
||||||
|
|
||||||
|
const dst3 = [dst >> 16, (dst >> 8) & 0xFF, dst & 0xFF];
|
||||||
|
|
||||||
|
this.pendingLabels[label].forEach((p) => {
|
||||||
|
for (let i=0; i<3; i++) {
|
||||||
|
this.code[p+i+1] = dst3[i];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
delete this.pendingLabels[label];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
jmp(label) {
|
||||||
|
this._pushLabel(label);
|
||||||
|
this.code.push(0x56);
|
||||||
|
}
|
||||||
|
|
||||||
|
jmpi(label) {
|
||||||
|
this._pushLabel(label);
|
||||||
|
this.code.push(0x57);
|
||||||
|
}
|
||||||
|
|
||||||
|
pc() { this.code.push(0x58); }
|
||||||
|
msize() { this.code.push(0x59); }
|
||||||
|
gas() { this.code.push(0x5a); }
|
||||||
|
label(name) {
|
||||||
|
if (typeof this.labels[name] != "undefined") {
|
||||||
|
throw new Error("Label already defined");
|
||||||
|
}
|
||||||
|
this.labels[name] = this.code.length;
|
||||||
|
this.code.push(0x5b);
|
||||||
|
|
||||||
|
this._fillLabel(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
push(data) {
|
||||||
|
const d = Web3Utils.hexToBytes(Web3Utils.toHex(data));
|
||||||
|
if (d.length == 0 || d.length > 32) {
|
||||||
|
throw new Error("Assertion failed");
|
||||||
|
}
|
||||||
|
this.code = this.code.concat([0x5F + d.length], d);
|
||||||
|
}
|
||||||
|
|
||||||
|
dup(n) {
|
||||||
|
if (n < 0 || n >= 16) {
|
||||||
|
throw new Error("Assertion failed");
|
||||||
|
}
|
||||||
|
this.code.push(0x80 + n);
|
||||||
|
}
|
||||||
|
|
||||||
|
swap(n) {
|
||||||
|
if (n < 1 || n > 16) {
|
||||||
|
throw new Error("Assertion failed");
|
||||||
|
}
|
||||||
|
this.code.push(0x8f + n);
|
||||||
|
}
|
||||||
|
|
||||||
|
log0() { this.code.push(0xa0); }
|
||||||
|
log1() { this.code.push(0xa1); }
|
||||||
|
log2() { this.code.push(0xa2); }
|
||||||
|
log3() { this.code.push(0xa3); }
|
||||||
|
log4() { this.code.push(0xa4); }
|
||||||
|
|
||||||
|
create() { this.code.push(0xf0); }
|
||||||
|
call() { this.code.push(0xf1); }
|
||||||
|
callcode() { this.code.push(0xf2); }
|
||||||
|
return() { this.code.push(0xf3); }
|
||||||
|
delegatecall() { this.code.push(0xf4); }
|
||||||
|
|
||||||
|
staticcall() { this.code.push(0xfa); }
|
||||||
|
revert() { this.code.push(0xfd); }
|
||||||
|
invalid() { this.code.push(0xfe); }
|
||||||
|
selfdestruct() { this.code.push(0xff); }
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Contract;
|
||||||
|
|
||||||
64
src/mimc7.js
Normal file
64
src/mimc7.js
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
const bn128 = require("snarkjs").bn128;
|
||||||
|
const bigInt = require("snarkjs").bigInt;
|
||||||
|
const Web3Utils = require("web3-utils");
|
||||||
|
const F = bn128.Fr;
|
||||||
|
|
||||||
|
const SEED = "mimc";
|
||||||
|
const NROUNDS = 91;
|
||||||
|
|
||||||
|
exports.getIV = (seed) => {
|
||||||
|
if (typeof seed === "undefined") seed = SEED;
|
||||||
|
const c = Web3Utils.keccak256(seed+"_iv");
|
||||||
|
const cn = bigInt(Web3Utils.toBN(c).toString());
|
||||||
|
const iv = cn.mod(F.q);
|
||||||
|
return iv;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.getConstants = (seed, nRounds) => {
|
||||||
|
if (typeof seed === "undefined") seed = SEED;
|
||||||
|
if (typeof nRounds === "undefined") nRounds = NROUNDS;
|
||||||
|
const cts = new Array(nRounds);
|
||||||
|
let c = Web3Utils.keccak256(SEED);
|
||||||
|
for (let i=1; i<nRounds; i++) {
|
||||||
|
c = Web3Utils.keccak256(c);
|
||||||
|
|
||||||
|
const n1 = Web3Utils.toBN(c).mod(Web3Utils.toBN(F.q.toString()));
|
||||||
|
const c2 = Web3Utils.padLeft(Web3Utils.toHex(n1), 64);
|
||||||
|
cts[i] = bigInt(Web3Utils.toBN(c2).toString());
|
||||||
|
}
|
||||||
|
cts[0] = bigInt(0);
|
||||||
|
return cts;
|
||||||
|
};
|
||||||
|
|
||||||
|
const cts = exports.getConstants(SEED, 91);
|
||||||
|
|
||||||
|
exports.hash = (_x_in, _k) =>{
|
||||||
|
const x_in = bigInt(_x_in);
|
||||||
|
const k = bigInt(_k);
|
||||||
|
let r;
|
||||||
|
for (let i=0; i<NROUNDS; i++) {
|
||||||
|
const c = cts[i];
|
||||||
|
const t = (i==0) ? F.add(x_in, k) : F.add(F.add(r, k), c);
|
||||||
|
r = F.exp(t, 7);
|
||||||
|
}
|
||||||
|
return F.affine(F.add(r, k));
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.multiHash = (arr, key) => {
|
||||||
|
let r;
|
||||||
|
if (typeof(key) === "undefined") {
|
||||||
|
r = F.zero;
|
||||||
|
} else {
|
||||||
|
r = key;
|
||||||
|
}
|
||||||
|
for (let i=0; i<arr.length; i++) {
|
||||||
|
r = F.add(
|
||||||
|
F.add(
|
||||||
|
r,
|
||||||
|
arr[i]
|
||||||
|
),
|
||||||
|
exports.hash(bigInt(arr[i]), r)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return F.affine(r);
|
||||||
|
};
|
||||||
114
src/mimc_gencontract.js
Normal file
114
src/mimc_gencontract.js
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
// Copyright (c) 2018 Jordi Baylina
|
||||||
|
// License: LGPL-3.0+
|
||||||
|
//
|
||||||
|
|
||||||
|
const Web3Utils = require("web3-utils");
|
||||||
|
|
||||||
|
const Contract = require("./evmasm");
|
||||||
|
|
||||||
|
function createCode(seed, n) {
|
||||||
|
|
||||||
|
let ci = Web3Utils.keccak256(seed);
|
||||||
|
|
||||||
|
const C = new Contract();
|
||||||
|
|
||||||
|
C.push(0x44);
|
||||||
|
C.push("0x00");
|
||||||
|
C.push("0x00");
|
||||||
|
C.calldatacopy();
|
||||||
|
C.push("0x0100000000000000000000000000000000000000000000000000000000");
|
||||||
|
C.push("0x00");
|
||||||
|
C.mload();
|
||||||
|
C.div();
|
||||||
|
C.push("0xd15ca109"); // MiMCpe7(uint256,uint256)
|
||||||
|
// C.push("0x8c42199e"); // MiMCpe7(uint256,uint256,uint256)
|
||||||
|
C.eq();
|
||||||
|
C.jmpi("start");
|
||||||
|
C.invalid();
|
||||||
|
|
||||||
|
C.label("start");
|
||||||
|
C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q
|
||||||
|
C.push("0x24");
|
||||||
|
C.mload(); // k q
|
||||||
|
|
||||||
|
|
||||||
|
C.dup(1); // q k q
|
||||||
|
C.dup(0); // q q k q
|
||||||
|
C.push("0x04");
|
||||||
|
C.mload(); // x q q k q
|
||||||
|
C.dup(3); // k x q q k q
|
||||||
|
C.addmod(); // t=x+k q k q
|
||||||
|
C.dup(1); // q t q k q
|
||||||
|
C.dup(0); // q q t q k q
|
||||||
|
C.dup(2); // t q q t q k q
|
||||||
|
C.dup(0); // t t q q t q k q
|
||||||
|
C.mulmod(); // a=t^2 q t q k q
|
||||||
|
C.dup(1); // q a q t q k q
|
||||||
|
C.dup(1); // a q a q t q k q
|
||||||
|
C.dup(0); // a a q a q t q k q
|
||||||
|
C.mulmod(); // b=t^4 a q t q k q
|
||||||
|
C.mulmod(); // c=t^6 t q k q
|
||||||
|
C.mulmod(); // r=t^7 k q
|
||||||
|
|
||||||
|
for (let i=0; i<n-1; i++) {
|
||||||
|
ci = Web3Utils.keccak256(ci);
|
||||||
|
C.dup(2); // q r k q
|
||||||
|
C.dup(0); // q q r k q
|
||||||
|
C.dup(0); // q q q r k q
|
||||||
|
C.swap(3); // r q q q k q
|
||||||
|
C.push(ci); // c r q q k q
|
||||||
|
C.addmod(); // s=c+r q q k q
|
||||||
|
C.dup(3); // k s q q k q
|
||||||
|
C.addmod(); // t=s+k q k q
|
||||||
|
C.dup(1); // q t q k q
|
||||||
|
C.dup(0); // q q t q k q
|
||||||
|
C.dup(2); // t q q t q k q
|
||||||
|
C.dup(0); // t t q q t q k q
|
||||||
|
C.mulmod(); // a=t^2 q t q k q
|
||||||
|
C.dup(1); // q a q t q k q
|
||||||
|
C.dup(1); // a q a q t q k q
|
||||||
|
C.dup(0); // a a q a q t q k q
|
||||||
|
C.mulmod(); // b=t^4 a q t q k q
|
||||||
|
C.mulmod(); // c=t^6 t q k q
|
||||||
|
C.mulmod(); // r=t^7 k q
|
||||||
|
}
|
||||||
|
|
||||||
|
C.addmod(); // res=t^7+k
|
||||||
|
C.push("0x00");
|
||||||
|
C.mstore(); // Save it to pos 0;
|
||||||
|
C.push("0x20");
|
||||||
|
C.push("0x00");
|
||||||
|
C.return();
|
||||||
|
|
||||||
|
return C.createTxData();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.abi = [
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "in_x",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "in_k",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "MiMCpe7",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "out_x",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "pure",
|
||||||
|
"type": "function"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports.createCode = createCode;
|
||||||
|
|
||||||
|
|
||||||
3
src/mimc_print_iv.js
Normal file
3
src/mimc_print_iv.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
const mimc7 = require("./mimc7.js");
|
||||||
|
|
||||||
|
console.log("IV: "+mimc7.getIV().toString());
|
||||||
13
src/mimc_printconstants..js
Normal file
13
src/mimc_printconstants..js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
const mimc7 = require("./mimc7.js");
|
||||||
|
|
||||||
|
const nRounds = 91;
|
||||||
|
let S = "[\n";
|
||||||
|
const cts = mimc7.getConstants();
|
||||||
|
for (let i=0; i<nRounds; i++) {
|
||||||
|
S = S + cts[i].toString();
|
||||||
|
if (i<nRounds-1) S = S + ",";
|
||||||
|
S=S+"\n";
|
||||||
|
}
|
||||||
|
S = S + "]\n";
|
||||||
|
|
||||||
|
console.log(S);
|
||||||
13
src/mimc_printcontract.js
Normal file
13
src/mimc_printcontract.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
const mimcGenContract = require("./mimc_gencontract");
|
||||||
|
|
||||||
|
const SEED = "mimc";
|
||||||
|
|
||||||
|
let nRounds;
|
||||||
|
if (typeof process.argv[2] != "undefined") {
|
||||||
|
nRounds = parseInt(process.argv[2]);
|
||||||
|
} else {
|
||||||
|
nRounds = 91;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(mimcGenContract.createCode(SEED, nRounds));
|
||||||
|
|
||||||
111
src/pedersenHash.js
Normal file
111
src/pedersenHash.js
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
const bn128 = require("snarkjs").bn128;
|
||||||
|
const bigInt = require("snarkjs").bigInt;
|
||||||
|
const babyJub = require("./babyjub");
|
||||||
|
const createBlakeHash = require("blake-hash");
|
||||||
|
|
||||||
|
const GENPOINT_PREFIX = "PedersenGenerator";
|
||||||
|
const windowSize = 4;
|
||||||
|
const nWindowsPerSegment = 50;
|
||||||
|
|
||||||
|
exports.hash = pedersenHash;
|
||||||
|
exports.getBasePoint = getBasePoint;
|
||||||
|
|
||||||
|
function pedersenHash(msg) {
|
||||||
|
const bitsPerSegment = windowSize*nWindowsPerSegment;
|
||||||
|
const bits = buffer2bits(msg);
|
||||||
|
|
||||||
|
const nSegments = Math.floor((bits.length - 1)/(windowSize*nWindowsPerSegment)) +1;
|
||||||
|
|
||||||
|
let accP = [bigInt.zero,bigInt.one];
|
||||||
|
|
||||||
|
for (let s=0; s<nSegments; s++) {
|
||||||
|
let nWindows;
|
||||||
|
if (s == nSegments-1) {
|
||||||
|
nWindows = Math.floor(((bits.length - (nSegments - 1)*bitsPerSegment) - 1) / windowSize) +1;
|
||||||
|
} else {
|
||||||
|
nWindows = nWindowsPerSegment;
|
||||||
|
}
|
||||||
|
let escalar = bigInt.zero;
|
||||||
|
let exp = bigInt.one;
|
||||||
|
for (let w=0; w<nWindows; w++) {
|
||||||
|
let o = s*bitsPerSegment + w*windowSize;
|
||||||
|
let acc = bigInt.one;
|
||||||
|
for (let b=0; ((b<windowSize-1)&&(o<bits.length)) ; b++) {
|
||||||
|
if (bits[o]) {
|
||||||
|
acc = acc.add( bigInt.one.shl(b) );
|
||||||
|
}
|
||||||
|
o++;
|
||||||
|
}
|
||||||
|
if (o<bits.length) {
|
||||||
|
if (bits[o]) {
|
||||||
|
acc = acc.neg();
|
||||||
|
}
|
||||||
|
o++;
|
||||||
|
}
|
||||||
|
escalar = escalar.add(acc.mul(exp));
|
||||||
|
exp = exp.shl(windowSize+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (escalar.lesser(bigInt.zero)) {
|
||||||
|
escalar = babyJub.subOrder.add(escalar);
|
||||||
|
}
|
||||||
|
|
||||||
|
accP = babyJub.addPoint(accP, babyJub.mulPointEscalar(getBasePoint(s), escalar));
|
||||||
|
}
|
||||||
|
|
||||||
|
return babyJub.packPoint(accP);
|
||||||
|
}
|
||||||
|
|
||||||
|
let bases = [];
|
||||||
|
|
||||||
|
function getBasePoint(pointIdx) {
|
||||||
|
if (pointIdx<bases.length) return bases[pointIdx];
|
||||||
|
let p= null;
|
||||||
|
let tryIdx = 0;
|
||||||
|
while (p==null) {
|
||||||
|
const S = GENPOINT_PREFIX + "_" + padLeftZeros(pointIdx, 32) + "_" + padLeftZeros(tryIdx, 32);
|
||||||
|
const h = createBlakeHash("blake256").update(S).digest();
|
||||||
|
h[31] = h[31] & 0xBF; // Set 255th bit to 0 (256th is the signal and 254th is the last possible bit to 1)
|
||||||
|
p = babyJub.unpackPoint(h);
|
||||||
|
tryIdx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const p8 = babyJub.mulPointEscalar(p, 8);
|
||||||
|
|
||||||
|
if (!babyJub.inSubgroup(p8)) {
|
||||||
|
throw new Error("Point not in curve");
|
||||||
|
}
|
||||||
|
|
||||||
|
bases[pointIdx] = p8;
|
||||||
|
return p8;
|
||||||
|
}
|
||||||
|
|
||||||
|
function padLeftZeros(idx, n) {
|
||||||
|
let sidx = "" + idx;
|
||||||
|
while (sidx.length<n) sidx = "0"+sidx;
|
||||||
|
return sidx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Input a buffer
|
||||||
|
Returns an array of booleans. 0 is LSB of first byte and so on.
|
||||||
|
*/
|
||||||
|
function buffer2bits(buff) {
|
||||||
|
const res = new Array(buff.length*8);
|
||||||
|
for (let i=0; i<buff.length; i++) {
|
||||||
|
const b = buff[i];
|
||||||
|
res[i*8] = b & 0x01;
|
||||||
|
res[i*8+1] = b & 0x02;
|
||||||
|
res[i*8+2] = b & 0x04;
|
||||||
|
res[i*8+3] = b & 0x08;
|
||||||
|
res[i*8+4] = b & 0x10;
|
||||||
|
res[i*8+5] = b & 0x20;
|
||||||
|
res[i*8+6] = b & 0x40;
|
||||||
|
res[i*8+7] = b & 0x80;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
13
src/pedersen_printbases.js
Normal file
13
src/pedersen_printbases.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
const pedersenHash = require("./pedersenHash.js");
|
||||||
|
|
||||||
|
let nBases;
|
||||||
|
if (typeof process.argv[2] != "undefined") {
|
||||||
|
nBases = parseInt(process.argv[2]);
|
||||||
|
} else {
|
||||||
|
nBases = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i=0; i < nBases; i++) {
|
||||||
|
const p = pedersenHash.getBasePoint(i);
|
||||||
|
console.log(`[${p[0]},${p[1]}]`);
|
||||||
|
}
|
||||||
311
src/smt.js
Normal file
311
src/smt.js
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
const bigInt = require("snarkjs").bigInt;
|
||||||
|
|
||||||
|
const SMTMemDB = require("./smt_memdb");
|
||||||
|
const mimc7 = require("./mimc7");
|
||||||
|
|
||||||
|
class SMT {
|
||||||
|
|
||||||
|
constructor(db, root) {
|
||||||
|
this.db = db;
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
_splitBits(_key) {
|
||||||
|
|
||||||
|
let k = bigInt(_key);
|
||||||
|
const res = [];
|
||||||
|
|
||||||
|
while (!k.isZero()) {
|
||||||
|
if (k.isOdd()) {
|
||||||
|
res.push(true);
|
||||||
|
} else {
|
||||||
|
res.push(false);
|
||||||
|
}
|
||||||
|
k = k.shr(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (res.length<256) res.push(false);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(_key, _newValue) {
|
||||||
|
const key = bigInt(_key);
|
||||||
|
const newValue = bigInt(_newValue);
|
||||||
|
|
||||||
|
|
||||||
|
const resFind = await this.find(key);
|
||||||
|
const res = {};
|
||||||
|
res.oldRoot = this.root;
|
||||||
|
res.oldKey = key;
|
||||||
|
res.oldValue = resFind.foundValue;
|
||||||
|
res.newKey = key;
|
||||||
|
res.newValue = newValue;
|
||||||
|
res.siblings = resFind.siblings;
|
||||||
|
|
||||||
|
const ins = [];
|
||||||
|
const dels = [];
|
||||||
|
|
||||||
|
let rtOld = mimc7.multiHash([key, resFind.foundValue], bigInt.one);
|
||||||
|
let rtNew = mimc7.multiHash([key, newValue], bigInt.one);
|
||||||
|
ins.push([rtNew, [1, key, newValue ]]);
|
||||||
|
dels.push(rtOld);
|
||||||
|
|
||||||
|
const keyBits = this._splitBits(key);
|
||||||
|
for (let level = resFind.siblings.length-1; level >=0; level--) {
|
||||||
|
let oldNode, newNode;
|
||||||
|
const sibling = resFind.siblings[level];
|
||||||
|
if (keyBits[level]) {
|
||||||
|
oldNode = [sibling, rtOld];
|
||||||
|
newNode = [sibling, rtNew];
|
||||||
|
} else {
|
||||||
|
oldNode = [rtOld, sibling];
|
||||||
|
newNode = [rtNew, sibling];
|
||||||
|
}
|
||||||
|
rtOld = mimc7.multiHash(oldNode, bigInt.zero);
|
||||||
|
rtNew = mimc7.multiHash(newNode, bigInt.zero);
|
||||||
|
dels.push(rtOld);
|
||||||
|
ins.push([rtNew, newNode]);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.newRoot = rtNew;
|
||||||
|
|
||||||
|
await this.db.multiIns(ins);
|
||||||
|
await this.db.setRoot(rtNew);
|
||||||
|
this.root = rtNew;
|
||||||
|
await this.db.multiDel(dels);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(_key) {
|
||||||
|
const key = bigInt(_key);
|
||||||
|
|
||||||
|
const resFind = await this.find(key);
|
||||||
|
if (!resFind.found) throw new Error("Key does not exists");
|
||||||
|
|
||||||
|
const res = {
|
||||||
|
siblings: [],
|
||||||
|
delKey: key,
|
||||||
|
delValue: resFind.foundValue
|
||||||
|
};
|
||||||
|
|
||||||
|
const dels = [];
|
||||||
|
const ins = [];
|
||||||
|
let rtOld = mimc7.multiHash([key, resFind.foundValue], bigInt.one);
|
||||||
|
let rtNew;
|
||||||
|
dels.push(rtOld);
|
||||||
|
|
||||||
|
let mixed;
|
||||||
|
if (resFind.siblings.length > 0) {
|
||||||
|
const record = await this.db.get(resFind.siblings[resFind.siblings.length - 1]);
|
||||||
|
if ((record.length == 3)&&(record[0].equals(bigInt.one))) {
|
||||||
|
mixed = false;
|
||||||
|
res.oldKey = record[1];
|
||||||
|
res.oldValue = record[2];
|
||||||
|
res.isOld0 = false;
|
||||||
|
rtNew = resFind.siblings[resFind.siblings.length - 1];
|
||||||
|
} else if (record.length == 2) {
|
||||||
|
mixed = true;
|
||||||
|
res.oldKey = key;
|
||||||
|
res.oldValue = bigInt(0);
|
||||||
|
res.isOld0 = true;
|
||||||
|
rtNew = bigInt.zero;
|
||||||
|
} else {
|
||||||
|
throw new Error("Invalid node. Database corrupted");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rtNew = bigInt.zero;
|
||||||
|
res.oldKey = key;
|
||||||
|
res.oldValue = bigInt(0);
|
||||||
|
res.isOld0 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const keyBits = this._splitBits(key);
|
||||||
|
|
||||||
|
for (let level = resFind.siblings.length-1; level >=0; level--) {
|
||||||
|
let newSibling = resFind.siblings[level];
|
||||||
|
if ((level == resFind.siblings.length-1)&&(!res.isOld0)) {
|
||||||
|
newSibling = bigInt.zero;
|
||||||
|
}
|
||||||
|
const oldSibling = resFind.siblings[level];
|
||||||
|
if (keyBits[level]) {
|
||||||
|
rtOld = mimc7.multiHash([oldSibling, rtOld], bigInt.zero);
|
||||||
|
} else {
|
||||||
|
rtOld = mimc7.multiHash([rtOld, oldSibling], bigInt.zero);
|
||||||
|
}
|
||||||
|
dels.push(rtOld);
|
||||||
|
if (!newSibling.isZero()) {
|
||||||
|
mixed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mixed) {
|
||||||
|
res.siblings.unshift(resFind.siblings[level]);
|
||||||
|
let newNode;
|
||||||
|
if (keyBits[level]) {
|
||||||
|
newNode = [newSibling, rtNew];
|
||||||
|
} else {
|
||||||
|
newNode = [rtNew, newSibling];
|
||||||
|
}
|
||||||
|
rtNew = mimc7.multiHash(newNode, bigInt.zero);
|
||||||
|
ins.push([rtNew, newNode]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.db.multiIns(ins);
|
||||||
|
await this.db.setRoot(rtNew);
|
||||||
|
this.root = rtNew;
|
||||||
|
await this.db.multiDel(dels);
|
||||||
|
|
||||||
|
res.newRoot = rtNew;
|
||||||
|
res.oldRoot = rtOld;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async insert(_key, _value) {
|
||||||
|
const key = bigInt(_key);
|
||||||
|
const value = bigInt(_value);
|
||||||
|
let addedOne = false;
|
||||||
|
const res = {};
|
||||||
|
res.oldRoot = this.root;
|
||||||
|
const newKeyBits = this._splitBits(key);
|
||||||
|
|
||||||
|
let rtOld;
|
||||||
|
|
||||||
|
const resFind = await this.find(key);
|
||||||
|
|
||||||
|
if (resFind.found) throw new Error("Key already exists");
|
||||||
|
|
||||||
|
res.siblings = resFind.siblings;
|
||||||
|
let mixed;
|
||||||
|
|
||||||
|
if (!resFind.isOld0) {
|
||||||
|
const oldKeyits = this._splitBits(resFind.notFoundKey);
|
||||||
|
for (let i= res.siblings.length; oldKeyits[i] == newKeyBits[i]; i++) {
|
||||||
|
res.siblings.push(bigInt.zero);
|
||||||
|
}
|
||||||
|
rtOld = mimc7.multiHash([resFind.notFoundKey, resFind.notFoundValue], bigInt.one);
|
||||||
|
res.siblings.push(rtOld);
|
||||||
|
addedOne = true;
|
||||||
|
mixed = false;
|
||||||
|
} else if (res.siblings.length >0) {
|
||||||
|
mixed = true;
|
||||||
|
rtOld = bigInt.zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
const inserts = [];
|
||||||
|
const dels = [];
|
||||||
|
|
||||||
|
let rt = mimc7.multiHash([key, value], bigInt.one);
|
||||||
|
inserts.push([rt,[1, key, value]] );
|
||||||
|
|
||||||
|
for (let i=res.siblings.length-1; i>=0; i--) {
|
||||||
|
if ((i<res.siblings.length-1)&&(!res.siblings[i].isZero())) {
|
||||||
|
mixed = true;
|
||||||
|
}
|
||||||
|
if (mixed) {
|
||||||
|
const oldSibling = resFind.siblings[i];
|
||||||
|
if (newKeyBits[i]) {
|
||||||
|
rtOld = mimc7.multiHash([oldSibling, rtOld], bigInt.zero);
|
||||||
|
} else {
|
||||||
|
rtOld = mimc7.multiHash([rtOld, oldSibling], bigInt.zero);
|
||||||
|
}
|
||||||
|
dels.push(rtOld);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let newRt;
|
||||||
|
if (newKeyBits[i]) {
|
||||||
|
newRt = mimc7.multiHash([res.siblings[i], rt], bigInt.zero);
|
||||||
|
inserts.push([newRt,[res.siblings[i], rt]] );
|
||||||
|
} else {
|
||||||
|
newRt = mimc7.multiHash([rt, res.siblings[i]], bigInt.zero);
|
||||||
|
inserts.push([newRt,[rt, res.siblings[i]]] );
|
||||||
|
}
|
||||||
|
rt = newRt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addedOne) res.siblings.pop();
|
||||||
|
while ((res.siblings.length>0) && (res.siblings[res.siblings.length-1].isZero())) {
|
||||||
|
res.siblings.pop();
|
||||||
|
}
|
||||||
|
res.oldKey = resFind.notFoundKey;
|
||||||
|
res.oldValue = resFind.notFoundValue;
|
||||||
|
res.newRoot = rt;
|
||||||
|
res.isOld0 = resFind.isOld0;
|
||||||
|
|
||||||
|
|
||||||
|
await this.db.multiIns(inserts);
|
||||||
|
await this.db.setRoot(rt);
|
||||||
|
this.root = rt;
|
||||||
|
await this.db.multiDel(dels);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async find(key) {
|
||||||
|
const keyBits = this._splitBits(key);
|
||||||
|
return await this._find(key, keyBits, this.root, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async _find(key, keyBits, root, level) {
|
||||||
|
if (typeof root === "undefined") root = this.root;
|
||||||
|
|
||||||
|
let res;
|
||||||
|
if (root.isZero()) {
|
||||||
|
res = {
|
||||||
|
found: false,
|
||||||
|
siblings: [],
|
||||||
|
notFoundKey: key,
|
||||||
|
notFoundValue: bigInt.zero,
|
||||||
|
isOld0: true
|
||||||
|
};
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
const record = await this.db.get(root);
|
||||||
|
|
||||||
|
if ((record.length==3)&&(record[0].equals(bigInt.one))) {
|
||||||
|
if (record[1].equals(key)) {
|
||||||
|
res = {
|
||||||
|
found: true,
|
||||||
|
siblings: [],
|
||||||
|
foundValue: record[2],
|
||||||
|
isOld0: false
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
res = {
|
||||||
|
found: false,
|
||||||
|
siblings: [],
|
||||||
|
notFoundKey: record[1],
|
||||||
|
notFoundValue: record[2],
|
||||||
|
isOld0: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (keyBits[level] == 0) {
|
||||||
|
res = await this._find(key, keyBits, record[0], level+1);
|
||||||
|
res.siblings.unshift(record[1]);
|
||||||
|
} else {
|
||||||
|
res = await this._find(key, keyBits, record[1], level+1);
|
||||||
|
res.siblings.unshift(record[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadFromFile(fileName) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function newMemEmptyTrie() {
|
||||||
|
const db = new SMTMemDB();
|
||||||
|
const rt = await db.getRoot();
|
||||||
|
const smt = new SMT(db, rt);
|
||||||
|
return smt;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.loadFromFile = loadFromFile;
|
||||||
|
module.exports.newMemEmptyTrie = newMemEmptyTrie;
|
||||||
50
src/smt_memdb.js
Normal file
50
src/smt_memdb.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
const bigInt = require("snarkjs").bigInt;
|
||||||
|
|
||||||
|
class SMTMemDb {
|
||||||
|
constructor() {
|
||||||
|
this.nodes = {};
|
||||||
|
this.root = bigInt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRoot() {
|
||||||
|
return this.root;
|
||||||
|
}
|
||||||
|
|
||||||
|
_key2str(k) {
|
||||||
|
// const keyS = bigInt(key).leInt2Buff(32).toString("hex");
|
||||||
|
const keyS = bigInt(k).toString();
|
||||||
|
return keyS;
|
||||||
|
}
|
||||||
|
|
||||||
|
_normalize(n) {
|
||||||
|
for (let i=0; i<n.length; i++) {
|
||||||
|
n[i] = bigInt(n[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async get(key) {
|
||||||
|
const keyS = this._key2str(key);
|
||||||
|
return this.nodes[keyS];
|
||||||
|
}
|
||||||
|
|
||||||
|
async setRoot(rt) {
|
||||||
|
this.root = rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
async multiIns(inserts) {
|
||||||
|
for (let i=0; i<inserts.length; i++) {
|
||||||
|
const keyS = this._key2str(inserts[i][0]);
|
||||||
|
this._normalize(inserts[i][1]);
|
||||||
|
this.nodes[keyS] = inserts[i][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async multiDel(dels) {
|
||||||
|
for (let i=0; i<dels.length; i++) {
|
||||||
|
const keyS = this._key2str(dels[i]);
|
||||||
|
delete this.nodes[keyS];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = SMTMemDb;
|
||||||
74
test/aliascheck.js
Normal file
74
test/aliascheck.js
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
const chai = require("chai");
|
||||||
|
const path = require("path");
|
||||||
|
const snarkjs = require("snarkjs");
|
||||||
|
const compiler = require("circom");
|
||||||
|
|
||||||
|
const assert = chai.assert;
|
||||||
|
|
||||||
|
const bigInt = snarkjs.bigInt;
|
||||||
|
|
||||||
|
function print(circuit, w, s) {
|
||||||
|
console.log(s + ": " + w[circuit.getSignalIdx(s)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBits(v, n) {
|
||||||
|
const res = [];
|
||||||
|
for (let i=0; i<n; i++) {
|
||||||
|
if (v.shr(i).isOdd()) {
|
||||||
|
res.push(bigInt.one);
|
||||||
|
} else {
|
||||||
|
res.push(bigInt.zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
const q = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||||
|
|
||||||
|
describe("Aliascheck test", () => {
|
||||||
|
let circuit;
|
||||||
|
before( async() => {
|
||||||
|
const cirDef = await compiler(path.join(__dirname, "circuits", "aliascheck_test.circom"));
|
||||||
|
|
||||||
|
circuit = new snarkjs.Circuit(cirDef);
|
||||||
|
|
||||||
|
console.log("NConstrains: " + circuit.nConstraints);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Satisfy the aliastest 0", async () => {
|
||||||
|
const inp = getBits(bigInt.zero, 254);
|
||||||
|
circuit.calculateWitness({in: inp});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Satisfy the aliastest 3", async () => {
|
||||||
|
const inp = getBits(bigInt(3), 254);
|
||||||
|
circuit.calculateWitness({in: inp});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Satisfy the aliastest q-1", async () => {
|
||||||
|
const inp = getBits(q.sub(bigInt.one), 254);
|
||||||
|
circuit.calculateWitness({in: inp});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Nhot not satisfy an input of q", async () => {
|
||||||
|
const inp = getBits(q, 254);
|
||||||
|
try {
|
||||||
|
circuit.calculateWitness({in: inp});
|
||||||
|
assert(false);
|
||||||
|
} catch(err) {
|
||||||
|
assert.equal(err.message, "Constraint doesn't match: 1 != 0");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Nhot not satisfy all ones", async () => {
|
||||||
|
|
||||||
|
const inp = getBits(bigInt(1).shl(254).sub(bigInt(1)), 254);
|
||||||
|
try {
|
||||||
|
circuit.calculateWitness({in: inp});
|
||||||
|
assert(false);
|
||||||
|
} catch(err) {
|
||||||
|
assert.equal(err.message, "Constraint doesn't match: 1 != 0");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -8,30 +8,35 @@ const assert = chai.assert;
|
|||||||
const bigInt = require("big-integer");
|
const bigInt = require("big-integer");
|
||||||
|
|
||||||
|
|
||||||
describe("Baby Jub test", () => {
|
describe("Baby Jub test", function () {
|
||||||
|
let circuitAdd;
|
||||||
|
let circuitTest;
|
||||||
|
|
||||||
|
this.timeout(100000);
|
||||||
|
|
||||||
|
before( async() => {
|
||||||
|
const cirDefAdd = await compiler(path.join(__dirname, "circuits", "babyadd_tester.circom"));
|
||||||
|
circuitAdd = new snarkjs.Circuit(cirDefAdd);
|
||||||
|
console.log("NConstrains BabyAdd: " + circuitAdd.nConstraints);
|
||||||
|
|
||||||
|
const cirDefTest = await compiler(path.join(__dirname, "circuits", "babycheck_test.circom"));
|
||||||
|
circuitTest = new snarkjs.Circuit(cirDefTest);
|
||||||
|
console.log("NConstrains BabyTest: " + circuitTest.nConstraints);
|
||||||
|
});
|
||||||
|
|
||||||
it("Should add point (0,1) and (0,1)", async () => {
|
it("Should add point (0,1) and (0,1)", async () => {
|
||||||
|
|
||||||
const cirDef = await compiler(path.join(__dirname, "circuits", "babyadd_tester.circom"));
|
|
||||||
|
|
||||||
// console.log(JSON.stringify(cirDef, null, 1));
|
|
||||||
|
|
||||||
// assert.equal(cirDef.nVars, 2);
|
|
||||||
|
|
||||||
const circuit = new snarkjs.Circuit(cirDef);
|
|
||||||
|
|
||||||
console.log("NConstrains: " + circuit.nConstraints);
|
|
||||||
|
|
||||||
const input={
|
const input={
|
||||||
x1: snarkjs.bigInt(0),
|
x1: snarkjs.bigInt(0),
|
||||||
y1: snarkjs.bigInt(1),
|
y1: snarkjs.bigInt(1),
|
||||||
x2: snarkjs.bigInt(0),
|
x2: snarkjs.bigInt(0),
|
||||||
y2: snarkjs.bigInt(1)
|
y2: snarkjs.bigInt(1)
|
||||||
}
|
};
|
||||||
|
|
||||||
const w = circuit.calculateWitness(input);
|
const w = circuitAdd.calculateWitness(input);
|
||||||
|
|
||||||
const xout = w[circuit.getSignalIdx("main.xout")];
|
const xout = w[circuitAdd.getSignalIdx("main.xout")];
|
||||||
const yout = w[circuit.getSignalIdx("main.yout")];
|
const yout = w[circuitAdd.getSignalIdx("main.yout")];
|
||||||
|
|
||||||
assert(xout.equals(0));
|
assert(xout.equals(0));
|
||||||
assert(yout.equals(1));
|
assert(yout.equals(1));
|
||||||
@@ -39,27 +44,17 @@ describe("Baby Jub test", () => {
|
|||||||
|
|
||||||
it("Should add 2 same numbers", async () => {
|
it("Should add 2 same numbers", async () => {
|
||||||
|
|
||||||
const cirDef = await compiler(path.join(__dirname, "circuits", "babyadd_tester.circom"));
|
|
||||||
|
|
||||||
// console.log(JSON.stringify(cirDef, null, 1));
|
|
||||||
|
|
||||||
// assert.equal(cirDef.nVars, 2);
|
|
||||||
|
|
||||||
const circuit = new snarkjs.Circuit(cirDef);
|
|
||||||
|
|
||||||
console.log("NConstrains: " + circuit.nConstraints);
|
|
||||||
|
|
||||||
const input={
|
const input={
|
||||||
x1: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
x1: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
||||||
y1: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
|
y1: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
|
||||||
x2: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
x2: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
||||||
y2: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475")
|
y2: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475")
|
||||||
}
|
};
|
||||||
|
|
||||||
const w = circuit.calculateWitness(input);
|
const w = circuitAdd.calculateWitness(input);
|
||||||
|
|
||||||
const xout = w[circuit.getSignalIdx("main.xout")];
|
const xout = w[circuitAdd.getSignalIdx("main.xout")];
|
||||||
const yout = w[circuit.getSignalIdx("main.yout")];
|
const yout = w[circuitAdd.getSignalIdx("main.yout")];
|
||||||
|
|
||||||
assert(xout.equals(snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365")));
|
assert(xout.equals(snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365")));
|
||||||
assert(yout.equals(snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889")));
|
assert(yout.equals(snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889")));
|
||||||
@@ -67,32 +62,39 @@ describe("Baby Jub test", () => {
|
|||||||
|
|
||||||
it("Should add 2 different numbers", async () => {
|
it("Should add 2 different numbers", async () => {
|
||||||
|
|
||||||
const cirDef = await compiler(path.join(__dirname, "circuits", "babyadd_tester.circom"));
|
|
||||||
|
|
||||||
// console.log(JSON.stringify(cirDef, null, 1));
|
|
||||||
|
|
||||||
// assert.equal(cirDef.nVars, 2);
|
|
||||||
|
|
||||||
const circuit = new snarkjs.Circuit(cirDef);
|
|
||||||
|
|
||||||
console.log("NConstrains: " + circuit.nConstraints);
|
|
||||||
|
|
||||||
const input={
|
const input={
|
||||||
x1: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
x1: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
||||||
y1: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
|
y1: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
|
||||||
x2: snarkjs.bigInt("16540640123574156134436876038791482806971768689494387082833631921987005038935"),
|
x2: snarkjs.bigInt("16540640123574156134436876038791482806971768689494387082833631921987005038935"),
|
||||||
y2: snarkjs.bigInt("20819045374670962167435360035096875258406992893633759881276124905556507972311")
|
y2: snarkjs.bigInt("20819045374670962167435360035096875258406992893633759881276124905556507972311")
|
||||||
}
|
};
|
||||||
|
|
||||||
const w = circuit.calculateWitness(input);
|
const w = circuitAdd.calculateWitness(input);
|
||||||
|
|
||||||
const xout = w[circuit.getSignalIdx("main.xout")];
|
const xout = w[circuitAdd.getSignalIdx("main.xout")];
|
||||||
const yout = w[circuit.getSignalIdx("main.yout")];
|
const yout = w[circuitAdd.getSignalIdx("main.yout")];
|
||||||
|
|
||||||
|
/*
|
||||||
console.log(xout.toString());
|
console.log(xout.toString());
|
||||||
console.log(yout.toString());
|
console.log(yout.toString());
|
||||||
|
*/
|
||||||
|
|
||||||
assert(xout.equals(snarkjs.bigInt("7916061937171219682591368294088513039687205273691143098332585753343424131937")));
|
assert(xout.equals(snarkjs.bigInt("7916061937171219682591368294088513039687205273691143098332585753343424131937")));
|
||||||
assert(yout.equals(snarkjs.bigInt("14035240266687799601661095864649209771790948434046947201833777492504781204499")));
|
assert(yout.equals(snarkjs.bigInt("14035240266687799601661095864649209771790948434046947201833777492504781204499")));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should check 0 is a valid poiny", async() => {
|
||||||
|
const w = circuitTest.calculateWitness({x: 0, y:1});
|
||||||
|
assert(circuitTest.checkWitness(w));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should check 0 is an invalid poiny", async() => {
|
||||||
|
try {
|
||||||
|
circuitTest.calculateWitness({x: 1, y: 0});
|
||||||
|
assert(false, "Should be a valid point");
|
||||||
|
} catch(err) {
|
||||||
|
assert.equal(err.message, "Constraint doesn't match: 168700 != 1");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
156
test/babyjub_js.js
Normal file
156
test/babyjub_js.js
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
const chai = require("chai");
|
||||||
|
const path = require("path");
|
||||||
|
const snarkjs = require("snarkjs");
|
||||||
|
const compiler = require("circom");
|
||||||
|
const babyjub = require("../src/babyjub.js");
|
||||||
|
|
||||||
|
const assert = chai.assert;
|
||||||
|
|
||||||
|
// const bigInt = require("big-integer");
|
||||||
|
|
||||||
|
|
||||||
|
describe("Baby Jub js test", function () {
|
||||||
|
|
||||||
|
this.timeout(100000);
|
||||||
|
|
||||||
|
it("Should add point (0,1) and (0,1)", () => {
|
||||||
|
|
||||||
|
const p1 = [
|
||||||
|
snarkjs.bigInt(0),
|
||||||
|
snarkjs.bigInt(1)];
|
||||||
|
const p2 = [
|
||||||
|
snarkjs.bigInt(0),
|
||||||
|
snarkjs.bigInt(1)
|
||||||
|
];
|
||||||
|
|
||||||
|
const out = babyjub.addPoint(p1, p2)
|
||||||
|
assert(out[0].equals(0));
|
||||||
|
assert(out[1].equals(1));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should add 2 same numbers", () => {
|
||||||
|
|
||||||
|
const p1 = [
|
||||||
|
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
||||||
|
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
|
||||||
|
];
|
||||||
|
const p2 = [
|
||||||
|
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
||||||
|
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
|
||||||
|
];
|
||||||
|
|
||||||
|
const out = babyjub.addPoint(p1, p2)
|
||||||
|
assert(out[0].equals(snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365")));
|
||||||
|
assert(out[1].equals(snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889")));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should add 2 different numbers", () => {
|
||||||
|
|
||||||
|
const p1 = [
|
||||||
|
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
||||||
|
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
|
||||||
|
];
|
||||||
|
const p2 = [
|
||||||
|
snarkjs.bigInt("16540640123574156134436876038791482806971768689494387082833631921987005038935"),
|
||||||
|
snarkjs.bigInt("20819045374670962167435360035096875258406992893633759881276124905556507972311"),
|
||||||
|
];
|
||||||
|
|
||||||
|
const out = babyjub.addPoint(p1, p2)
|
||||||
|
|
||||||
|
assert(out[0].equals(snarkjs.bigInt("7916061937171219682591368294088513039687205273691143098332585753343424131937")));
|
||||||
|
assert(out[1].equals(snarkjs.bigInt("14035240266687799601661095864649209771790948434046947201833777492504781204499")));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should mulPointEscalar 0", () => {
|
||||||
|
const p = [
|
||||||
|
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
||||||
|
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
|
||||||
|
];
|
||||||
|
|
||||||
|
const r = babyjub.mulPointEscalar(p, snarkjs.bigInt("3"));
|
||||||
|
let r2 = babyjub.addPoint(p, p);
|
||||||
|
r2 = babyjub.addPoint(r2, p);
|
||||||
|
assert.equal(r2[0].toString(), r[0].toString());
|
||||||
|
assert.equal(r2[1].toString(), r[1].toString());
|
||||||
|
assert.equal(r[0].toString(), "19372461775513343691590086534037741906533799473648040012278229434133483800898");
|
||||||
|
assert.equal(r[1].toString(), "9458658722007214007257525444427903161243386465067105737478306991484593958249");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should mulPointEscalar 1", () => {
|
||||||
|
const p = [
|
||||||
|
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
||||||
|
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
|
||||||
|
];
|
||||||
|
|
||||||
|
const r = babyjub.mulPointEscalar(p, snarkjs.bigInt("14035240266687799601661095864649209771790948434046947201833777492504781204499"));
|
||||||
|
assert.equal(r[0].toString(), "17070357974431721403481313912716834497662307308519659060910483826664480189605");
|
||||||
|
assert.equal(r[1].toString(), "4014745322800118607127020275658861516666525056516280575712425373174125159339");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should mulPointEscalar 2", () => {
|
||||||
|
const p = [
|
||||||
|
snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365"),
|
||||||
|
snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889"),
|
||||||
|
];
|
||||||
|
|
||||||
|
const r = babyjub.mulPointEscalar(p, snarkjs.bigInt("20819045374670962167435360035096875258406992893633759881276124905556507972311"));
|
||||||
|
assert.equal(r[0].toString(), "13563888653650925984868671744672725781658357821216877865297235725727006259983");
|
||||||
|
assert.equal(r[1].toString(), "8442587202676550862664528699803615547505326611544120184665036919364004251662");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should inCurve 1", () => {
|
||||||
|
const p = [
|
||||||
|
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
||||||
|
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
|
||||||
|
];
|
||||||
|
assert(babyjub.inCurve(p));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should inCurve 2", () => {
|
||||||
|
const p = [
|
||||||
|
snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365"),
|
||||||
|
snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889"),
|
||||||
|
];
|
||||||
|
assert(babyjub.inCurve(p));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should inSubgroup 1", () => {
|
||||||
|
const p = [
|
||||||
|
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
||||||
|
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
|
||||||
|
];
|
||||||
|
assert(babyjub.inSubgroup(p));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should inSubgroup 2", () => {
|
||||||
|
const p = [
|
||||||
|
snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365"),
|
||||||
|
snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889"),
|
||||||
|
];
|
||||||
|
assert(babyjub.inSubgroup(p));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should packPoint - unpackPoint 1", () => {
|
||||||
|
const p = [
|
||||||
|
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
||||||
|
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
|
||||||
|
];
|
||||||
|
const buf = babyjub.packPoint(p);
|
||||||
|
assert.equal(buf.toString('hex'), '53b81ed5bffe9545b54016234682e7b2f699bd42a5e9eae27ff4051bc698ce85');
|
||||||
|
const p2 = babyjub.unpackPoint(buf);
|
||||||
|
assert.equal(p2[0].toString(), "17777552123799933955779906779655732241715742912184938656739573121738514868268");
|
||||||
|
assert.equal(p2[1].toString(), "2626589144620713026669568689430873010625803728049924121243784502389097019475");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should packPoint - unpackPoint 2", () => {
|
||||||
|
const p = [
|
||||||
|
snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365"),
|
||||||
|
snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889"),
|
||||||
|
];
|
||||||
|
const buf = babyjub.packPoint(p);
|
||||||
|
assert.equal(buf.toString('hex'), 'e114eb17eddf794f063a68fecac515e3620e131976108555735c8b0773929709');
|
||||||
|
const p2 = babyjub.unpackPoint(buf);
|
||||||
|
assert.equal(p2[0].toString(), "6890855772600357754907169075114257697580319025794532037257385534741338397365");
|
||||||
|
assert.equal(p2[1].toString(), "4338620300185947561074059802482547481416142213883829469920100239455078257889");
|
||||||
|
});
|
||||||
|
});
|
||||||
56
test/binsub.js
Normal file
56
test/binsub.js
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
const chai = require("chai");
|
||||||
|
const path = require("path");
|
||||||
|
const snarkjs = require("snarkjs");
|
||||||
|
const compiler = require("circom");
|
||||||
|
|
||||||
|
const assert = chai.assert;
|
||||||
|
|
||||||
|
const bigInt = snarkjs.bigInt;
|
||||||
|
|
||||||
|
function print(circuit, w, s) {
|
||||||
|
console.log(s + ": " + w[circuit.getSignalIdx(s)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkSub(_a,_b, circuit) {
|
||||||
|
let a=bigInt(_a);
|
||||||
|
let b=bigInt(_b);
|
||||||
|
if (a.lesser(bigInt.zero)) a = a.add(bigInt.one.shl(16));
|
||||||
|
if (b.lesser(bigInt.zero)) b = b.add(bigInt.one.shl(16));
|
||||||
|
const w = circuit.calculateWitness({a: a, b: b});
|
||||||
|
|
||||||
|
let res = a.sub(b);
|
||||||
|
if (res.lesser(bigInt.zero)) res = res.add(bigInt.one.shl(16));
|
||||||
|
assert( w[circuit.getSignalIdx("main.out")].equals(bigInt(res)) );
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("BinSub test", () => {
|
||||||
|
let circuit;
|
||||||
|
before( async() => {
|
||||||
|
const cirDef = await compiler(path.join(__dirname, "circuits", "binsub_test.circom"));
|
||||||
|
|
||||||
|
circuit = new snarkjs.Circuit(cirDef);
|
||||||
|
|
||||||
|
console.log("NConstrains BinSub: " + circuit.nConstraints);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should check variuos ege cases", async () => {
|
||||||
|
checkSub(0,0, circuit);
|
||||||
|
checkSub(1,0, circuit);
|
||||||
|
checkSub(-1,0, circuit);
|
||||||
|
checkSub(2,1, circuit);
|
||||||
|
checkSub(2,2, circuit);
|
||||||
|
checkSub(2,3, circuit);
|
||||||
|
checkSub(2,-1, circuit);
|
||||||
|
checkSub(2,-2, circuit);
|
||||||
|
checkSub(2,-3, circuit);
|
||||||
|
checkSub(-2,-3, circuit);
|
||||||
|
checkSub(-2,-2, circuit);
|
||||||
|
checkSub(-2,-1, circuit);
|
||||||
|
checkSub(-2,0, circuit);
|
||||||
|
checkSub(-2,1, circuit);
|
||||||
|
checkSub(-2,2, circuit);
|
||||||
|
checkSub(-2,3, circuit);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
35
test/binsum.js
Normal file
35
test/binsum.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
const chai = require("chai");
|
||||||
|
const path = require("path");
|
||||||
|
const snarkjs = require("snarkjs");
|
||||||
|
const crypto = require("crypto");
|
||||||
|
|
||||||
|
const compiler = require("circom");
|
||||||
|
|
||||||
|
const assert = chai.assert;
|
||||||
|
|
||||||
|
describe("Sum test", () => {
|
||||||
|
it("Should create a constant circuit", async () => {
|
||||||
|
|
||||||
|
const cirDef = await compiler(path.join(__dirname, "circuits", "constants_test.circom"));
|
||||||
|
assert.equal(cirDef.nVars, 2);
|
||||||
|
|
||||||
|
const circuit = new snarkjs.Circuit(cirDef);
|
||||||
|
|
||||||
|
const witness = circuit.calculateWitness({ "in": "0xd807aa98" });
|
||||||
|
|
||||||
|
assert(witness[0].equals(snarkjs.bigInt(1)));
|
||||||
|
assert(witness[1].equals(snarkjs.bigInt("0xd807aa98")));
|
||||||
|
});
|
||||||
|
it("Should create a sum circuit", async () => {
|
||||||
|
|
||||||
|
const cirDef = await compiler(path.join(__dirname, "circuits", "sum_test.circom"));
|
||||||
|
assert.equal(cirDef.nVars, 101);
|
||||||
|
|
||||||
|
const circuit = new snarkjs.Circuit(cirDef);
|
||||||
|
|
||||||
|
const witness = circuit.calculateWitness({ "a": "111", "b": "222" });
|
||||||
|
|
||||||
|
assert(witness[0].equals(snarkjs.bigInt(1)));
|
||||||
|
assert(witness[1].equals(snarkjs.bigInt("333")));
|
||||||
|
});
|
||||||
|
});
|
||||||
3
test/circuits/aliascheck_test.circom
Normal file
3
test/circuits/aliascheck_test.circom
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
include "../../circuits/aliascheck.circom";
|
||||||
|
|
||||||
|
component main = AliasCheck()
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
include "../../circuit/babyjub.circom";
|
include "../../circuits/babyjub.circom";
|
||||||
|
|
||||||
component main = BabyAdd();
|
component main = BabyAdd();
|
||||||
|
|||||||
3
test/circuits/babycheck_test.circom
Normal file
3
test/circuits/babycheck_test.circom
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
include "../../circuits/babyjub.circom";
|
||||||
|
|
||||||
|
component main = BabyCheck();
|
||||||
26
test/circuits/binsub_test.circom
Normal file
26
test/circuits/binsub_test.circom
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
include "../../circuits/bitify.circom"
|
||||||
|
include "../../circuits/binsub.circom"
|
||||||
|
|
||||||
|
template A() {
|
||||||
|
signal private input a;
|
||||||
|
signal input b;
|
||||||
|
signal output out;
|
||||||
|
|
||||||
|
component n2ba = Num2Bits(16);
|
||||||
|
component n2bb = Num2Bits(16);
|
||||||
|
component sub = BinSub(16);
|
||||||
|
component b2n = Bits2Num(16);
|
||||||
|
|
||||||
|
n2ba.in <== a;
|
||||||
|
n2bb.in <== b;
|
||||||
|
|
||||||
|
for (var i=0; i<16; i++) {
|
||||||
|
sub.in[0][i] <== n2ba.out[i];
|
||||||
|
sub.in[1][i] <== n2bb.out[i];
|
||||||
|
b2n.in[i] <== sub.out[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
out <== b2n.out;
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = A();
|
||||||
18
test/circuits/constants_test.circom
Normal file
18
test/circuits/constants_test.circom
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
include "../../circuits/sha256/constants.circom"
|
||||||
|
|
||||||
|
template A() {
|
||||||
|
signal input in;
|
||||||
|
component h0;
|
||||||
|
h0 = K(8);
|
||||||
|
|
||||||
|
var lc = 0;
|
||||||
|
var e = 1;
|
||||||
|
for (var i=0; i<32; i++) {
|
||||||
|
lc = lc + e*h0.out[i];
|
||||||
|
e *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
lc === in;
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = A();
|
||||||
3
test/circuits/eddsa_test.circom
Normal file
3
test/circuits/eddsa_test.circom
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
include "../../circuits/eddsa.circom";
|
||||||
|
|
||||||
|
component main = EdDSAVerifier(80);
|
||||||
3
test/circuits/eddsamimc_test.circom
Normal file
3
test/circuits/eddsamimc_test.circom
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
include "../../circuits/eddsamimc.circom";
|
||||||
|
|
||||||
|
component main = EdDSAMiMCVerifier();
|
||||||
3
test/circuits/edwards2montgomery.circom
Normal file
3
test/circuits/edwards2montgomery.circom
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
include "../../circuits/montgomery.circom";
|
||||||
|
|
||||||
|
component main = Edwards2Montgomery();
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
include "../../circuit/escalarmul.circom";
|
include "../../circuits/escalarmul.circom";
|
||||||
|
|
||||||
|
|
||||||
template Main() {
|
template Main() {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
include "../../circuit/escalarmul.circom";
|
include "../../circuits/escalarmul.circom";
|
||||||
include "../../node_modules/circom/circuits/bitify.circom";
|
include "../../circuits/bitify.circom";
|
||||||
|
|
||||||
|
|
||||||
template Main() {
|
template Main() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
include "../../circuit/escalarmul.circom";
|
include "../../circuits/escalarmul.circom";
|
||||||
|
|
||||||
|
|
||||||
template Main() {
|
template Main() {
|
||||||
|
|||||||
28
test/circuits/escalarmulany_test.circom
Normal file
28
test/circuits/escalarmulany_test.circom
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
include "../../circuits/escalarmulany.circom";
|
||||||
|
include "../../circuits/bitify.circom";
|
||||||
|
|
||||||
|
template Main() {
|
||||||
|
signal input e;
|
||||||
|
signal input p[2];
|
||||||
|
signal output out[2];
|
||||||
|
|
||||||
|
component n2b = Num2Bits(253);
|
||||||
|
component escalarMulAny = EscalarMulAny(253);
|
||||||
|
|
||||||
|
escalarMulAny.p[0] <== p[0];
|
||||||
|
escalarMulAny.p[1] <== p[1];
|
||||||
|
|
||||||
|
var i;
|
||||||
|
|
||||||
|
e ==> n2b.in;
|
||||||
|
|
||||||
|
for (i=0; i<253; i++) {
|
||||||
|
n2b.out[i] ==> escalarMulAny.e[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
escalarMulAny.out[0] ==> out[0];
|
||||||
|
escalarMulAny.out[1] ==> out[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = Main();
|
||||||
|
|
||||||
29
test/circuits/escalarmulfix_test.circom
Normal file
29
test/circuits/escalarmulfix_test.circom
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
include "../../circuits/escalarmulfix.circom";
|
||||||
|
include "../../circuits/bitify.circom";
|
||||||
|
|
||||||
|
|
||||||
|
template Main() {
|
||||||
|
signal input e;
|
||||||
|
signal output out[2];
|
||||||
|
|
||||||
|
var base = [17777552123799933955779906779655732241715742912184938656739573121738514868268,
|
||||||
|
2626589144620713026669568689430873010625803728049924121243784502389097019475]
|
||||||
|
|
||||||
|
|
||||||
|
component n2b = Num2Bits(253);
|
||||||
|
component escalarMul = EscalarMulFix(253, base);
|
||||||
|
|
||||||
|
var i;
|
||||||
|
|
||||||
|
e ==> n2b.in;
|
||||||
|
|
||||||
|
for (i=0; i<253; i++) {
|
||||||
|
n2b.out[i] ==> escalarMul.e[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
escalarMul.out[0] ==> out[0];
|
||||||
|
escalarMul.out[1] ==> out[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = Main();
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
include "../../circuit/escalarmulw4table.circom";
|
include "../../circuits/escalarmulw4table.circom";
|
||||||
|
|
||||||
var base = [17777552123799933955779906779655732241715742912184938656739573121738514868268,
|
var base = [17777552123799933955779906779655732241715742912184938656739573121738514868268,
|
||||||
2626589144620713026669568689430873010625803728049924121243784502389097019475]
|
2626589144620713026669568689430873010625803728049924121243784502389097019475]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
include "../../circuit/escalarmulw4table.circom";
|
include "../../circuits/escalarmulw4table.circom";
|
||||||
|
|
||||||
var base = [17777552123799933955779906779655732241715742912184938656739573121738514868268,
|
var base = [17777552123799933955779906779655732241715742912184938656739573121738514868268,
|
||||||
2626589144620713026669568689430873010625803728049924121243784502389097019475];
|
2626589144620713026669568689430873010625803728049924121243784502389097019475];
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
include "../../circuit/escalarmulw4table.circom";
|
include "../../circuits/escalarmulw4table.circom";
|
||||||
|
|
||||||
var base = [17777552123799933955779906779655732241715742912184938656739573121738514868268,
|
var base = [17777552123799933955779906779655732241715742912184938656739573121738514868268,
|
||||||
2626589144620713026669568689430873010625803728049924121243784502389097019475]
|
2626589144620713026669568689430873010625803728049924121243784502389097019475]
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
include "../../circuit/escalarmul.circom";
|
|
||||||
include "../../node_modules/circom/circuits/sha256/bitify.circom";
|
|
||||||
|
|
||||||
|
|
||||||
template Main() {
|
|
||||||
signal input in;
|
|
||||||
signal output out[2];
|
|
||||||
|
|
||||||
component n2b = Num2Bits(253);
|
|
||||||
component escalarMul = EscalarMul(253);
|
|
||||||
|
|
||||||
var i;
|
|
||||||
|
|
||||||
in ==> n2b.in;
|
|
||||||
|
|
||||||
for (i=0; i<253; i++) {
|
|
||||||
n2b.out[i] ==> escalarMul.in[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
escalarMul.out[0] ==> out[0];
|
|
||||||
escalarMul.out[1] ==> out[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
component main = Main();
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
include "../../circuit/escalarmul.circom";
|
|
||||||
|
|
||||||
|
|
||||||
template Main() {
|
|
||||||
signal input in[256];
|
|
||||||
signal output out[2];
|
|
||||||
|
|
||||||
var i;
|
|
||||||
|
|
||||||
component escalarMul = EscalarMul(256);
|
|
||||||
|
|
||||||
for (i=0; i<256; i++) {
|
|
||||||
in[i] ==> escalarMul.in[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
escalarMul.out[0] ==> out[0];
|
|
||||||
escalarMul.out[1] ==> out[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
component main = Main();
|
|
||||||
4
test/circuits/isequal.circom
Normal file
4
test/circuits/isequal.circom
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
include "../../circuits/comparators.circom";
|
||||||
|
|
||||||
|
component main = IsEqual();
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user