PRCYCoin  2.0.0.7rc1
P2P Digital Currency
util.h
Go to the documentation of this file.
1 /**********************************************************************
2  * Copyright (c) 2018 Andrew Poelstra *
3  * Distributed under the MIT software license, see the accompanying *
4  * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
5  **********************************************************************/
6 
7 #ifndef SECP256K1_MODULE_BULLETPROOF_UTIL
8 #define SECP256K1_MODULE_BULLETPROOF_UTIL
9 
10 /* floor(log2(n)) which returns 0 for 0, since this is used to estimate proof sizes */
11 SECP256K1_INLINE static size_t secp256k1_floor_lg(size_t n) {
12  switch (n) {
13  case 0: return 0;
14  case 1: return 0;
15  case 2: return 1;
16  case 3: return 1;
17  case 4: return 2;
18  case 5: return 2;
19  case 6: return 2;
20  case 7: return 2;
21  case 8: return 3;
22  default: {
23  size_t i = 0;
24  while (n > 1) {
25  n /= 2;
26  i++;
27  }
28  return i;
29  }
30  }
31 }
32 
33 SECP256K1_INLINE static size_t secp256k1_popcountl(unsigned long x) {
34 #ifdef HAVE_BUILTIN_POPCOUNTL
35  return __builtin_popcountl(x);
36 #else
37  size_t ret = 0;
38  size_t i;
39  for (i = 0; i < 64; i++) {
40  ret += x & 1;
41  x >>= 1;
42  }
43  return ret;
44 #endif
45 }
46 
47 SECP256K1_INLINE static size_t secp256k1_ctzl(unsigned long x) {
48 #ifdef HAVE_BUILTIN_CTZL
49  return __builtin_ctzl(x);
50 #else
51  size_t i;
52  for (i = 0; i < 64; i++) {
53  if (x & (1ull << i)) {
54  return i;
55  }
56  }
57  /* If no bits are set, the result is __builtin_ctzl is undefined,
58  * so we can return whatever we want here. */
59  return 0;
60 #endif
61 }
62 
63 static void secp256k1_scalar_dot_product(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, size_t n) {
64  secp256k1_scalar_clear(r);
65  while(n--) {
66  secp256k1_scalar term;
67  secp256k1_scalar_mul(&term, &a[n], &b[n]);
68  secp256k1_scalar_add(r, r, &term);
69  }
70 }
71 
72 static void secp256k1_scalar_inverse_all_var(secp256k1_scalar *r, const secp256k1_scalar *a, size_t len) {
74  size_t i;
75  if (len < 1) {
76  return;
77  }
78 
79  VERIFY_CHECK((r + len <= a) || (a + len <= r));
80 
81  r[0] = a[0];
82 
83  i = 0;
84  while (++i < len) {
85  secp256k1_scalar_mul(&r[i], &r[i - 1], &a[i]);
86  }
87 
88  secp256k1_scalar_inverse_var(&u, &r[--i]);
89 
90  while (i > 0) {
91  size_t j = i--;
92  secp256k1_scalar_mul(&r[j], &r[i], &u);
93  secp256k1_scalar_mul(&u, &u, &a[j]);
94  }
95 
96  r[0] = u;
97 }
98 
99 SECP256K1_INLINE static void secp256k1_bulletproof_serialize_points(unsigned char *out, secp256k1_ge *pt, size_t n) {
100  const size_t bitveclen = (n + 7) / 8;
101  size_t i;
102 
103  memset(out, 0, bitveclen);
104  for (i = 0; i < n; i++) {
105  secp256k1_fe pointx;
106  pointx = pt[i].x;
107  secp256k1_fe_normalize(&pointx);
108  secp256k1_fe_get_b32(&out[bitveclen + i*32], &pointx);
109  if (!secp256k1_fe_is_quad_var(&pt[i].y)) {
110  out[i/8] |= (1ull << (i % 8));
111  }
112  }
113 }
114 
115 SECP256K1_INLINE static int secp256k1_bulletproof_deserialize_point(secp256k1_ge *pt, const unsigned char *data, size_t i, size_t n) {
116  const size_t bitveclen = (n + 7) / 8;
117  const size_t offset = bitveclen + i*32;
118  secp256k1_fe fe;
119 
120  secp256k1_fe_set_b32(&fe, &data[offset]);
121  if (secp256k1_ge_set_xquad(pt, &fe)) {
122  if (data[i / 8] & (1 << (i % 8))) {
123  secp256k1_ge_neg(pt, pt);
124  }
125  return 1;
126  } else {
127  return 0;
128  }
129 }
130 
131 static void secp256k1_bulletproof_update_commit(unsigned char *commit, const secp256k1_ge *lpt, const secp256k1_ge *rpt) {
132  secp256k1_fe pointx;
134  unsigned char lrparity;
135  lrparity = (!secp256k1_fe_is_quad_var(&lpt->y) << 1) + !secp256k1_fe_is_quad_var(&rpt->y);
136  secp256k1_sha256_initialize(&sha256);
137  secp256k1_sha256_write(&sha256, commit, 32);
138  secp256k1_sha256_write(&sha256, &lrparity, 1);
139  pointx = lpt->x;
140  secp256k1_fe_normalize(&pointx);
141  secp256k1_fe_get_b32(commit, &pointx);
142  secp256k1_sha256_write(&sha256, commit, 32);
143  pointx = rpt->x;
144  secp256k1_fe_normalize(&pointx);
145  secp256k1_fe_get_b32(commit, &pointx);
146  secp256k1_sha256_write(&sha256, commit, 32);
147  secp256k1_sha256_finalize(&sha256, commit);
148 }
149 
150 static void secp256k1_bulletproof_update_commit_n(unsigned char *commit, const secp256k1_ge *pt, size_t n) {
152  unsigned char lrparity = 0;
153  size_t i;
154 
155  VERIFY_CHECK(n < 8);
156 
157  for (i = 0; i < n; i++) {
158  lrparity |= secp256k1_fe_is_quad_var(&pt[i].y) << i;
159  }
160 
161  secp256k1_sha256_initialize(&sha256);
162  secp256k1_sha256_write(&sha256, commit, 32);
163  secp256k1_sha256_write(&sha256, &lrparity, 1);
164  for (i = 0; i < n; i++) {
165  secp256k1_fe pointx;
166  pointx = pt[i].x;
167  secp256k1_fe_normalize(&pointx);
168  secp256k1_fe_get_b32(commit, &pointx);
169  secp256k1_sha256_write(&sha256, commit, 32);
170  }
171  secp256k1_sha256_finalize(&sha256, commit);
172 }
173 
174 /* Convenience function to compute blind*G + sum_i (s[i] * gen[i])
175  * If G is passed as NULL, use the standard generator. While in the
176  * standard-generator case we could use ecmult_gen rather than
177  * ecmult_const, we don't. This function is only used during proof
178  * generation so performance is not critical.
179  *
180  * If `blind` is NULL it is treated as zero.
181  *
182  * This function is not constant-time with respect to the NULLness
183  * of its inputs. NULLness should never be correlated with secret data.
184  */
185 static void secp256k1_bulletproof_vector_commit(secp256k1_gej *r, const secp256k1_scalar *s, const secp256k1_ge *gen, size_t n, const secp256k1_scalar *blind, const secp256k1_ge *g) {
186  secp256k1_scalar zero;
187  secp256k1_ge rge;
188 
189  if (g == NULL) {
190  g = &secp256k1_ge_const_g;
191  }
192  if (blind == NULL) {
193  secp256k1_scalar_clear(&zero);
194  blind = &zero;
195  }
196 
197  /* Multiply by blinding factor */
198  secp256k1_ecmult_const(r, g, blind, 256);
199 
200  /* Do the non-blind sum, going through contortions to avoid adding infinities */
201  while (n--) {
202  int inf;
203  secp256k1_ge tmpge;
204  secp256k1_ge negg;
205  secp256k1_gej tmpj;
206 
207  /* Add G, undoing it if this causes rge == infinity */
208  secp256k1_ge_set_gej(&tmpge, r);
209  secp256k1_gej_add_ge(r, r, g);
210  secp256k1_ge_set_gej(&rge, r);
211 
212  inf = secp256k1_ge_is_infinity(&rge);
213  secp256k1_fe_cmov(&rge.x, &tmpge.x, inf);
214  secp256k1_fe_cmov(&rge.y, &tmpge.y, inf);
215  rge.infinity = 0;
216 
217  /* Add the next term to our now-guaranteed-noninfinite R */
218  secp256k1_ecmult_const(&tmpj, &gen[n], &s[n], 256);
219  secp256k1_gej_add_ge(r, &tmpj, &rge); /* here tmpj may be infinite but tmpge won't be */
220 
221  /* Subtract G, undoing it if we undid the addition above */
222  secp256k1_ge_neg(&negg, g);
223  secp256k1_ge_set_gej(&tmpge, r);
224  secp256k1_gej_add_ge(r, r, &negg);
225  secp256k1_ge_set_gej(&rge, r);
226 
227  secp256k1_fe_cmov(&rge.x, &tmpge.x, inf);
228  secp256k1_fe_cmov(&rge.y, &tmpge.y, inf);
229  rge.infinity = rge.infinity * (1 - inf) + tmpge.infinity * inf;
230  }
231 }
232 
233 #endif
VERIFY_CHECK
#define VERIFY_CHECK(cond)
Definition: util.h:61
secp256k1_ge::y
secp256k1_fe y
Definition: group.h:20
b
void const uint64_t * b
Definition: field_5x52_asm_impl.h:10
sha256
Internal SHA-256 implementation.
Definition: sha256.cpp:15
secp256k1_sha256
Definition: hash.h:13
r
void const uint64_t uint64_t * r
Definition: field_5x52_asm_impl.h:10
secp256k1_scalar
A scalar modulo the group order of the secp256k1 curve.
Definition: scalar_4x64.h:13
secp256k1_gej
A group element of the secp256k1 curve, in jacobian coordinates.
Definition: group.h:24
secp256k1_fe
Definition: field_10x26.h:12
secp256k1_ge::infinity
int infinity
Definition: group.h:21
SECP256K1_INLINE
#define SECP256K1_INLINE
Definition: secp256k1.h:23
secp256k1_ge::x
secp256k1_fe x
Definition: group.h:19
secp256k1_ge
A group element of the secp256k1 curve, in affine coordinates.
Definition: group.h:14