Browse Source

Pedersen2 and BitPoints MulFix and MulAny

feature/synctests2
Jordi Baylina 5 years ago
parent
commit
55e9a60c37
No known key found for this signature in database GPG Key ID: 7480C80C1BE43112
40 changed files with 2267 additions and 75 deletions
  1. +14
    -0
      circuit/aliascheck.circom
  2. +33
    -0
      circuit/babyjub.circom
  3. +56
    -0
      circuit/compconstant.circom
  4. +104
    -10
      circuit/eddsa.circom
  5. +174
    -0
      circuit/escalarmulany.circom
  6. +258
    -0
      circuit/escalarmulfix.circom
  7. +123
    -0
      circuit/montgomery.circom
  8. +55
    -0
      circuit/mux3.circom
  9. +4
    -4
      circuit/pedersen.circom
  10. +236
    -0
      circuit/pedersen2.circom
  11. +144
    -0
      circuit/pointbits.circom
  12. +16
    -0
      circuit/sign.circom
  13. +56
    -8
      src/babyjub.js
  14. +92
    -0
      src/eddsa.js
  15. +110
    -0
      src/pedersenHash.js
  16. +13
    -0
      src/printBases.js
  17. +10
    -0
      test.js
  18. +74
    -0
      test/aliascheck.js
  19. +42
    -40
      test/babyjub.js
  20. +3
    -0
      test/circuits/aliascheck_test.circom
  21. +3
    -0
      test/circuits/babycheck_test.circom
  22. +3
    -0
      test/circuits/edwards2montgomery.circom
  23. +28
    -0
      test/circuits/escalarmulany_test.circom
  24. +29
    -0
      test/circuits/escalarmulfix_test.circom
  25. +3
    -0
      test/circuits/montgomery2edwards.circom
  26. +3
    -0
      test/circuits/montgomeryadd.circom
  27. +3
    -0
      test/circuits/montgomerydouble.circom
  28. +39
    -0
      test/circuits/mux3_1.circom
  29. +32
    -0
      test/circuits/pedersen2_test.circom
  30. +5
    -5
      test/circuits/pedersen_test.circom
  31. +23
    -0
      test/circuits/pointbits_loopback.circom
  32. +3
    -0
      test/circuits/sign_test.circom
  33. +59
    -0
      test/escalarmulany.js
  34. +67
    -0
      test/escalarmulfix.js
  35. +99
    -0
      test/montgomery.js
  36. +55
    -7
      test/multiplexer.js
  37. +1
    -1
      test/pedersen.js
  38. +74
    -0
      test/pedersen2.js
  39. +33
    -0
      test/point2bits.js
  40. +88
    -0
      test/sign.js

+ 14
- 0
circuit/aliascheck.circom

@ -0,0 +1,14 @@
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;
}

+ 33
- 0
circuit/babyjub.circom

@ -29,3 +29,36 @@ template BabyAdd() {
yout <-- (delta - a * epsilon) / (1-d*tau);
(1-d*tau)*yout === (delta - a * epsilon);
}
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;
}

+ 56
- 0
circuit/compconstant.circom

@ -0,0 +1,56 @@
include "../node_modules/circom/circuits/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];
}

+ 104
- 10
circuit/eddsa.circom

@ -1,22 +1,116 @@
include "../node_modules/circom/circuits/bitify.circom";
include "../node_modules/circom/circuits/comparators.circom";
include "escalarmulany.circom";
include "babyjub.circom";
templete EdDSAVerfier(n) {
signal input msg[n];
templete Verfier() {
signal input hMsg[256];
signal input A[256];
signal input R8[256];
signal input S[256];
signal input Ax;
signal input Ay;
signal Ax;
signal Ay;
signal input Rx;
signal input Ry;
signal R8x;
signal R8y;
signal input s[256];
var i;
// Ensure S<Subgroup Order
componet exps = Exp();
component exph = Exp();
component compConstant = CompConstant(2736030358979909402780800718157159386076813972158567259200215660948447373040);
component adder = BabyAdd();
for (var i=0; i<254; i++) {
S[i] ==> compConstant.in[i];
}
compConstant.out === 0;
S[255] === 0;
S[256] === 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] <== R[i];
hash.in[256+i] <== A[i];
}
for (i=0; i<n; i++) {
hash.in[512+i] <== msg[i];
}
// 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.outx;
dbl2.y <== dbl1.outy;
component dbl3 = BabyDbl();
dbl3.x <== dbl2.outx;
dbl3.y <== dbl2.outy;
// 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] <== hash.out[i];
}
mulAny.p[0] <== dbl3.outx;
mulAny.p[1] <== dbl3.outy;
// 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;
}

+ 174
- 0
circuit/escalarmulany.circom

@ -0,0 +1,174 @@
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 BitElement() {
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 Segment(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] = BitElement();
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] = BitElement();
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] = Segment(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];
}
}

+ 258
- 0
circuit/escalarmulfix.circom

@ -0,0 +1,258 @@
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];
}
}

+ 123
- 0
circuit/montgomery.circom

@ -0,0 +1,123 @@
/*
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];
}

+ 55
- 0
circuit/mux3.circom

@ -0,0 +1,55 @@
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;
}

+ 4
- 4
circuit/pedersen.circom

@ -5,8 +5,8 @@ template Pedersen(n) {
signal input in[n];
signal output out[2];
var nexps = ((n-1) \ 253) + 1;
var nlastbits = n - (nexps-1)*253;
var nexps = ((n-1) \ 250) + 1;
var nlastbits = n - (nexps-1)*250;
component escalarMuls[nexps];
@ -27,11 +27,11 @@ template Pedersen(n) {
var j;
var nexpbits;
for (i=0; i<nexps; i++) {
nexpbits = (i == nexps-1) ? nlastbits : 253;
nexpbits = (i == nexps-1) ? nlastbits : 250;
escalarMuls[i] = EscalarMul(nexpbits, PBASE[i]);
for (j=0; j<nexpbits; j++) {
escalarMuls[i].in[j] <== in[253*i + j];
escalarMuls[i].in[j] <== in[250*i + j];
}
if (i==0) {

+ 236
- 0
circuit/pedersen2.circom

@ -0,0 +1,236 @@
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 = [
[7889815880984390413826091016397158135734961432619494935997950708325418623781,8846020814737052626835496416415322522216827521798085437978304928900248828704],
[12932435660254426850246080929365951045207624124386035886549006330955720993567,15876660444082442781217588393435527739441124986236154572507597829115005542086],
[2482397177297734131621151094340467680859038448217226675361423673093734165962,10039279516804305991696249700635360957313934801940294703211894781106216299926],
[17157815998940296936592098789990444736073034804807810484873853349962905015352,6488208869655503622669430389521947006738035600928015942696596112432120303604],
[264004460746169389447419243214191481604172623204375600962322511417379874376,2415858116338771134001541482988382151008857516531390792628421155957250972277],
[4135925743285698117252356077971179769271452015650275231796007492648697405139,10188226868678337759614729372197905253307539893323271103976079007344248400845],
[1774758779250924961062140611815304699163957993414252473010092444201412186500,4347026286058522695608532575722049241297833321096891696953943795644684841805],
[7879866447646097585900946926276218605564915618236971624614091698429769712458,2093592432852088858177276030443845730480437238346603396739626046140688969347],
[8298560996095230984182228319122592575131718101813938808256495049817179791777,1767915891871602626938298102360238720016341966012238026281701463959008338852],
[10415885340847357003805466620366840573458521568359796855704531856219635265921,3432650026491357206165099540731361444311747596326968441647905394914712226413]
]
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].xout;
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];
}
}

+ 144
- 0
circuit/pointbits.circom

@ -0,0 +1,144 @@
include "../node_modules/circom/circuits/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;
}

+ 16
- 0
circuit/sign.circom

@ -0,0 +1,16 @@
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;
}

+ 56
- 8
src/babyjub.js

@ -4,6 +4,17 @@ 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;
@ -32,26 +43,63 @@ function mulPointEscalar(base, e) {
return res;
}
function isLowGrade(p) {
const r = bigInt("21888242871839275222246405745257275088614511777268538073601725287587578984328").shr(3);
const res= mulPointEscalar(p, r);
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) {
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]);
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;
if (!isLowGrade(p)) 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;
}

+ 92
- 0
src/eddsa.js

@ -0,0 +1,92 @@
const createBlakeHash = require("blake-hash");
const bigInt = require("snarkjs").bigInt;
const babyJub = require("./babyjub");
const pedersenHash = require("./pedersenHash").hash;
const crypto = require("crypto");
exports.cratePrvKey = cratePrvKey;
exports.prv2pub= prv2pub;
exports.sign = sign;
exports.verify = verify;
exports.packSignature = packSignature;
exports.unpackSignature = unpackSignature;
function cratePrvKey() {
return crypto.randomBytes(32);
}
function pruneBuffer(_buff) {
const buff = Buffer.from(_buff);
buff[0] = buff[0] & 0xF8;
buff[31] = buff[31] & 0x7F;
buff[31] = buff[31] | 0x40;
}
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 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(sig.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(8));
Pright = babyJub.addaddPoint(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))
};
}

+ 110
- 0
src/pedersenHash.js

@ -0,0 +1,110 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const babyJub = require("./babyjub");
const assert = require("assert");
const createBlakeHash = require("blake-hash");
const GENPOINT_PREFIX = "Iden3_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);
assert(babyJub.inSubgroup(p8), "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
- 0
src/printBases.js

@ -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]}]`);
}

+ 10
- 0
test.js

@ -0,0 +1,10 @@
const snarkjs = require("snarkjs");
let n = 16352677002768649294638363183714474939219394808856154771098596513875516795430n
let r = snarkjs.bn128.Fr.sqrt(n)
r = snarkjs.bn128.Fr.q -r;
console.log(r.toString());

+ 74
- 0
test/aliascheck.js

@ -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");
}
});
});

+ 42
- 40
test/babyjub.js

@ -8,30 +8,35 @@ const assert = chai.assert;
const bigInt = require("big-integer");
describe("Baby Jub test", () => {
it("Should add point (0,1) and (0,1)", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "babyadd_tester.circom"));
describe("Baby Jub test", function () {
let circuitAdd;
let circuitTest;
// console.log(JSON.stringify(cirDef, null, 1));
this.timeout(100000);
// assert.equal(cirDef.nVars, 2);
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 circuit = new snarkjs.Circuit(cirDef);
const cirDefTest = await compiler(path.join(__dirname, "circuits", "babycheck_test.circom"));
circuitTest = new snarkjs.Circuit(cirDefTest);
console.log("NConstrains BabyTest: " + circuitTest.nConstraints);
});
console.log("NConstrains: " + circuit.nConstraints);
it("Should add point (0,1) and (0,1)", async () => {
const input={
x1: snarkjs.bigInt(0),
y1: snarkjs.bigInt(1),
x2: snarkjs.bigInt(0),
y2: snarkjs.bigInt(1)
}
};
const w = circuit.calculateWitness(input);
const w = circuitAdd.calculateWitness(input);
const xout = w[circuit.getSignalIdx("main.xout")];
const yout = w[circuit.getSignalIdx("main.yout")];
const xout = w[circuitAdd.getSignalIdx("main.xout")];
const yout = w[circuitAdd.getSignalIdx("main.yout")];
assert(xout.equals(0));
assert(yout.equals(1));
@ -39,27 +44,17 @@ describe("Baby Jub test", () => {
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={
x1: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
y1: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
x2: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
y2: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475")
}
};
const w = circuit.calculateWitness(input);
const w = circuitAdd.calculateWitness(input);
const xout = w[circuit.getSignalIdx("main.xout")];
const yout = w[circuit.getSignalIdx("main.yout")];
const xout = w[circuitAdd.getSignalIdx("main.xout")];
const yout = w[circuitAdd.getSignalIdx("main.yout")];
assert(xout.equals(snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365")));
assert(yout.equals(snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889")));
@ -67,32 +62,39 @@ describe("Baby Jub test", () => {
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={
x1: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
y1: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
x2: snarkjs.bigInt("16540640123574156134436876038791482806971768689494387082833631921987005038935"),
y2: snarkjs.bigInt("20819045374670962167435360035096875258406992893633759881276124905556507972311")
}
};
const w = circuit.calculateWitness(input);
const w = circuitAdd.calculateWitness(input);
const xout = w[circuit.getSignalIdx("main.xout")];
const yout = w[circuit.getSignalIdx("main.yout")];
const xout = w[circuitAdd.getSignalIdx("main.xout")];
const yout = w[circuitAdd.getSignalIdx("main.yout")];
/*
console.log(xout.toString());
console.log(yout.toString());
*/
assert(xout.equals(snarkjs.bigInt("7916061937171219682591368294088513039687205273691143098332585753343424131937")));
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");
}
});
});

+ 3
- 0
test/circuits/aliascheck_test.circom

@ -0,0 +1,3 @@
include "../../circuit/aliascheck.circom";
component main = AliasCheck()

+ 3
- 0
test/circuits/babycheck_test.circom

@ -0,0 +1,3 @@
include "../../circuit/babyjub.circom";
component main = BabyCheck();

+ 3
- 0
test/circuits/edwards2montgomery.circom

@ -0,0 +1,3 @@
include "../../circuit/montgomery.circom";
component main = Edwards2Montgomery();

+ 28
- 0
test/circuits/escalarmulany_test.circom

@ -0,0 +1,28 @@
include "../../circuit/escalarmulany.circom";
include "../../node_modules/circom/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
- 0
test/circuits/escalarmulfix_test.circom

@ -0,0 +1,29 @@
include "../../circuit/escalarmulfix.circom";
include "../../node_modules/circom/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();

+ 3
- 0
test/circuits/montgomery2edwards.circom

@ -0,0 +1,3 @@
include "../../circuit/montgomery.circom";
component main = Montgomery2Edwards();

+ 3
- 0
test/circuits/montgomeryadd.circom

@ -0,0 +1,3 @@
include "../../circuit/montgomery.circom";
component main = MontgomeryAdd();

+ 3
- 0
test/circuits/montgomerydouble.circom

@ -0,0 +1,3 @@
include "../../circuit/montgomery.circom";
component main = MontgomeryDouble();

+ 39
- 0
test/circuits/mux3_1.circom

@ -0,0 +1,39 @@
include "../../circuit/mux3.circom";
include "../../node_modules/circom/circuits/bitify.circom";
template Constants() {
var i;
signal output out[8];
out[0] <== 37;
out[1] <== 47;
out[2] <== 53;
out[3] <== 71;
out[4] <== 89;
out[5] <== 107;
out[6] <== 163;
out[7] <== 191;
}
template Main() {
var i;
signal private input selector;
signal output out;
component mux = Mux3();
component n2b = Num2Bits(3);
component cst = Constants();
selector ==> n2b.in;
for (i=0; i<3; i++) {
n2b.out[i] ==> mux.s[i];
}
for (i=0; i<8; i++) {
cst.out[i] ==> mux.c[i];
}
mux.out ==> out;
}
component main = Main();

+ 32
- 0
test/circuits/pedersen2_test.circom

@ -0,0 +1,32 @@
include "../../circuit/pedersen2.circom";
include "../../node_modules/circom/circuits/bitify.circom";
template Main() {
signal input in;
signal output out[2];
component pedersen = Pedersen(256);
component n2b;
n2b = Num2Bits(253);
var i;
in ==> n2b.in;
for (i=0; i<253; i++) {
pedersen.in[i] <== n2b.out[i];
}
for (i=253; i<256; i++) {
pedersen.in[i] <== 0;
}
pedersen.out[0] ==> out[0];
pedersen.out[1] ==> out[1];
}
component main = Main();

+ 5
- 5
test/circuits/pedersen_test.circom

@ -6,20 +6,20 @@ template Main() {
signal input in[2];
signal output out[2];
component pedersen = Pedersen(253*2);
component pedersen = Pedersen(250*2);
component n2b[2];
n2b[0] = Num2Bits(253);
n2b[1] = Num2Bits(253);
n2b[0] = Num2Bits(250);
n2b[1] = Num2Bits(250);
var i;
in[0] ==> n2b[0].in;
in[1] ==> n2b[1].in;
for (i=0; i<253; i++) {
for (i=0; i<250; i++) {
n2b[0].out[i] ==> pedersen.in[i];
n2b[1].out[i] ==> pedersen.in[253+i];
n2b[1].out[i] ==> pedersen.in[250+i];
}
pedersen.out[0] ==> out[0];

+ 23
- 0
test/circuits/pointbits_loopback.circom

@ -0,0 +1,23 @@
include "../../circuit/pointbits.circom";
template Main() {
signal input in[2];
var i
component p2b = Point2Bits_Strict();
component b2p = Bits2Point_Strict();
p2b.in[0] <== in[0];
p2b.in[1] <== in[1];
for (i=0; i<256; i++) {
b2p.in[i] <== p2b.out[i];
}
b2p.out[0] === in[0];
b2p.out[1] === in[1];
}
component main = Main();

+ 3
- 0
test/circuits/sign_test.circom

@ -0,0 +1,3 @@
include "../../circuit/sign.circom";
component main = Sign();

+ 59
- 0
test/escalarmulany.js

@ -0,0 +1,59 @@
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)]);
}
describe("Escalarmul test", function () {
let circuitEMulAny;
this.timeout(100000);
let g = [
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475")
];
before( async() => {
const cirDefEMulAny = await compiler(path.join(__dirname, "circuits", "escalarmulany_test.circom"));
circuitEMulAny = new snarkjs.Circuit(cirDefEMulAny);
console.log("NConstrains Escalarmul any: " + circuitEMulAny.nConstraints);
});
it("Should generate Same escalar mul", async () => {
const w = circuitEMulAny.calculateWitness({"e": 1, "p": g});
assert(circuitEMulAny.checkWitness(w));
const xout = w[circuitEMulAny.getSignalIdx("main.out[0]")];
const yout = w[circuitEMulAny.getSignalIdx("main.out[1]")];
assert(xout.equals(g[0]));
assert(yout.equals(g[1]));
});
it("If multiply by order should return 0", async () => {
const r = bigInt("2736030358979909402780800718157159386076813972158567259200215660948447373041");
const w = circuitEMulAny.calculateWitness({"e": r, "p": g});
assert(circuitEMulAny.checkWitness(w));
const xout = w[circuitEMulAny.getSignalIdx("main.out[0]")];
const yout = w[circuitEMulAny.getSignalIdx("main.out[1]")];
assert(xout.equals(bigInt.zero));
assert(yout.equals(bigInt.one));
});
});

+ 67
- 0
test/escalarmulfix.js

@ -0,0 +1,67 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const babyjub = require("../src/babyjub");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
function print(circuit, w, s) {
console.log(s + ": " + w[circuit.getSignalIdx(s)]);
}
describe("Escalarmul test", function () {
let circuit;
this.timeout(100000);
before( async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "escalarmulfix_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains Escalarmul fix: " + circuit.nConstraints);
});
it("Should generate Same escalar mul", async () => {
const w = circuit.calculateWitness({"e": 0});
assert(circuit.checkWitness(w));
const xout = w[circuit.getSignalIdx("main.out[0]")];
const yout = w[circuit.getSignalIdx("main.out[1]")];
assert(xout.equals(0));
assert(yout.equals(1));
});
it("Should generate Same escalar mul", async () => {
const w = circuit.calculateWitness({"e": 1});
assert(circuit.checkWitness(w));
const xout = w[circuit.getSignalIdx("main.out[0]")];
const yout = w[circuit.getSignalIdx("main.out[1]")];
assert(xout.equals(babyjub.Base8[0]));
assert(yout.equals(babyjub.Base8[1]));
});
it("If multiply by order should return 0", async () => {
const w = circuit.calculateWitness({"e": babyjub.subOrder });
assert(circuit.checkWitness(w));
const xout = w[circuit.getSignalIdx("main.out[0]")];
const yout = w[circuit.getSignalIdx("main.out[1]")];
assert(xout.equals(bigInt.zero));
assert(yout.equals(bigInt.one));
});
});

+ 99
- 0
test/montgomery.js

@ -0,0 +1,99 @@
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 = snarkjs.bigInt;
describe("Montgomery test", function () {
let circuitE2M;
let circuitM2E;
let circuitMAdd;
let circuitMDouble;
let g = [
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475")];
let mg, mg2, g2, g3, mg3;
this.timeout(100000);
before( async() => {
const cirDefE2M = await compiler(path.join(__dirname, "circuits", "edwards2montgomery.circom"));
circuitE2M = new snarkjs.Circuit(cirDefE2M);
console.log("NConstrains Edwards -> Montgomery: " + circuitE2M.nConstraints);
const cirDefM2E = await compiler(path.join(__dirname, "circuits", "montgomery2edwards.circom"));
circuitM2E = new snarkjs.Circuit(cirDefM2E);
console.log("NConstrains Montgomery -> Edwards: " + circuitM2E.nConstraints);
const cirDefMAdd = await compiler(path.join(__dirname, "circuits", "montgomeryadd.circom"));
circuitMAdd = new snarkjs.Circuit(cirDefMAdd);
console.log("NConstrains Montgomery Add: " + circuitMAdd.nConstraints);
const cirDefMDouble = await compiler(path.join(__dirname, "circuits", "montgomerydouble.circom"));
circuitMDouble = new snarkjs.Circuit(cirDefMDouble);
console.log("NConstrains Montgomery Double: " + circuitMDouble.nConstraints);
});
it("Convert Edwards to Montgomery and back again", async () => {
let w, xout, yout;
w = circuitE2M.calculateWitness({ in: g});
xout = w[circuitE2M.getSignalIdx("main.out[0]")];
yout = w[circuitE2M.getSignalIdx("main.out[1]")];
mg = [xout, yout];
w = circuitM2E.calculateWitness({ in: [xout, yout]});
xout = w[circuitM2E.getSignalIdx("main.out[0]")];
yout = w[circuitM2E.getSignalIdx("main.out[1]")];
assert(xout.equals(g[0]));
assert(yout.equals(g[1]));
});
it("Should double a point", async () => {
let w, xout, yout;
g2 = babyJub.addPoint(g,g);
w = circuitMDouble.calculateWitness({ in: mg});
xout = w[circuitE2M.getSignalIdx("main.out[0]")];
yout = w[circuitE2M.getSignalIdx("main.out[1]")];
mg2 = [xout, yout];
w = circuitM2E.calculateWitness({ in: mg2});
xout = w[circuitM2E.getSignalIdx("main.out[0]")];
yout = w[circuitM2E.getSignalIdx("main.out[1]")];
assert(xout.equals(g2[0]));
assert(yout.equals(g2[1]));
});
it("Should add a point", async () => {
let w, xout, yout;
g3 = babyJub.addPoint(g,g2);
w = circuitMAdd.calculateWitness({ in1: mg, in2: mg2});
xout = w[circuitMAdd.getSignalIdx("main.out[0]")];
yout = w[circuitMAdd.getSignalIdx("main.out[1]")];
mg3 = [xout, yout];
w = circuitM2E.calculateWitness({ in: mg3});
xout = w[circuitM2E.getSignalIdx("main.out[0]")];
yout = w[circuitM2E.getSignalIdx("main.out[1]")];
assert(xout.equals(g3[0]));
assert(yout.equals(g3[1]));
});
});

+ 55
- 7
test/multiplexer.js

@ -5,7 +5,7 @@ const compiler = require("circom");
const assert = chai.assert;
const bigInt = require("big-integer");
const bigInt = snarkjs.bigInt;
describe("Mux4 test", () => {
@ -19,15 +19,63 @@ describe("Mux4 test", () => {
const circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains: " + circuit.nConstraints);
console.log("NConstrains Mux4: " + circuit.nConstraints);
for (i=0; i<16; i++) {
const w = circuit.calculateWitness({ "selector": snarkjs.bigInt(i).toString() });
const ct16 = [
bigInt("123"),
bigInt("456"),
bigInt("789"),
bigInt("012"),
bigInt("111"),
bigInt("222"),
bigInt("333"),
bigInt("4546"),
bigInt("134523"),
bigInt("44356"),
bigInt("15623"),
bigInt("4566"),
bigInt("1223"),
bigInt("4546"),
bigInt("4256"),
bigInt("4456")
];
assert(w[0].equals(snarkjs.bigInt(1)));
for (let i=0; i<16; i++) {
const w = circuit.calculateWitness({ "selector": i });
console.log(i + " -> " + w[circuit.getSignalIdx("main.out")].toString());
// assert(w[circuit.getSignalIdx("main.out")].equals(snarkjs.bigInt("100").add(snarkjs.bigInt(i))));
assert(w[0].equals(bigInt(1)));
// console.log(i + " -> " + w[circuit.getSignalIdx("main.out")].toString());
assert(w[circuit.getSignalIdx("main.out")].equals(ct16[i]));
}
});
it("Should create a constant multiplexer", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "mux3_1.circom"));
const circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains Mux3: " + circuit.nConstraints);
const ct8 = [
bigInt("37"),
bigInt("47"),
bigInt("53"),
bigInt("71"),
bigInt("89"),
bigInt("107"),
bigInt("163"),
bigInt("191")
];
for (let i=0; i<8; i++) {
const w = circuit.calculateWitness({ "selector": i });
assert(w[0].equals(bigInt(1)));
// console.log(i + " -> " + w[circuit.getSignalIdx("main.out")].toString());
assert(w[circuit.getSignalIdx("main.out")].equals(ct8[i]));
}
});
});

+ 1
- 1
test/pedersen.js

@ -88,7 +88,7 @@ describe("Double Pedersen test", function() {
it("Should pedersen all ones", async () => {
let w, xout, yout;
const allOnes = bigInt("1").shl(251).sub(bigInt("1"));
const allOnes = bigInt("1").shl(250).sub(bigInt("1"));
w = circuit.calculateWitness({ in: [allOnes, allOnes]});
xout = w[circuit.getSignalIdx("main.out[0]")];

+ 74
- 0
test/pedersen2.js

@ -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;
const babyJub = require("../src/babyjub.js");
const pedersen = require("../src/pedersenHash.js");
describe("Pedersen test", function() {
let circuit;
this.timeout(100000);
before( async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "pedersen2_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains Pedersen2: " + circuit.nConstraints);
});
it("Should pedersen at zero", async () => {
let w, xout, yout;
w = circuit.calculateWitness({ in: 0});
xout = w[circuit.getSignalIdx("main.out[0]")];
yout = w[circuit.getSignalIdx("main.out[1]")];
const b = Buffer.alloc(32);
const h = pedersen.hash(b);
const hP = babyJub.unpackPoint(h);
/*
console.log(`[${xout.toString()}, ${yout.toString()}]`);
console.log(`[${hP[0].toString()}, ${hP[1].toString()}]`);
*/
assert(xout.equals(hP[0]));
assert(yout.equals(hP[1]));
});
it("Should pedersen with 253 ones", async () => {
let w, xout, yout;
const n = bigInt.one.shl(253).sub(bigInt.one);
console.log(n.toString(16));
w = circuit.calculateWitness({ in: n});
xout = w[circuit.getSignalIdx("main.out[0]")];
yout = w[circuit.getSignalIdx("main.out[1]")];
const b = Buffer.alloc(32);
for (let i=0; i<31; i++) b[i] = 0xFF;
b[31] = 0x1F;
const h = pedersen.hash(b);
const hP = babyJub.unpackPoint(h);
/*
console.log(`[${xout.toString()}, ${yout.toString()}]`);
console.log(`[${hP[0].toString()}, ${hP[1].toString()}]`);
*/
assert(xout.equals(hP[0]));
assert(yout.equals(hP[1]));
});
});

+ 33
- 0
test/point2bits.js

@ -0,0 +1,33 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
const babyJub = require("../src/babyjub.js");
describe("Point 2 bits test", function() {
let circuit;
this.timeout(100000);
before( async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "pointbits_loopback.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains Point2Bits loopback: " + circuit.nConstraints);
});
it("Should do the both convertions for 8Base", async () => {
const w = circuit.calculateWitness({ in: babyJub.Base8});
assert(circuit.checkWitness(w));
});
it("Should do the both convertions for Zero point", async () => {
const w = circuit.calculateWitness({ in: [0, 1]});
assert(circuit.checkWitness(w));
});
});

+ 88
- 0
test/sign.js

@ -0,0 +1,88 @@
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", "sign_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains: " + circuit.nConstraints);
});
it("Sign of 0", async () => {
const inp = getBits(bigInt.zero, 254);
const w = circuit.calculateWitness({in: inp});
assert( w[circuit.getSignalIdx("main.sign")].equals(bigInt(0)) );
});
it("Sign of 3", async () => {
const inp = getBits(bigInt(3), 254);
const w = circuit.calculateWitness({in: inp});
assert( w[circuit.getSignalIdx("main.sign")].equals(bigInt(0)) );
});
it("Sign of q/2", async () => {
const inp = getBits(q.shr(bigInt.one), 254);
const w = circuit.calculateWitness({in: inp});
assert( w[circuit.getSignalIdx("main.sign")].equals(bigInt(0)) );
});
it("Sign of q/2+1", async () => {
const inp = getBits(q.shr(bigInt.one).add(bigInt.one), 254);
const w = circuit.calculateWitness({in: inp});
assert( w[circuit.getSignalIdx("main.sign")].equals(bigInt(1)) );
});
it("Sign of q-1", async () => {
const inp = getBits(q.sub(bigInt.one), 254);
const w = circuit.calculateWitness({in: inp});
assert( w[circuit.getSignalIdx("main.sign")].equals(bigInt(1)) );
});
it("Sign of q", async () => {
const inp = getBits(q, 254);
const w = circuit.calculateWitness({in: inp});
assert( w[circuit.getSignalIdx("main.sign")].equals(bigInt(1)) );
});
it("Sign of all ones", async () => {
const inp = getBits(bigInt(1).shl(254).sub(bigInt(1)), 254);
const w = circuit.calculateWitness({in: inp});
assert( w[circuit.getSignalIdx("main.sign")].equals(bigInt(1)) );
});
});

Loading…
Cancel
Save