mirror of
https://github.com/arnaucube/circomlib.git
synced 2026-02-07 03:06:44 +01:00
Pedersen2 and BitPoints MulFix and MulAny
This commit is contained in:
14
circuit/aliascheck.circom
Normal file
14
circuit/aliascheck.circom
Normal file
@@ -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;
|
||||
}
|
||||
@@ -29,3 +29,36 @@ template BabyAdd() {
|
||||
yout <-- (delta - a * epsilon) / (1-d*tau);
|
||||
(1-d*tau)*yout === (delta - a * epsilon);
|
||||
}
|
||||
|
||||
template BabyDbl() {
|
||||
signal input x;
|
||||
signal input y;
|
||||
signal output xout;
|
||||
signal output yout;
|
||||
|
||||
component adder = BabyAdd();
|
||||
adder.x1 <== x;
|
||||
adder.y1 <== y;
|
||||
adder.x2 <== x;
|
||||
adder.y2 <== y;
|
||||
|
||||
adder.xout ==> xout;
|
||||
adder.yout ==> yout;
|
||||
}
|
||||
|
||||
|
||||
template BabyCheck() {
|
||||
signal input x;
|
||||
signal input y;
|
||||
|
||||
signal x2;
|
||||
signal y2;
|
||||
|
||||
var a = 168700;
|
||||
var d = 168696;
|
||||
|
||||
x2 <== x*x;
|
||||
y2 <== y*y;
|
||||
|
||||
a*x2 + y2 === 1 + d*x2*y2;
|
||||
}
|
||||
|
||||
56
circuit/compconstant.circom
Normal file
56
circuit/compconstant.circom
Normal file
@@ -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];
|
||||
|
||||
signal input A[256];
|
||||
signal input R8[256];
|
||||
signal input S[256];
|
||||
|
||||
signal Ax;
|
||||
signal Ay;
|
||||
|
||||
signal R8x;
|
||||
signal R8y;
|
||||
|
||||
var i;
|
||||
|
||||
// Ensure S<Subgroup Order
|
||||
|
||||
component compConstant = CompConstant(2736030358979909402780800718157159386076813972158567259200215660948447373040);
|
||||
|
||||
for (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;
|
||||
|
||||
|
||||
templete Verfier() {
|
||||
signal input hMsg[256];
|
||||
// Compute the right side: right = R8 + right2
|
||||
|
||||
signal input Ax;
|
||||
signal input Ay;
|
||||
component addRight = BabyAdd();
|
||||
addRight.x1 <== R8x;
|
||||
addRight.y1 <== R8y;
|
||||
addRight.x2 <== mulAny.out[0];
|
||||
addRight.y2 <== mulAny.out[1];
|
||||
|
||||
signal input Rx;
|
||||
signal input Ry;
|
||||
// Calculate left side of equation left = S*B8
|
||||
|
||||
signal input s[256];
|
||||
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
|
||||
|
||||
componet exps = Exp();
|
||||
component exph = Exp();
|
||||
|
||||
component adder = BabyAdd();
|
||||
|
||||
mulFix.out[0] === addRight.xout;
|
||||
mulFix.out[1] === addRight.yout;
|
||||
}
|
||||
|
||||
174
circuit/escalarmulany.circom
Normal file
174
circuit/escalarmulany.circom
Normal file
@@ -0,0 +1,174 @@
|
||||
|
||||
include "montgomery.circom";
|
||||
include "babyjub.circom";
|
||||
|
||||
template Multiplexor2() {
|
||||
signal input sel;
|
||||
signal input in[2][2];
|
||||
signal output out[2];
|
||||
|
||||
out[0] <== (in[1][0] - in[0][0])*sel + in[0][0];
|
||||
out[1] <== (in[1][1] - in[0][1])*sel + in[0][1];
|
||||
}
|
||||
|
||||
template BitElement() {
|
||||
signal input sel;
|
||||
signal input dblIn[2];
|
||||
signal input addIn[2];
|
||||
signal output dblOut[2];
|
||||
signal output addOut[2];
|
||||
|
||||
component doubler = MontgomeryDouble();
|
||||
component adder = MontgomeryAdd();
|
||||
component selector = Multiplexor2();
|
||||
|
||||
|
||||
sel ==> selector.sel;
|
||||
|
||||
dblIn[0] ==> doubler.in[0];
|
||||
dblIn[1] ==> doubler.in[1];
|
||||
doubler.out[0] ==> adder.in1[0];
|
||||
doubler.out[1] ==> adder.in1[1];
|
||||
addIn[0] ==> adder.in2[0];
|
||||
addIn[1] ==> adder.in2[1];
|
||||
addIn[0] ==> selector.in[0][0];
|
||||
addIn[1] ==> selector.in[0][1];
|
||||
adder.out[0] ==> selector.in[1][0];
|
||||
adder.out[1] ==> selector.in[1][1];
|
||||
|
||||
doubler.out[0] ==> dblOut[0];
|
||||
doubler.out[1] ==> dblOut[1];
|
||||
selector.out[0] ==> addOut[0];
|
||||
selector.out[1] ==> addOut[1];
|
||||
}
|
||||
|
||||
// p is montgomery point
|
||||
// n must be <= 248
|
||||
// returns out in twisted edwards
|
||||
// Double is in montgomery to be linked;
|
||||
|
||||
template Segment(n) {
|
||||
signal input e[n];
|
||||
signal input p[2];
|
||||
signal output out[2];
|
||||
signal output dbl[2];
|
||||
|
||||
component bits[n-1];
|
||||
|
||||
component e2m = Edwards2Montgomery();
|
||||
|
||||
p[0] ==> e2m.in[0];
|
||||
p[1] ==> e2m.in[1];
|
||||
|
||||
var i;
|
||||
|
||||
bits[0] = BitElement();
|
||||
e2m.out[0] ==> bits[0].dblIn[0]
|
||||
e2m.out[1] ==> bits[0].dblIn[1]
|
||||
e2m.out[0] ==> bits[0].addIn[0]
|
||||
e2m.out[1] ==> bits[0].addIn[1]
|
||||
e[1] ==> bits[0].sel;
|
||||
|
||||
for (i=1; i<n-1; i++) {
|
||||
bits[i] = BitElement();
|
||||
|
||||
bits[i-1].dblOut[0] ==> bits[i].dblIn[0]
|
||||
bits[i-1].dblOut[1] ==> bits[i].dblIn[1]
|
||||
bits[i-1].addOut[0] ==> bits[i].addIn[0]
|
||||
bits[i-1].addOut[1] ==> bits[i].addIn[1]
|
||||
e[i+1] ==> bits[i].sel;
|
||||
}
|
||||
|
||||
bits[n-2].dblOut[0] ==> dbl[0];
|
||||
bits[n-2].dblOut[1] ==> dbl[1];
|
||||
|
||||
component m2e = Montgomery2Edwards();
|
||||
|
||||
bits[n-2].addOut[0] ==> m2e.in[0];
|
||||
bits[n-2].addOut[1] ==> m2e.in[1];
|
||||
|
||||
component eadder = BabyAdd();
|
||||
|
||||
m2e.out[0] ==> eadder.x1;
|
||||
m2e.out[1] ==> eadder.y1;
|
||||
-p[0] ==> eadder.x2;
|
||||
p[1] ==> eadder.y2;
|
||||
|
||||
component lastSel = Multiplexor2();
|
||||
|
||||
e[0] ==> lastSel.sel;
|
||||
eadder.xout ==> lastSel.in[0][0];
|
||||
eadder.yout ==> lastSel.in[0][1];
|
||||
m2e.out[0] ==> lastSel.in[1][0];
|
||||
m2e.out[1] ==> lastSel.in[1][1];
|
||||
|
||||
lastSel.out[0] ==> out[0];
|
||||
lastSel.out[1] ==> out[1];
|
||||
}
|
||||
|
||||
// This function assumes that p is in the subgroup and it is different to 0
|
||||
|
||||
template EscalarMulAny(n) {
|
||||
signal input e[n]; // Input in binary format
|
||||
signal input p[2]; // Point (Twisted format)
|
||||
signal output out[2]; // Point (Twisted format)
|
||||
|
||||
var nsegments = (n-1)\148 +1;
|
||||
var nlastsegment = n - (nsegments-1)*148;
|
||||
|
||||
component segments[nsegments];
|
||||
component doublers[nsegments-1];
|
||||
component m2e[nsegments-1];
|
||||
component adders[nsegments-1];
|
||||
|
||||
var s;
|
||||
var i;
|
||||
var nseg;
|
||||
|
||||
for (s=0; s<nsegments; s++) {
|
||||
|
||||
nseg = (s < nsegments-1) ? 148 : nlastsegment;
|
||||
|
||||
segments[s] = Segment(nseg);
|
||||
|
||||
for (i=0; i<nseg; i++) {
|
||||
e[s*148+i] ==> segments[s].e[i];
|
||||
}
|
||||
|
||||
if (s==0) {
|
||||
p[0] ==> segments[s].p[0];
|
||||
p[1] ==> segments[s].p[1];
|
||||
} else {
|
||||
doublers[s-1] = MontgomeryDouble();
|
||||
m2e[s-1] = Montgomery2Edwards();
|
||||
adders[s-1] = BabyAdd();
|
||||
|
||||
segments[s-1].dbl[0] ==> doublers[s-1].in[0];
|
||||
segments[s-1].dbl[1] ==> doublers[s-1].in[1];
|
||||
|
||||
doublers[s-1].out[0] ==> m2e[s-1].in[0];
|
||||
doublers[s-1].out[1] ==> m2e[s-1].in[1];
|
||||
|
||||
m2e[s-1].out[0] ==> segments[s].p[0];
|
||||
m2e[s-1].out[1] ==> segments[s].p[1];
|
||||
|
||||
if (s==1) {
|
||||
segments[s-1].out[0] ==> adders[s-1].x1;
|
||||
segments[s-1].out[1] ==> adders[s-1].y1;
|
||||
} else {
|
||||
adders[s-2].xout ==> adders[s-1].x1;
|
||||
adders[s-2].yout ==> adders[s-1].y1;
|
||||
}
|
||||
segments[s].out[0] ==> adders[s-1].x2;
|
||||
segments[s].out[1] ==> adders[s-1].y2;
|
||||
}
|
||||
}
|
||||
|
||||
if (nsegments == 1) {
|
||||
segments[0].out[0] ==> out[0];
|
||||
segments[0].out[1] ==> out[1];
|
||||
} else {
|
||||
adders[nsegments-2].xout ==> out[0];
|
||||
adders[nsegments-2].yout ==> out[1];
|
||||
}
|
||||
}
|
||||
258
circuit/escalarmulfix.circom
Normal file
258
circuit/escalarmulfix.circom
Normal file
@@ -0,0 +1,258 @@
|
||||
include "mux3.circom";
|
||||
include "montgomery.circom";
|
||||
include "babyjub.circom";
|
||||
|
||||
/*
|
||||
Window of 3 elements, it calculates
|
||||
out = base + base*in[0] + 2*base*in[1] + 4*base*in[2]
|
||||
out4 = 4*base
|
||||
|
||||
The result should be compensated.
|
||||
*/
|
||||
template WindowMulFix() {
|
||||
signal input in[3];
|
||||
signal input base[2];
|
||||
signal output out[2];
|
||||
signal output out8[2]; // Returns 8*Base (To be linked)
|
||||
|
||||
component mux = MultiMux3(2);
|
||||
|
||||
mux.s[0] <== in[0];
|
||||
mux.s[1] <== in[1];
|
||||
mux.s[2] <== in[2];
|
||||
|
||||
component dbl2 = MontgomeryDouble();
|
||||
component adr3 = MontgomeryAdd();
|
||||
component adr4 = MontgomeryAdd();
|
||||
component adr5 = MontgomeryAdd();
|
||||
component adr6 = MontgomeryAdd();
|
||||
component adr7 = MontgomeryAdd();
|
||||
component adr8 = MontgomeryAdd();
|
||||
|
||||
// in[0] -> 1*BASE
|
||||
|
||||
mux.c[0][0] <== base[0];
|
||||
mux.c[1][0] <== base[1];
|
||||
|
||||
// in[1] -> 2*BASE
|
||||
dbl2.in[0] <== base[0];
|
||||
dbl2.in[1] <== base[1];
|
||||
mux.c[0][1] <== dbl2.out[0];
|
||||
mux.c[1][1] <== dbl2.out[1];
|
||||
|
||||
// in[2] -> 3*BASE
|
||||
adr3.in1[0] <== base[0];
|
||||
adr3.in1[1] <== base[1];
|
||||
adr3.in2[0] <== dbl2.out[0];
|
||||
adr3.in2[1] <== dbl2.out[1];
|
||||
mux.c[0][2] <== adr3.out[0];
|
||||
mux.c[1][2] <== adr3.out[1];
|
||||
|
||||
// in[3] -> 4*BASE
|
||||
adr4.in1[0] <== base[0];
|
||||
adr4.in1[1] <== base[1];
|
||||
adr4.in2[0] <== adr3.out[0];
|
||||
adr4.in2[1] <== adr3.out[1];
|
||||
mux.c[0][3] <== adr4.out[0];
|
||||
mux.c[1][3] <== adr4.out[1];
|
||||
|
||||
// in[4] -> 5*BASE
|
||||
adr5.in1[0] <== base[0];
|
||||
adr5.in1[1] <== base[1];
|
||||
adr5.in2[0] <== adr4.out[0];
|
||||
adr5.in2[1] <== adr4.out[1];
|
||||
mux.c[0][4] <== adr5.out[0];
|
||||
mux.c[1][4] <== adr5.out[1];
|
||||
|
||||
// in[5] -> 6*BASE
|
||||
adr6.in1[0] <== base[0];
|
||||
adr6.in1[1] <== base[1];
|
||||
adr6.in2[0] <== adr5.out[0];
|
||||
adr6.in2[1] <== adr5.out[1];
|
||||
mux.c[0][5] <== adr6.out[0];
|
||||
mux.c[1][5] <== adr6.out[1];
|
||||
|
||||
// in[6] -> 7*BASE
|
||||
adr7.in1[0] <== base[0];
|
||||
adr7.in1[1] <== base[1];
|
||||
adr7.in2[0] <== adr6.out[0];
|
||||
adr7.in2[1] <== adr6.out[1];
|
||||
mux.c[0][6] <== adr7.out[0];
|
||||
mux.c[1][6] <== adr7.out[1];
|
||||
|
||||
// in[7] -> 8*BASE
|
||||
adr8.in1[0] <== base[0];
|
||||
adr8.in1[1] <== base[1];
|
||||
adr8.in2[0] <== adr7.out[0];
|
||||
adr8.in2[1] <== adr7.out[1];
|
||||
mux.c[0][7] <== adr8.out[0];
|
||||
mux.c[1][7] <== adr8.out[1];
|
||||
|
||||
out8[0] <== adr8.out[0];
|
||||
out8[1] <== adr8.out[1];
|
||||
|
||||
out[0] <== mux.out[0];
|
||||
out[1] <== mux.out[1];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This component does a multiplication of a escalar times a fix base
|
||||
Signals:
|
||||
e: The scalar in bits
|
||||
base: the base point in edwards format
|
||||
out: The result
|
||||
dbl: Point in Edwards to be linked to the next segment.
|
||||
*/
|
||||
|
||||
template SegmentMulFix(nWindows) {
|
||||
signal input e[nWindows*3];
|
||||
signal input base[2];
|
||||
signal output out[2];
|
||||
signal output dbl[2];
|
||||
|
||||
var i;
|
||||
var j;
|
||||
|
||||
// Convert the base to montgomery
|
||||
|
||||
component e2m = Edwards2Montgomery();
|
||||
e2m.in[0] <== base[0];
|
||||
e2m.in[1] <== base[1];
|
||||
|
||||
component windows[nWindows];
|
||||
component adders[nWindows-1];
|
||||
component cadders[nWindows-1];
|
||||
for (i=0; i<nWindows; i++) {
|
||||
windows[i] = WindowMulFix();
|
||||
if (i==0) {
|
||||
windows[i].base[0] <== e2m.out[0];
|
||||
windows[i].base[1] <== e2m.out[1];
|
||||
} else {
|
||||
windows[i].base[0] <== windows[i-1].out8[0];
|
||||
windows[i].base[1] <== windows[i-1].out8[1];
|
||||
|
||||
adders[i-1] = MontgomeryAdd();
|
||||
cadders[i-1] = MontgomeryAdd();
|
||||
if (i==1) {
|
||||
adders[i-1].in1[0] <== windows[0].out[0];
|
||||
adders[i-1].in1[1] <== windows[0].out[1];
|
||||
cadders[i-1].in1[0] <== e2m.out[0];
|
||||
cadders[i-1].in1[1] <== e2m.out[1];
|
||||
} else {
|
||||
adders[i-1].in1[0] <== adders[i-2].out[0];
|
||||
adders[i-1].in1[1] <== adders[i-2].out[1];
|
||||
cadders[i-1].in1[0] <== cadders[i-2].out[0];
|
||||
cadders[i-1].in1[1] <== cadders[i-2].out[1];
|
||||
}
|
||||
adders[i-1].in2[0] <== windows[i].out[0];
|
||||
adders[i-1].in2[1] <== windows[i].out[1];
|
||||
cadders[i-1].in2[0] <== windows[i-1].out8[0];
|
||||
cadders[i-1].in2[1] <== windows[i-1].out8[1];
|
||||
}
|
||||
for (j=0; j<3; j++) {
|
||||
windows[i].in[j] <== e[3*i+j];
|
||||
}
|
||||
}
|
||||
|
||||
component m2e = Montgomery2Edwards();
|
||||
component cm2e = Montgomery2Edwards();
|
||||
|
||||
if (nWindows > 1) {
|
||||
m2e.in[0] <== adders[nWindows-2].out[0];
|
||||
m2e.in[1] <== adders[nWindows-2].out[1];
|
||||
cm2e.in[0] <== cadders[nWindows-2].out[0];
|
||||
cm2e.in[1] <== cadders[nWindows-2].out[1];
|
||||
} else {
|
||||
m2e.in[0] <== windows[0].out[0];
|
||||
m2e.in[1] <== windows[0].out[1];
|
||||
cm2e.in[0] <== e2m.out[0];
|
||||
cm2e.in[1] <== e2m.out[1];
|
||||
}
|
||||
|
||||
component cAdd = BabyAdd();
|
||||
cAdd.x1 <== m2e.out[0];
|
||||
cAdd.y1 <== m2e.out[1];
|
||||
cAdd.x2 <== -cm2e.out[0];
|
||||
cAdd.y2 <== cm2e.out[1];
|
||||
|
||||
|
||||
cAdd.xout ==> out[0];
|
||||
cAdd.yout ==> out[1];
|
||||
|
||||
windows[nWindows-1].out8[0] ==> dbl[0];
|
||||
windows[nWindows-1].out8[1] ==> dbl[1];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This component multiplies a escalar times a fixed point BASE (twisted edwards format)
|
||||
Signals
|
||||
e: The escalar in binary format
|
||||
out: The output point in twisted edwards
|
||||
*/
|
||||
template EscalarMulFix(n, BASE) {
|
||||
signal input e[n]; // Input in binary format
|
||||
signal output out[2]; // Point (Twisted format)
|
||||
|
||||
var nsegments = (n-1)\249 +1;
|
||||
var nlastsegment = n - (nsegments-1)*249;
|
||||
|
||||
component segments[nsegments];
|
||||
|
||||
component m2e[nsegments-1];
|
||||
component adders[nsegments-1];
|
||||
|
||||
var s;
|
||||
var i;
|
||||
var nseg;
|
||||
var nWindows
|
||||
|
||||
for (s=0; s<nsegments; s++) {
|
||||
|
||||
nseg = (s < nsegments-1) ? 249 : nlastsegment;
|
||||
nWindows = ((nseg - 1)\3)+1;
|
||||
|
||||
segments[s] = SegmentMulFix(nWindows);
|
||||
|
||||
for (i=0; i<nseg; i++) {
|
||||
segments[s].e[i] <== e[s*249+i];
|
||||
}
|
||||
|
||||
for (i = nseg; i<nWindows*3; i++) {
|
||||
segments[s].e[i] <== 0;
|
||||
}
|
||||
|
||||
if (s==0) {
|
||||
segments[s].base[0] <== BASE[0];
|
||||
segments[s].base[1] <== BASE[1];
|
||||
} else {
|
||||
m2e[s-1] = Montgomery2Edwards();
|
||||
adders[s-1] = BabyAdd();
|
||||
|
||||
segments[s-1].dbl[0] ==> m2e[s-1].in[0];
|
||||
segments[s-1].dbl[1] ==> m2e[s-1].in[1];
|
||||
|
||||
m2e[s-1].out[0] ==> segments[s].base[0];
|
||||
m2e[s-1].out[1] ==> segments[s].base[1];
|
||||
|
||||
if (s==1) {
|
||||
segments[s-1].out[0] ==> adders[s-1].x1;
|
||||
segments[s-1].out[1] ==> adders[s-1].y1;
|
||||
} else {
|
||||
adders[s-2].xout ==> adders[s-1].x1;
|
||||
adders[s-2].yout ==> adders[s-1].y1;
|
||||
}
|
||||
segments[s].out[0] ==> adders[s-1].x2;
|
||||
segments[s].out[1] ==> adders[s-1].y2;
|
||||
}
|
||||
}
|
||||
|
||||
if (nsegments == 1) {
|
||||
segments[0].out[0] ==> out[0];
|
||||
segments[0].out[1] ==> out[1];
|
||||
} else {
|
||||
adders[nsegments-2].xout ==> out[0];
|
||||
adders[nsegments-2].yout ==> out[1];
|
||||
}
|
||||
}
|
||||
123
circuit/montgomery.circom
Normal file
123
circuit/montgomery.circom
Normal file
@@ -0,0 +1,123 @@
|
||||
|
||||
/*
|
||||
Source: https://en.wikipedia.org/wiki/Montgomery_curve
|
||||
|
||||
1 + y 1 + y
|
||||
[u, v] = [ ------- , ---------- ]
|
||||
1 - y (1 - y)x
|
||||
|
||||
*/
|
||||
|
||||
template Edwards2Montgomery() {
|
||||
signal input in[2];
|
||||
signal output out[2];
|
||||
|
||||
out[0] <-- (1 + in[1]) / (1 - in[1]);
|
||||
out[1] <-- out[0] / in[0];
|
||||
|
||||
|
||||
out[0] * (1-in[1]) === (1 + in[1]);
|
||||
out[1] * in[0] === out[0];
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
u u - 1
|
||||
[x, y] = [ ---, ------- ]
|
||||
v u + 1
|
||||
|
||||
*/
|
||||
template Montgomery2Edwards() {
|
||||
signal input in[2];
|
||||
signal output out[2];
|
||||
|
||||
out[0] <-- in[0] / in[1];
|
||||
out[1] <-- (in[0] - 1) / (in[0] + 1);
|
||||
|
||||
out[0] * in[1] === in[0];
|
||||
out[1] * (in[0] + 1) === in[0] - 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
x2 - x1
|
||||
lamda = ---------
|
||||
y2 - y1
|
||||
|
||||
x3 + A + x1 + x2
|
||||
x3 = B * lamda^2 - A - x1 -x2 => lamda^2 = ------------------
|
||||
B
|
||||
|
||||
y3 = (2*x1 + x2 + A)*lamda - B*lamda^3 - y1 =>
|
||||
|
||||
|
||||
=> y3 = lamda * ( 2*x1 + x2 + A - x3 - A - x1 - x2) - y1 =>
|
||||
|
||||
=> y3 = lamda * ( x1 - x3 ) - y1
|
||||
|
||||
----------
|
||||
|
||||
y2 - y1
|
||||
lamda = ---------
|
||||
x2 - x1
|
||||
|
||||
x3 = B * lamda^2 - A - x1 -x2
|
||||
|
||||
y3 = lamda * ( x1 - x3 ) - y1
|
||||
|
||||
*/
|
||||
|
||||
template MontgomeryAdd() {
|
||||
signal input in1[2];
|
||||
signal input in2[2];
|
||||
signal output out[2];
|
||||
|
||||
var a = 168700;
|
||||
var d = 168696;
|
||||
|
||||
var A = (2 * (a + d)) / (a - d);
|
||||
var B = 4 / (a - d);
|
||||
|
||||
signal lamda;
|
||||
|
||||
lamda <-- (in2[1] - in1[1]) / (in2[0] - in1[0]);
|
||||
lamda * (in2[0] - in1[0]) === (in2[1] - in1[1]);
|
||||
|
||||
out[0] <== B*lamda*lamda - A - in1[0] -in2[0];
|
||||
out[1] <== lamda * (in1[0] - out[0]) - in1[1];
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
x1_2 = x1*x1
|
||||
|
||||
3*x1_2 + 2*A*x1 + 1
|
||||
lamda = ---------------------
|
||||
2*B*y1
|
||||
|
||||
x3 = B * lamda^2 - A - x1 -x1
|
||||
|
||||
y3 = lamda * ( x1 - x3 ) - y1
|
||||
|
||||
*/
|
||||
template MontgomeryDouble() {
|
||||
signal input in[2];
|
||||
signal output out[2];
|
||||
|
||||
var a = 168700;
|
||||
var d = 168696;
|
||||
|
||||
var A = (2 * (a + d)) / (a - d);
|
||||
var B = 4 / (a - d);
|
||||
|
||||
signal lamda;
|
||||
signal x1_2;
|
||||
|
||||
x1_2 <== in[0] * in[0];
|
||||
|
||||
lamda <-- (3*x1_2 + 2*A*in[0] + 1 ) / (2*B*in[1]);
|
||||
lamda * (2*B*in[1]) === (3*x1_2 + 2*A*in[0] + 1 );
|
||||
|
||||
out[0] <== B*lamda*lamda - A - 2*in[0];
|
||||
out[1] <== lamda * (in[0] - out[0]) - in[1];
|
||||
}
|
||||
55
circuit/mux3.circom
Normal file
55
circuit/mux3.circom
Normal file
@@ -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;
|
||||
}
|
||||
@@ -5,8 +5,8 @@ template Pedersen(n) {
|
||||
signal input in[n];
|
||||
signal output out[2];
|
||||
|
||||
var nexps = ((n-1) \ 253) + 1;
|
||||
var nlastbits = n - (nexps-1)*253;
|
||||
var nexps = ((n-1) \ 250) + 1;
|
||||
var nlastbits = n - (nexps-1)*250;
|
||||
|
||||
component escalarMuls[nexps];
|
||||
|
||||
@@ -27,11 +27,11 @@ template Pedersen(n) {
|
||||
var j;
|
||||
var nexpbits;
|
||||
for (i=0; i<nexps; i++) {
|
||||
nexpbits = (i == nexps-1) ? nlastbits : 253;
|
||||
nexpbits = (i == nexps-1) ? nlastbits : 250;
|
||||
escalarMuls[i] = EscalarMul(nexpbits, PBASE[i]);
|
||||
|
||||
for (j=0; j<nexpbits; j++) {
|
||||
escalarMuls[i].in[j] <== in[253*i + j];
|
||||
escalarMuls[i].in[j] <== in[250*i + j];
|
||||
}
|
||||
|
||||
if (i==0) {
|
||||
|
||||
236
circuit/pedersen2.circom
Normal file
236
circuit/pedersen2.circom
Normal file
@@ -0,0 +1,236 @@
|
||||
include "montgomery.circom";
|
||||
include "mux3.circom";
|
||||
include "babyjub.circom";
|
||||
|
||||
template Window4() {
|
||||
signal input in[4];
|
||||
signal input base[2];
|
||||
signal output out[2];
|
||||
signal output out8[2]; // Returns 8*Base (To be linked)
|
||||
|
||||
component mux = MultiMux3(2);
|
||||
|
||||
mux.s[0] <== in[0];
|
||||
mux.s[1] <== in[1];
|
||||
mux.s[2] <== in[2];
|
||||
|
||||
component dbl2 = MontgomeryDouble();
|
||||
component adr3 = MontgomeryAdd();
|
||||
component adr4 = MontgomeryAdd();
|
||||
component adr5 = MontgomeryAdd();
|
||||
component adr6 = MontgomeryAdd();
|
||||
component adr7 = MontgomeryAdd();
|
||||
component adr8 = MontgomeryAdd();
|
||||
|
||||
// in[0] -> 1*BASE
|
||||
|
||||
mux.c[0][0] <== base[0];
|
||||
mux.c[1][0] <== base[1];
|
||||
|
||||
// in[1] -> 2*BASE
|
||||
dbl2.in[0] <== base[0];
|
||||
dbl2.in[1] <== base[1];
|
||||
mux.c[0][1] <== dbl2.out[0];
|
||||
mux.c[1][1] <== dbl2.out[1];
|
||||
|
||||
// in[2] -> 3*BASE
|
||||
adr3.in1[0] <== base[0];
|
||||
adr3.in1[1] <== base[1];
|
||||
adr3.in2[0] <== dbl2.out[0];
|
||||
adr3.in2[1] <== dbl2.out[1];
|
||||
mux.c[0][2] <== adr3.out[0];
|
||||
mux.c[1][2] <== adr3.out[1];
|
||||
|
||||
// in[3] -> 4*BASE
|
||||
adr4.in1[0] <== base[0];
|
||||
adr4.in1[1] <== base[1];
|
||||
adr4.in2[0] <== adr3.out[0];
|
||||
adr4.in2[1] <== adr3.out[1];
|
||||
mux.c[0][3] <== adr4.out[0];
|
||||
mux.c[1][3] <== adr4.out[1];
|
||||
|
||||
// in[4] -> 5*BASE
|
||||
adr5.in1[0] <== base[0];
|
||||
adr5.in1[1] <== base[1];
|
||||
adr5.in2[0] <== adr4.out[0];
|
||||
adr5.in2[1] <== adr4.out[1];
|
||||
mux.c[0][4] <== adr5.out[0];
|
||||
mux.c[1][4] <== adr5.out[1];
|
||||
|
||||
// in[5] -> 6*BASE
|
||||
adr6.in1[0] <== base[0];
|
||||
adr6.in1[1] <== base[1];
|
||||
adr6.in2[0] <== adr5.out[0];
|
||||
adr6.in2[1] <== adr5.out[1];
|
||||
mux.c[0][5] <== adr6.out[0];
|
||||
mux.c[1][5] <== adr6.out[1];
|
||||
|
||||
// in[6] -> 7*BASE
|
||||
adr7.in1[0] <== base[0];
|
||||
adr7.in1[1] <== base[1];
|
||||
adr7.in2[0] <== adr6.out[0];
|
||||
adr7.in2[1] <== adr6.out[1];
|
||||
mux.c[0][6] <== adr7.out[0];
|
||||
mux.c[1][6] <== adr7.out[1];
|
||||
|
||||
// in[7] -> 8*BASE
|
||||
adr8.in1[0] <== base[0];
|
||||
adr8.in1[1] <== base[1];
|
||||
adr8.in2[0] <== adr7.out[0];
|
||||
adr8.in2[1] <== adr7.out[1];
|
||||
mux.c[0][7] <== adr8.out[0];
|
||||
mux.c[1][7] <== adr8.out[1];
|
||||
|
||||
out8[0] <== adr8.out[0];
|
||||
out8[1] <== adr8.out[1];
|
||||
|
||||
out[0] <== mux.out[0];
|
||||
out[1] <== - mux.out[1]*2*in[3] + mux.out[1]; // Negate y if in[3] is one
|
||||
}
|
||||
|
||||
|
||||
template Segment(nWindows) {
|
||||
signal input in[nWindows*4];
|
||||
signal input base[2];
|
||||
signal output out[2];
|
||||
|
||||
var i;
|
||||
var j;
|
||||
|
||||
// Convert the base to montgomery
|
||||
|
||||
component e2m = Edwards2Montgomery();
|
||||
e2m.in[0] <== base[0];
|
||||
e2m.in[1] <== base[1];
|
||||
|
||||
component windows[nWindows];
|
||||
component doublers1[nWindows-1];
|
||||
component doublers2[nWindows-1];
|
||||
component adders[nWindows-1];
|
||||
for (i=0; i<nWindows; i++) {
|
||||
windows[i] = Window4();
|
||||
if (i==0) {
|
||||
windows[i].base[0] <== e2m.out[0];
|
||||
windows[i].base[1] <== e2m.out[1];
|
||||
} else {
|
||||
doublers1[i-1] = MontgomeryDouble();
|
||||
doublers2[i-1] = MontgomeryDouble();
|
||||
doublers1[i-1].in[0] <== windows[i-1].out8[0];
|
||||
doublers1[i-1].in[1] <== windows[i-1].out8[1];
|
||||
doublers2[i-1].in[0] <== doublers1[i-1].out[0];
|
||||
doublers2[i-1].in[1] <== doublers1[i-1].out[1];
|
||||
|
||||
windows[i].base[0] <== doublers2[i-1].out[0];
|
||||
windows[i].base[1] <== doublers2[i-1].out[1];
|
||||
|
||||
adders[i-1] = MontgomeryAdd();
|
||||
if (i==1) {
|
||||
adders[i-1].in1[0] <== windows[0].out[0];
|
||||
adders[i-1].in1[1] <== windows[0].out[1];
|
||||
} else {
|
||||
adders[i-1].in1[0] <== adders[i-2].out[0];
|
||||
adders[i-1].in1[1] <== adders[i-2].out[1];
|
||||
}
|
||||
adders[i-1].in2[0] <== windows[i].out[0];
|
||||
adders[i-1].in2[1] <== windows[i].out[1];
|
||||
}
|
||||
for (j=0; j<4; j++) {
|
||||
windows[i].in[j] <== in[4*i+j];
|
||||
}
|
||||
}
|
||||
|
||||
component m2e = Montgomery2Edwards();
|
||||
|
||||
if (nWindows > 1) {
|
||||
m2e.in[0] <== adders[nWindows-2].out[0];
|
||||
m2e.in[1] <== adders[nWindows-2].out[1];
|
||||
} else {
|
||||
m2e.in[0] <== windows[0].out[0];
|
||||
m2e.in[1] <== windows[0].out[1];
|
||||
}
|
||||
|
||||
out[0] <== m2e.out[0];
|
||||
out[1] <== m2e.out[1];
|
||||
}
|
||||
|
||||
template Pedersen(n) {
|
||||
signal input in[n];
|
||||
signal output out[2];
|
||||
|
||||
var BASE = [
|
||||
[7889815880984390413826091016397158135734961432619494935997950708325418623781,8846020814737052626835496416415322522216827521798085437978304928900248828704],
|
||||
[12932435660254426850246080929365951045207624124386035886549006330955720993567,15876660444082442781217588393435527739441124986236154572507597829115005542086],
|
||||
[2482397177297734131621151094340467680859038448217226675361423673093734165962,10039279516804305991696249700635360957313934801940294703211894781106216299926],
|
||||
[17157815998940296936592098789990444736073034804807810484873853349962905015352,6488208869655503622669430389521947006738035600928015942696596112432120303604],
|
||||
[264004460746169389447419243214191481604172623204375600962322511417379874376,2415858116338771134001541482988382151008857516531390792628421155957250972277],
|
||||
[4135925743285698117252356077971179769271452015650275231796007492648697405139,10188226868678337759614729372197905253307539893323271103976079007344248400845],
|
||||
[1774758779250924961062140611815304699163957993414252473010092444201412186500,4347026286058522695608532575722049241297833321096891696953943795644684841805],
|
||||
[7879866447646097585900946926276218605564915618236971624614091698429769712458,2093592432852088858177276030443845730480437238346603396739626046140688969347],
|
||||
[8298560996095230984182228319122592575131718101813938808256495049817179791777,1767915891871602626938298102360238720016341966012238026281701463959008338852],
|
||||
[10415885340847357003805466620366840573458521568359796855704531856219635265921,3432650026491357206165099540731361444311747596326968441647905394914712226413]
|
||||
]
|
||||
|
||||
var nSegments = ((n-1)\200)+1;
|
||||
|
||||
component segments[nSegments];
|
||||
|
||||
var i;
|
||||
var j;
|
||||
var nBits;
|
||||
var nWindows;
|
||||
for (i=0; i<nSegments; i++) {
|
||||
nBits = (i == (nSegments-1)) ? n - (nSegments-1)*200 : 200;
|
||||
nWindows = ((nBits - 1)\4)+1;
|
||||
segments[i] = Segment(nWindows);
|
||||
segments[i].base[0] <== BASE[i][0];
|
||||
segments[i].base[1] <== BASE[i][1];
|
||||
for (j = 0; j<nBits; j++) {
|
||||
segments[i].in[j] <== in[i*200+j];
|
||||
}
|
||||
// Fill padding bits
|
||||
for (j = nBits; j < nWindows*4; j++) {
|
||||
segments[i].in[j] <== 0;
|
||||
}
|
||||
}
|
||||
|
||||
component adders[nSegments-1];
|
||||
|
||||
for (i=0; i<nSegments-1; i++) {
|
||||
adders[i] = BabyAdd();
|
||||
if (i==0) {
|
||||
adders[i].x1 <== segments[0].out[0];
|
||||
adders[i].y1 <== segments[0].out[1];
|
||||
adders[i].x2 <== segments[1].out[0];
|
||||
adders[i].y2 <== segments[1].out[1];
|
||||
} else {
|
||||
adders[i].x1 <== adders[i-1].xout;
|
||||
adders[i].y1 <== adders[i-1].xout;
|
||||
adders[i].x2 <== segments[i+1].out[0];
|
||||
adders[i].y2 <== segments[i+1].out[1];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
coponent packPoint = PackPoint();
|
||||
|
||||
if (nSegments>1) {
|
||||
packPoint.in[0] <== adders[nSegments-2].xout;
|
||||
packPoint.in[1] <== adders[nSegments-2].yout;
|
||||
} else {
|
||||
packPoint.in[0] <== segments[0].out[0];
|
||||
packPoint.in[1] <== segments[0].out[1];
|
||||
}
|
||||
|
||||
out[0] <== packPoint.out[0];
|
||||
out[1] <== packPoint.out[1];
|
||||
*/
|
||||
|
||||
if (nSegments>1) {
|
||||
out[0] <== adders[nSegments-2].xout;
|
||||
out[1] <== adders[nSegments-2].yout;
|
||||
} else {
|
||||
out[0] <== segments[0].out[0];
|
||||
out[1] <== segments[0].out[1];
|
||||
}
|
||||
}
|
||||
|
||||
144
circuit/pointbits.circom
Normal file
144
circuit/pointbits.circom
Normal file
@@ -0,0 +1,144 @@
|
||||
include "../node_modules/circom/circuits/bitify.circom";
|
||||
include "aliascheck.circom";
|
||||
include "compconstant.circom";
|
||||
include "babyjub.circom";
|
||||
|
||||
|
||||
function sqrt(n) {
|
||||
|
||||
if (n == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Test that have solution
|
||||
var res = n ** ((-1) >> 1);
|
||||
// if (res!=1) assert(false, "SQRT does not exists");
|
||||
if (res!=1) return 0;
|
||||
|
||||
var m = 28;
|
||||
var c = 19103219067921713944291392827692070036145651957329286315305642004821462161904;
|
||||
var t = n ** 81540058820840996586704275553141814055101440848469862132140264610111;
|
||||
var r = n ** ((81540058820840996586704275553141814055101440848469862132140264610111+1)>>1);
|
||||
var sq;
|
||||
var i;
|
||||
var b;
|
||||
var j;
|
||||
|
||||
while ((r != 0)&&(t != 1)) {
|
||||
sq = t*t;
|
||||
i = 1;
|
||||
while (sq!=1) {
|
||||
i++;
|
||||
sq = sq*sq;
|
||||
}
|
||||
|
||||
// b = c ^ m-i-1
|
||||
b = c;
|
||||
for (j=0; j< m-i-1; j ++) b = b*b;
|
||||
|
||||
m = i;
|
||||
c = b*b;
|
||||
t = t*c;
|
||||
r = r*b;
|
||||
}
|
||||
|
||||
if (r > ((-1) >> 1)) {
|
||||
r = -r;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
template Bits2Point() {
|
||||
signal input in[256];
|
||||
signal output out[2];
|
||||
}
|
||||
|
||||
template Bits2Point_Strict() {
|
||||
signal input in[256];
|
||||
signal output out[2];
|
||||
|
||||
var i;
|
||||
|
||||
// Check aliasing
|
||||
component aliasCheckY = AliasCheck();
|
||||
for (i=0; i<254; i++) {
|
||||
aliasCheckY.in[i] <== in[i];
|
||||
}
|
||||
in[254] === 0;
|
||||
|
||||
component b2nY = Bits2Num(254);
|
||||
for (i=0; i<254; i++) {
|
||||
b2nY.in[i] <== in[i];
|
||||
}
|
||||
|
||||
out[1] <== b2nY.out;
|
||||
|
||||
var a = 168700;
|
||||
var d = 168696;
|
||||
|
||||
var y2 = out[1] * out[1];
|
||||
|
||||
var x = sqrt( (1-y2)/(a - d*y2) );
|
||||
|
||||
if (in[255] == 1) x = -x;
|
||||
|
||||
out[0] <-- x;
|
||||
|
||||
component babyCheck = BabyCheck();
|
||||
babyCheck.x <== out[0];
|
||||
babyCheck.y <== out[1];
|
||||
|
||||
component n2bX = Num2Bits(254);
|
||||
n2bX.in <== out[0];
|
||||
component aliasCheckX = AliasCheck();
|
||||
for (i=0; i<254; i++) {
|
||||
aliasCheckX.in[i] <== n2bX.out[i];
|
||||
}
|
||||
|
||||
component signCalc = CompConstant(10944121435919637611123202872628637544274182200208017171849102093287904247808);
|
||||
for (i=0; i<254; i++) {
|
||||
signCalc.in[i] <== n2bX.out[i];
|
||||
}
|
||||
|
||||
signCalc.out === in[255];
|
||||
}
|
||||
|
||||
|
||||
template Point2Bits() {
|
||||
signal input in[2];
|
||||
signal output out[256];
|
||||
|
||||
|
||||
}
|
||||
|
||||
template Point2Bits_Strict() {
|
||||
signal input in[2];
|
||||
signal output out[256];
|
||||
|
||||
var i;
|
||||
|
||||
component n2bX = Num2Bits(254);
|
||||
n2bX.in <== in[0];
|
||||
component n2bY = Num2Bits(254);
|
||||
n2bY.in <== in[1];
|
||||
|
||||
component aliasCheckX = AliasCheck();
|
||||
component aliasCheckY = AliasCheck();
|
||||
for (i=0; i<254; i++) {
|
||||
aliasCheckX.in[i] <== n2bX.out[i];
|
||||
aliasCheckY.in[i] <== n2bY.out[i];
|
||||
}
|
||||
|
||||
component signCalc = CompConstant(10944121435919637611123202872628637544274182200208017171849102093287904247808);
|
||||
for (i=0; i<254; i++) {
|
||||
signCalc.in[i] <== n2bX.out[i];
|
||||
}
|
||||
|
||||
for (i=0; i<254; i++) {
|
||||
out[i] <== n2bY.out[i];
|
||||
}
|
||||
out[254] <== 0;
|
||||
out[255] <== signCalc.out;
|
||||
}
|
||||
16
circuit/sign.circom
Normal file
16
circuit/sign.circom
Normal file
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user