17
17
*/
18
18
package org .tron .common .crypto .zksnark ;
19
19
20
- import static org .tron .common .crypto .zksnark .Params .P ;
21
-
22
20
import java .math .BigInteger ;
23
21
24
22
/**
25
23
* Arithmetic in F_p, p = 21888242871839275222246405745257275088696311157297823662689037894645226208583
26
- *
24
+ * This class stores elements of F_p in the Montgomery form: a*r mod p.
25
+ *
27
26
* @author Mikhail Kalinin
28
27
* @since 01.09.2017
29
28
*/
30
29
public class Fp implements Field <Fp > {
30
+ /**
31
+ * "p" field parameter of F_p, F_p2, F_p6 and F_p12
32
+ */
33
+ static final BigInteger P = new BigInteger (
34
+ "21888242871839275222246405745257275088696311157297823662689037894645226208583" );
31
35
32
- static final Fp ZERO = new Fp (BigInteger .ZERO );
33
- static final Fp _1 = new Fp (BigInteger .ONE );
34
- static final Fp NON_RESIDUE = new Fp (new BigInteger (
36
+ /**
37
+ * This value is equal to 2^256. It should be greater than {@link #P} and coprime to it.
38
+ * Field elements are represented in Montgomery form as a*{@link #REDUCER} mod {@link #P}.
39
+ * This specific value of {@link #REDUCER} is selected to facilitate efficient division
40
+ * by {@link #REDUCER} through simple shifting.
41
+ */
42
+ static final BigInteger REDUCER = new BigInteger (
43
+ "115792089237316195423570985008687907853269984665640564039457584007913129639936" );
44
+
45
+ /**
46
+ * The number of bits in the {@link #REDUCER} value.
47
+ */
48
+ static final int REDUCER_BITS = 256 ;
49
+
50
+ /**
51
+ * A precomputed value of {@link #REDUCER}^2 mod {@link #P}.
52
+ */
53
+ static final BigInteger REDUCER_SQUARED = new BigInteger (
54
+ "3096616502983703923843567936837374451735540968419076528771170197431451843209" );
55
+
56
+ /**
57
+ * A precomputed value of {@link #REDUCER}^3 mod {@link #P}.
58
+ */
59
+ static final BigInteger REDUCER_CUBED = new BigInteger (
60
+ "14921786541159648185948152738563080959093619838510245177710943249661917737183" );
61
+
62
+ /**
63
+ * A precomputed value of -{@link #P}^{-1} mod {@link #REDUCER}.
64
+ */
65
+ static final BigInteger FACTOR = new BigInteger (
66
+ "111032442853175714102588374283752698368366046808579839647964533820976443843465" );
67
+
68
+ /**
69
+ * The MASK value is set to 2^256 - 1 and is utilized to replace the operation % 2^256
70
+ * with a bitwise AND using this value. This choice ensures that only the lower 256 bits
71
+ * of a result are retained, effectively simulating the modulus operation.
72
+ */
73
+ static final BigInteger MASK = new BigInteger (
74
+ "115792089237316195423570985008687907853269984665640564039457584007913129639935" );
75
+
76
+ static final Fp ZERO = Fp .create (BigInteger .ZERO );
77
+ static final Fp _1 = Fp .create (BigInteger .ONE );
78
+ static final Fp NON_RESIDUE = Fp .create (new BigInteger (
35
79
"21888242871839275222246405745257275088696311157297823662689037894645226208582" ));
36
80
37
- static final Fp _2_INV = new Fp (BigInteger .valueOf (2 ).modInverse (P ));
81
+ static final Fp _2_INV = Fp . create (BigInteger .valueOf (2 ).modInverse (P ));
38
82
39
83
BigInteger v ;
40
84
@@ -43,41 +87,52 @@ public class Fp implements Field<Fp> {
43
87
}
44
88
45
89
static Fp create (byte [] v ) {
46
- return new Fp (new BigInteger (1 , v ));
90
+ BigInteger value = new BigInteger (1 , v );
91
+ if (value .compareTo (P ) >= 0 ) {
92
+ // Only the values less than P are valid
93
+ return null ;
94
+ }
95
+ return new Fp (toMontgomery (value ));
47
96
}
48
97
49
98
static Fp create (BigInteger v ) {
50
- return new Fp (v );
99
+ if (v .compareTo (P ) >= 0 ) {
100
+ // Only the values less than P are valid
101
+ return null ;
102
+ }
103
+ return new Fp (toMontgomery (v ));
51
104
}
52
105
53
106
@ Override
54
107
public Fp add (Fp o ) {
55
- return new Fp (this .v .add (o .v ).mod (P ));
108
+ BigInteger r = v .add (o .v );
109
+ return new Fp (r .compareTo (P ) < 0 ? r : r .subtract (P ));
56
110
}
57
111
58
112
@ Override
59
113
public Fp mul (Fp o ) {
60
- return new Fp (this . v .multiply (o .v ). mod ( P ));
114
+ return new Fp (redc ( v .multiply (o .v )));
61
115
}
62
116
63
117
@ Override
64
118
public Fp sub (Fp o ) {
65
- return new Fp (this .v .subtract (o .v ).mod (P ));
119
+ BigInteger r = v .subtract (o .v );
120
+ return new Fp (r .compareTo (BigInteger .ZERO ) < 0 ? r .add (P ) : r );
66
121
}
67
122
68
123
@ Override
69
124
public Fp squared () {
70
- return new Fp (v .multiply (v ). mod ( P ));
125
+ return new Fp (redc ( v .multiply (v )));
71
126
}
72
127
73
128
@ Override
74
129
public Fp dbl () {
75
- return new Fp ( v . add (v ). mod ( P ) );
130
+ return add (this );
76
131
}
77
132
78
133
@ Override
79
134
public Fp inverse () {
80
- return new Fp (v .modInverse (P ));
135
+ return new Fp (redc ( v .modInverse (P ). multiply ( REDUCER_CUBED ) ));
81
136
}
82
137
83
138
@ Override
@@ -90,20 +145,12 @@ public boolean isZero() {
90
145
return v .compareTo (BigInteger .ZERO ) == 0 ;
91
146
}
92
147
93
- /**
94
- * Checks if provided value is a valid Fp member
95
- */
96
- @ Override
97
- public boolean isValid () {
98
- return v .compareTo (P ) < 0 ;
99
- }
100
-
101
148
Fp2 mul (Fp2 o ) {
102
149
return new Fp2 (o .a .mul (this ), o .b .mul (this ));
103
150
}
104
151
105
152
public byte [] bytes () {
106
- return v .toByteArray ();
153
+ return fromMontgomery ( v ) .toByteArray ();
107
154
}
108
155
109
156
@ Override
@@ -129,4 +176,36 @@ public int hashCode() {
129
176
public String toString () {
130
177
return v .toString ();
131
178
}
179
+
180
+ /**
181
+ * Converts a value in normal representation to Montgomery form.
182
+ *
183
+ * @param n value in normal form
184
+ * @return value in Montgomery form
185
+ */
186
+ private static BigInteger toMontgomery (BigInteger n ) {
187
+ return redc (n .multiply (REDUCER_SQUARED ));
188
+ }
189
+
190
+ /**
191
+ * Converts a value in Montgomery form to a normal representation.
192
+ *
193
+ * @param n value in Montgomery form
194
+ * @return value in normal form
195
+ */
196
+ private static BigInteger fromMontgomery (BigInteger n ) {
197
+ return redc (n );
198
+ }
199
+
200
+ /**
201
+ * Montgomery reduction; given a value x, computes x*{@link #REDUCER}^{-1} mod {@link #P}
202
+ *
203
+ * @param x value to reduce
204
+ * @return x*{@link #REDUCER}^{-1} mod {@link #P}
205
+ */
206
+ private static BigInteger redc (BigInteger x ) {
207
+ BigInteger temp = x .multiply (FACTOR ).and (MASK );
208
+ BigInteger reduced = temp .multiply (P ).add (x ).shiftRight (REDUCER_BITS );
209
+ return reduced .compareTo (P ) < 0 ? reduced : reduced .subtract (P );
210
+ }
132
211
}
0 commit comments