1717 */
1818package org .tron .common .crypto .zksnark ;
1919
20- import static org .tron .common .crypto .zksnark .Params .P ;
21-
2220import java .math .BigInteger ;
2321
2422/**
2523 * Arithmetic in F_p, p = 21888242871839275222246405745257275088696311157297823662689037894645226208583
26- *
24+ * This class stores elements of F_p in the Montgomery form: a*r mod p.
25+ *
2726 * @author Mikhail Kalinin
2827 * @since 01.09.2017
2928 */
3029public 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" );
3135
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 (
3579 "21888242871839275222246405745257275088696311157297823662689037894645226208582" ));
3680
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 ));
3882
3983 BigInteger v ;
4084
@@ -43,41 +87,52 @@ public class Fp implements Field<Fp> {
4387 }
4488
4589 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 ));
4796 }
4897
4998 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 ));
51104 }
52105
53106 @ Override
54107 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 ));
56110 }
57111
58112 @ Override
59113 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 )));
61115 }
62116
63117 @ Override
64118 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 );
66121 }
67122
68123 @ Override
69124 public Fp squared () {
70- return new Fp (v .multiply (v ). mod ( P ));
125+ return new Fp (redc ( v .multiply (v )));
71126 }
72127
73128 @ Override
74129 public Fp dbl () {
75- return new Fp ( v . add (v ). mod ( P ) );
130+ return add (this );
76131 }
77132
78133 @ Override
79134 public Fp inverse () {
80- return new Fp (v .modInverse (P ));
135+ return new Fp (redc ( v .modInverse (P ). multiply ( REDUCER_CUBED ) ));
81136 }
82137
83138 @ Override
@@ -90,20 +145,12 @@ public boolean isZero() {
90145 return v .compareTo (BigInteger .ZERO ) == 0 ;
91146 }
92147
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-
101148 Fp2 mul (Fp2 o ) {
102149 return new Fp2 (o .a .mul (this ), o .b .mul (this ));
103150 }
104151
105152 public byte [] bytes () {
106- return v .toByteArray ();
153+ return fromMontgomery ( v ) .toByteArray ();
107154 }
108155
109156 @ Override
@@ -129,4 +176,36 @@ public int hashCode() {
129176 public String toString () {
130177 return v .toString ();
131178 }
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+ }
132211}
0 commit comments