|
|
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]; } }
|