circomlib/circuits/pointbits.circom
circuits/pointbits.circomRaw
1/*
2 Copyright 2018 0KIMS association.
3
4 This file is part of circom (Zero Knowledge Circuit Compiler).
5
6 circom is a free software: you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 circom is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with circom. If not, see <https://www.gnu.org/licenses/>.
18*/
19
20include "bitify.circom";
21include "aliascheck.circom";
22include "compconstant.circom";
23include "babyjub.circom";
24
25
26function sqrt(n) {
27
28 if (n == 0) {
29 return 0;
30 }
31
32 // Test that have solution
33 var res = n ** ((-1) >> 1);
34// if (res!=1) assert(false, "SQRT does not exists");
35 if (res!=1) return 0;
36
37 var m = 28;
38 var c = 19103219067921713944291392827692070036145651957329286315305642004821462161904;
39 var t = n ** 81540058820840996586704275553141814055101440848469862132140264610111;
40 var r = n ** ((81540058820840996586704275553141814055101440848469862132140264610111+1)>>1);
41 var sq;
42 var i;
43 var b;
44 var j;
45
46 while ((r != 0)&&(t != 1)) {
47 sq = t*t;
48 i = 1;
49 while (sq!=1) {
50 i++;
51 sq = sq*sq;
52 }
53
54 // b = c ^ m-i-1
55 b = c;
56 for (j=0; j< m-i-1; j ++) b = b*b;
57
58 m = i;
59 c = b*b;
60 t = t*c;
61 r = r*b;
62 }
63
64 if (r > ((-1) >> 1)) {
65 r = -r;
66 }
67
68 return r;
69}
70
71
72template Bits2Point() {
73 signal input in[256];
74 signal output out[2];
75}
76
77template Bits2Point_Strict() {
78 signal input in[256];
79 signal output out[2];
80
81 var i;
82
83 // Check aliasing
84 component aliasCheckY = AliasCheck();
85 for (i=0; i<254; i++) {
86 aliasCheckY.in[i] <== in[i];
87 }
88 in[254] === 0;
89
90 component b2nY = Bits2Num(254);
91 for (i=0; i<254; i++) {
92 b2nY.in[i] <== in[i];
93 }
94
95 out[1] <== b2nY.out;
96
97 var a = 168700;
98 var d = 168696;
99
100 var y2 = out[1] * out[1];
101
102 var x = sqrt( (1-y2)/(a - d*y2) );
103
104 if (in[255] == 1) x = -x;
105
106 out[0] <-- x;
107
108 component babyCheck = BabyCheck();
109 babyCheck.x <== out[0];
110 babyCheck.y <== out[1];
111
112 component n2bX = Num2Bits(254);
113 n2bX.in <== out[0];
114 component aliasCheckX = AliasCheck();
115 for (i=0; i<254; i++) {
116 aliasCheckX.in[i] <== n2bX.out[i];
117 }
118
119 component signCalc = CompConstant(10944121435919637611123202872628637544274182200208017171849102093287904247808);
120 for (i=0; i<254; i++) {
121 signCalc.in[i] <== n2bX.out[i];
122 }
123
124 signCalc.out === in[255];
125}
126
127
128template Point2Bits() {
129 signal input in[2];
130 signal output out[256];
131
132
133}
134
135template Point2Bits_Strict() {
136 signal input in[2];
137 signal output out[256];
138
139 var i;
140
141 component n2bX = Num2Bits(254);
142 n2bX.in <== in[0];
143 component n2bY = Num2Bits(254);
144 n2bY.in <== in[1];
145
146 component aliasCheckX = AliasCheck();
147 component aliasCheckY = AliasCheck();
148 for (i=0; i<254; i++) {
149 aliasCheckX.in[i] <== n2bX.out[i];
150 aliasCheckY.in[i] <== n2bY.out[i];
151 }
152
153 component signCalc = CompConstant(10944121435919637611123202872628637544274182200208017171849102093287904247808);
154 for (i=0; i<254; i++) {
155 signCalc.in[i] <== n2bX.out[i];
156 }
157
158 for (i=0; i<254; i++) {
159 out[i] <== n2bY.out[i];
160 }
161 out[254] <== 0;
162 out[255] <== signCalc.out;
163}