@ -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; |
||||
|
} |
@ -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]; |
||||
|
} |
@ -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; |
||||
} |
} |
@ -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]; |
||||
|
} |
||||
|
} |
@ -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]; |
||||
|
} |
||||
|
} |
@ -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]; |
||||
|
} |
@ -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; |
||||
|
} |
@ -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]; |
||||
|
} |
||||
|
} |
||||
|
|
@ -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; |
||||
|
} |
@ -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; |
||||
|
} |
@ -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)) |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
|
@ -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; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
@ -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]}]`); |
||||
|
} |
@ -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()); |
||||
|
|
@ -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"); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
}); |
@ -0,0 +1,3 @@ |
|||||
|
include "../../circuit/aliascheck.circom"; |
||||
|
|
||||
|
component main = AliasCheck() |
@ -0,0 +1,3 @@ |
|||||
|
include "../../circuit/babyjub.circom"; |
||||
|
|
||||
|
component main = BabyCheck(); |
@ -0,0 +1,3 @@ |
|||||
|
include "../../circuit/montgomery.circom"; |
||||
|
|
||||
|
component main = Edwards2Montgomery(); |
@ -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(); |
||||
|
|
@ -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(); |
||||
|
|
@ -0,0 +1,3 @@ |
|||||
|
include "../../circuit/montgomery.circom"; |
||||
|
|
||||
|
component main = Montgomery2Edwards(); |
@ -0,0 +1,3 @@ |
|||||
|
include "../../circuit/montgomery.circom"; |
||||
|
|
||||
|
component main = MontgomeryAdd(); |
@ -0,0 +1,3 @@ |
|||||
|
include "../../circuit/montgomery.circom"; |
||||
|
|
||||
|
component main = MontgomeryDouble(); |
@ -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(); |
@ -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(); |
||||
|
|
||||
|
|
@ -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(); |
@ -0,0 +1,3 @@ |
|||||
|
include "../../circuit/sign.circom"; |
||||
|
|
||||
|
component main = Sign(); |
@ -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)); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
@ -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)); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
@ -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])); |
||||
|
}); |
||||
|
}); |
@ -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])); |
||||
|
}); |
||||
|
}); |
@ -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)); |
||||
|
}); |
||||
|
}); |
@ -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)) ); |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
}); |