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