PRCYCoin  2.0.0.7rc1
P2P Digital Currency
parser_impl.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_PARSER_IMPL
8 #define SECP256K1_MODULE_BULLETPROOF_PARSER_IMPL
9 
10 #include <ctype.h>
11 #include <stdio.h>
12 
14 
15 static size_t secp256k1_bulletproof_encoding_width(size_t n) {
16  if (n < 0x100) return 1;
17  if (n < 0x10000) return 2;
18  if (n < 0x100000000) return 4;
19  return 8;
20 }
21 
22 static void secp256k1_encode(unsigned char *buf, size_t width, size_t n) {
23  size_t i;
24  for (i = 0; i < width; i++) {
25  buf[i] = n;
26  n >>= 8;
27  }
28 }
29 
30 static size_t secp256k1_decode(const unsigned char *buf, size_t width) {
31  size_t ret = 0;
32  while (width--) {
33  ret = ret * 0x100 + buf[width];
34  }
35  return ret;
36 }
37 
38 static size_t secp256k1_scalar_encode(unsigned char *buf, const secp256k1_fast_scalar *s) {
39  secp256k1_scalar tmp = s->scal;
40  size_t i = 0;
41  size_t high = secp256k1_scalar_is_high(&tmp);
42 
43  if (high) {
44  secp256k1_scalar_negate(&tmp, &tmp);
45  }
46 
47  while (!secp256k1_scalar_is_zero(&tmp)) {
48  buf[1 + i] = secp256k1_scalar_shr_int(&tmp, 8);
49  i++;
50  }
51 
52  buf[0] = i ^ (high << 7);
53  return i + 1;
54 }
55 
56 static int secp256k1_scalar_decode(secp256k1_fast_scalar *r, const unsigned char *buf) {
57  secp256k1_scalar two;
58  unsigned char rbuf[32] = {0};
59  const size_t neg = buf[0] & 0x80;
60  const size_t len = buf[0] & 0x3f;
61  size_t i;
62  int overflow;
63 
64  for (i = 0; i < len; i++) {
65  rbuf[31 - i] = buf[i + 1];
66  }
67  secp256k1_scalar_set_b32(&r->scal, rbuf, &overflow);
68  if (overflow) {
69  return 0;
70  }
71  secp256k1_scalar_set_int(&two, 2);
72  if (secp256k1_scalar_is_one(&r->scal)) {
73  r->special = neg ? -1 : 1;
74  } else if (secp256k1_scalar_eq(&r->scal, &two)) {
75  r->special = neg ? -2 : 2;
76  } else if (secp256k1_scalar_is_zero(&r->scal)) {
77  r->special = 0;
78  } else {
79  r->special = 5;
80  }
81  if (neg) {
82  secp256k1_scalar_negate(&r->scal, &r->scal);
83  }
84  return 1;
85 }
86 
87 static int secp256k1_bulletproof_matrix_encode(FILE *fh, const secp256k1_bulletproof_wmatrix_row *w, size_t n_rows) {
88  size_t i;
89  unsigned char buf[41];
90  const size_t row_width = secp256k1_bulletproof_encoding_width(n_rows);
91  for (i = 0; i < n_rows; i++) {
92  size_t j;
93  size_t scalar_width;
94  secp256k1_encode(buf, row_width, w[i].size);
95  if (fwrite(buf, row_width, 1, fh) != 1) {
96  return 0;
97  }
98  for (j = 0; j < w[i].size; j++) {
99  secp256k1_encode(buf, row_width, w[i].entry[j].idx);
100  scalar_width = secp256k1_scalar_encode(buf + row_width, &w[i].entry[j].scal);
101  if (fwrite(buf, row_width + scalar_width, 1, fh) != 1) {
102  return 0;
103  }
104  }
105  }
106  return 1;
107 }
108 
109 static int secp256k1_bulletproof_matrix_decode(FILE *fh, secp256k1_bulletproof_wmatrix_row *w, secp256k1_bulletproof_wmatrix_entry *entries, size_t *n_entries, size_t n_rows, size_t row_width) {
110  size_t i;
111  unsigned char buf[0x3f];
112 
113  for (i = 0; i < n_rows; i++) {
114  size_t j;
115  if (fread(buf, row_width, 1, fh) != 1) {
116  return 0;
117  }
118  w[i].size = secp256k1_decode(buf, row_width);
119  w[i].entry = &entries[*n_entries];
120  for (j = 0; j < w[i].size; j++) {
121  if (fread(buf, row_width, 1, fh) != 1) {
122  return 0;
123  }
124  w[i].entry[j].idx = secp256k1_decode(buf, row_width);
125  if (fread(buf, 1, 1, fh) != 1 ||
126  fread(buf + 1, buf[0] & 0x3f, 1, fh) != 1 ||
127  secp256k1_scalar_decode(&w[i].entry[j].scal, buf) != 1) {
128  return 0;
129  }
130  }
131  *n_entries += w[i].size;
132  }
133  return 1;
134 }
135 
136 /* Function that just does a one-pass through a circuit to allocate memory */
137 static int secp256k1_bulletproof_circuit_allocate_memory(const secp256k1_context2 *ctx, FILE *fh, secp256k1_bulletproof_circuit **ret) {
138  unsigned char buf[32];
139  size_t version;
140  size_t n_gates;
141  size_t n_bits;
142  size_t n_commits;
143  size_t n_constraints;
144  size_t n_entries;
145  size_t total_mem;
146  size_t i, w;
147 
148  if (fread(buf, 32, 1, fh) != 1) {
149  return 0;
150  }
151 
152  version = secp256k1_decode(&buf[0], 4); /* read version and flags as one word */
153  if (version != SECP256K1_BULLETPROOF_CIRCUIT_VERSION) {
154  return 0;
155  }
156  n_commits = secp256k1_decode(&buf[4], 4);
157  n_gates = secp256k1_decode(&buf[8], 8);
158  n_bits = secp256k1_decode(&buf[16], 8);
159  n_constraints = secp256k1_decode(&buf[24], 8);
160  if (n_bits > n_gates) {
161  return 0;
162  }
163 
164  /* WL / WR / WO / WV entries */
165  n_entries = 0;
166  w = secp256k1_bulletproof_encoding_width(n_gates);
167  for (i = 0; i < 3 * n_gates + n_commits; i++) {
168  size_t n;
169  if (i == 3 * n_gates) {
170  w = secp256k1_bulletproof_encoding_width(n_commits);
171  }
172  if (fread(buf, w, 1, fh) != 1) {
173  return 0;
174  }
175  n = secp256k1_decode(buf, w);
176  n_entries += n;
177  while (n--) {
178  if (fseek(fh, w, SEEK_CUR)) { /* skip index */
179  return 0;
180  }
181  if (fread(buf, 1, 1, fh) != 1) { /* read scalar width */
182  return 0;
183  }
184  if (fseek(fh, buf[0] & 0x3f, SEEK_CUR)) { /* skip scalar */
185  return 0;
186  }
187  }
188  }
189  /* Number of c entries is implied by n_constraints */
190  total_mem = sizeof(**ret) + (3 * n_gates + n_commits) * sizeof(*(*ret)->wl) + n_constraints * sizeof(*(*ret)->c) + n_entries * sizeof(*(*ret)->entries);
191  if (total_mem > SECP256K1_BULLETPROOF_MAX_CIRCUIT) {
192  return 0;
193  }
194 
195  /* Put the file handle back to the beginning of the file (well, right after the header) */
196  if (fseek(fh, 32, SEEK_SET) != 0) {
197  return 0;
198  }
199 
200  /* Actually allocate all the memory */
201  *ret = (secp256k1_bulletproof_circuit *)checked_malloc(&ctx->error_callback, sizeof(**ret));
202  if (*ret == NULL) {
203  return 0;
204  }
205 
206  (*ret)->wl = (secp256k1_bulletproof_wmatrix_row *)checked_malloc(&ctx->error_callback, (3 * n_gates + n_commits) * sizeof(*(*ret)->wl));
207  (*ret)->c = (secp256k1_fast_scalar *)checked_malloc(&ctx->error_callback, (3 * n_gates + n_commits) * sizeof(*(*ret)->c));
208  (*ret)->entries = (secp256k1_bulletproof_wmatrix_entry *)checked_malloc(&ctx->error_callback, n_entries * sizeof(*(*ret)->entries));
209  if ((*ret)->wl == NULL || (*ret)->c == NULL || (*ret)->entries == NULL) {
210  free((*ret)->wl);
211  free((*ret)->c);
212  free((*ret)->entries);
213  free(*ret);
214  *ret = NULL;
215  return 0;
216  }
217 
218  (*ret)->n_commits = n_commits;
219  (*ret)->n_gates = n_gates;
220  (*ret)->n_bits = n_bits;
221  (*ret)->n_constraints = n_constraints;
222  (*ret)->wr = &(*ret)->wl[1 * n_gates];
223  (*ret)->wo = &(*ret)->wl[2 * n_gates];
224  (*ret)->wv = &(*ret)->wl[3 * n_gates];
225 
226  return 1;
227 }
228 
229 /* text string parser */
230 static void secp256k1_parse_scalar(secp256k1_fast_scalar *r, const char *c, const char **end) {
231  int neg = 0;
232  int null = 1;
233  while (isspace(*c)) {
234  c++;
235  }
236  if (*c == '-') {
237  neg = 1;
238  }
239  if (*c == '-' || *c == '+') {
240  c++;
241  }
242  while (isspace(*c)) {
243  c++;
244  }
245  secp256k1_scalar_clear(&r->scal);
246  while (isdigit(*c)) {
247  secp256k1_scalar digit;
248  secp256k1_scalar_set_int(&digit, 10);
249  secp256k1_scalar_mul(&r->scal, &r->scal, &digit);
250  secp256k1_scalar_set_int(&digit, *c - '0');
251  secp256k1_scalar_add(&r->scal, &r->scal, &digit);
252  null = 0;
253  c++;
254  }
255  /* interpret empty string as 1 */
256  if (null == 1) {
257  secp256k1_scalar_set_int(&r->scal, 1);
258  }
259  while (*c && *c != ',' && *c != ';' && *c != '=' && *c != 'L' && *c != 'R' && *c != 'O' && *c != 'V') {
260  c++;
261  }
262  if (secp256k1_scalar_is_one(&r->scal)) {
263  r->special = neg ? -1 : 1;
264  } else if (secp256k1_scalar_is_zero(&r->scal)) {
265  r->special = 0;
266  } else {
267  r->special = 5;
268  }
269  if (neg) {
270  secp256k1_scalar_negate(&r->scal, &r->scal);
271  }
272  if (end != NULL) {
273  *end = c;
274  }
275 }
276 
277 static size_t secp256k1_compressed_circuit_size(const secp256k1_bulletproof_circuit *circ) {
278  /* cached C sum, cached WL/WR/WO sums for each gate, constraint-many z powers */
279  return (1 + 3 * circ->n_gates + circ->n_constraints) * sizeof(secp256k1_scalar);
280 }
281 
282 static secp256k1_bulletproof_circuit *secp256k1_parse_circuit(const secp256k1_context2 *ctx, const char *c) {
283  size_t i;
284  int chars_read;
285  const char *cstart;
286  int n_gates;
287  int n_commits;
288  int n_bits;
289  int n_constraints;
290  size_t entry_idx = 0;
291  secp256k1_bulletproof_circuit *ret = (secp256k1_bulletproof_circuit*)checked_malloc(&ctx->error_callback, sizeof(*ret));
292 
293  if (sscanf(c, "%d,%d,%d,%d; %n", &n_gates, &n_commits, &n_bits, &n_constraints, &chars_read) != 4) {
294  free (ret);
295  return NULL;
296  }
297  c += chars_read;
298 
299  ret->n_gates = n_gates;
300  ret->n_commits = n_commits;
301  ret->n_bits = n_bits;
302  ret->n_constraints = n_constraints;
303  ret->wl = (secp256k1_bulletproof_wmatrix_row *)checked_malloc(&ctx->error_callback, (3*ret->n_gates + ret->n_commits) * sizeof(*ret->wl));
304  ret->wr = &ret->wl[1 * n_gates];
305  ret->wo = &ret->wl[2 * n_gates];
306  ret->wv = &ret->wl[3 * n_gates];
307  ret->c = (secp256k1_fast_scalar *)checked_malloc(&ctx->error_callback, ret->n_constraints * sizeof(*ret->c));
308  ret->entries = NULL;
309 
310  memset(ret->wl, 0, ret->n_gates * sizeof(*ret->wl));
311  memset(ret->wr, 0, ret->n_gates * sizeof(*ret->wr));
312  memset(ret->wo, 0, ret->n_gates * sizeof(*ret->wo));
313  memset(ret->wv, 0, ret->n_commits * sizeof(*ret->wv));
314  memset(ret->c, 0, ret->n_constraints * sizeof(*ret->c));
315 
316  cstart = c;
317  for (i = 0; i < ret->n_constraints; i++) {
318  int index;
319  size_t j;
320 
321  j = 0;
322  while (*c && *c != '=') {
326 
327  secp256k1_parse_scalar(&mul, c, &c);
328  switch (*c) {
329  case 'L':
330  w = ret->wl;
331  break;
332  case 'R':
333  w = ret->wr;
334  break;
335  case 'O':
336  w = ret->wo;
337  break;
338  case 'V':
339  w = ret->wv;
340  break;
341  default:
343  return NULL;
344  }
345  c++;
346  if (sscanf(c, "%d %n", &index, &chars_read) != 1) {
348  return NULL;
349  }
350  if ((w != ret->wv && index >= n_gates) || (w == ret->wv && index >= n_commits)) {
352  return NULL;
353  }
354  row = &w[index];
355 
356  row->size++;
357  entry_idx++;
358 
359  c += chars_read;
360  j++;
361  }
362  if (*c == '=') {
363  c++;
364  secp256k1_parse_scalar(&ret->c[i], c, &c);
365  if (*c != ';') {
367  return NULL;
368  }
369  c++;
370  } else {
372  return NULL;
373  }
374  }
375 
376  c = cstart;
377  ret->entries = (secp256k1_bulletproof_wmatrix_entry *)checked_malloc(&ctx->error_callback, entry_idx * sizeof(*ret->entries));
378  entry_idx = 0;
379  for (i = 0; i < ret->n_gates; i++) {
380  ret->wl[i].entry = &ret->entries[entry_idx];
381  entry_idx += ret->wl[i].size;
382  ret->wl[i].size = 0;
383  ret->wr[i].entry = &ret->entries[entry_idx];
384  entry_idx += ret->wr[i].size;
385  ret->wr[i].size = 0;
386  ret->wo[i].entry = &ret->entries[entry_idx];
387  entry_idx += ret->wo[i].size;
388  ret->wo[i].size = 0;
389  }
390  for (i = 0; i < ret->n_commits; i++) {
391  ret->wv[i].entry = &ret->entries[entry_idx];
392  entry_idx += ret->wv[i].size;
393  ret->wv[i].size = 0;
394  }
395 
396  for (i = 0; i < ret->n_constraints; i++) {
397  int index;
398  size_t j;
399 
400  j = 0;
401  while (*c && *c != '=') {
406 
407  secp256k1_parse_scalar(&mul, c, &c);
408  switch (*c) {
409  case 'L':
410  w = ret->wl;
411  break;
412  case 'R':
413  w = ret->wr;
414  break;
415  case 'O':
416  w = ret->wo;
417  break;
418  case 'V':
419  /* W_V is on the opposite side of the equation from W_L/W_R/W_O */
420  secp256k1_scalar_negate(&mul.scal, &mul.scal);
421  mul.special *= -1;
422  w = ret->wv;
423  break;
424  default:
426  return NULL;
427  }
428  c++;
429  sscanf(c, "%d %n", &index, &chars_read);
430  row = &w[index];
431 
432  row->size++;
433  entry = &row->entry[row->size - 1];
434  entry->idx = i;
435  entry->scal = mul;
436 
437  c += chars_read;
438  j++;
439  }
440  c++;
441  secp256k1_parse_scalar(&ret->c[i], c, &c);
442  c++;
443  }
444 
445  return ret;
446 }
447 
448 #endif
secp256k1_fast_scalar::special
int special
Definition: main_impl.h:21
circuit_compress_impl.h
SECP256K1_BULLETPROOF_CIRCUIT_VERSION
#define SECP256K1_BULLETPROOF_CIRCUIT_VERSION
Version number used in header of circuit and circuit-assignment binary files.
Definition: secp256k1_bulletproofs.h:22
secp256k1_bulletproof_circuit::n_commits
size_t n_commits
Definition: main_impl.h:33
secp256k1_bulletproof_circuit::n_bits
size_t n_bits
Definition: main_impl.h:35
secp256k1_bulletproof_circuit::wr
secp256k1_bulletproof_wmatrix_row * wr
Definition: main_impl.h:37
r
void const uint64_t uint64_t * r
Definition: field_5x52_asm_impl.h:10
secp256k1_fast_scalar::scal
secp256k1_scalar scal
Definition: main_impl.h:22
secp256k1_scalar
A scalar modulo the group order of the secp256k1 curve.
Definition: scalar_4x64.h:13
high
sph_u32 high
Definition: keccak.c:370
secp256k1_bulletproof_circuit::wv
secp256k1_bulletproof_wmatrix_row * wv
Definition: main_impl.h:39
secp256k1_bulletproof_circuit::c
secp256k1_fast_scalar * c
Definition: main_impl.h:40
secp256k1_bulletproof_circuit::wo
secp256k1_bulletproof_wmatrix_row * wo
Definition: main_impl.h:38
secp256k1_scalar
uint32_t secp256k1_scalar
A scalar modulo the group order of the secp256k1 curve.
Definition: scalar_low.h:13
secp256k1_bulletproof_wmatrix_entry
Definition: main_impl.h:21
SECP256K1_BULLETPROOF_MAX_CIRCUIT
#define SECP256K1_BULLETPROOF_MAX_CIRCUIT
Definition: secp256k1_bulletproofs.h:28
secp256k1_bulletproof_circuit::n_gates
size_t n_gates
Definition: main_impl.h:32
secp256k1_bulletproof_circuit_destroy
SECP256K1_API void secp256k1_bulletproof_circuit_destroy(const secp256k1_context2 *ctx, secp256k1_bulletproof_circuit *circ) SECP256K1_ARG_NONNULL(1)
Destroys a circuit Args: ctx: pointer to a context object (cannot be NULL) gen: pointer to the circui...
Definition: main_impl.h:964
secp256k1_context_struct2::error_callback
secp256k1_callback error_callback
Definition: secp256k1_types.h:19
secp256k1_context_struct2
Definition: secp256k1_types.h:15
secp256k1_bulletproof_wmatrix_entry::idx
size_t idx
Definition: main_impl.h:22
secp256k1_fast_scalar
Definition: main_impl.h:16
secp256k1_bulletproof_wmatrix_entry::scal
secp256k1_fast_scalar scal
Definition: main_impl.h:23
secp256k1_bulletproof_circuit
Definition: main_impl.h:31
secp256k1_bulletproof_wmatrix_row::size
size_t size
Definition: main_impl.h:27
secp256k1_bulletproof_circuit::n_constraints
size_t n_constraints
Definition: main_impl.h:34
secp256k1_bulletproof_wmatrix_row::entry
secp256k1_bulletproof_wmatrix_entry * entry
Definition: main_impl.h:28
secp256k1_bulletproof_circuit::wl
secp256k1_bulletproof_wmatrix_row * wl
Definition: main_impl.h:36
secp256k1_bulletproof_wmatrix_row
Definition: main_impl.h:26
secp256k1_bulletproof_circuit::entries
secp256k1_bulletproof_wmatrix_entry * entries
Definition: main_impl.h:42