Zeth - Zerocash on Ethereum  0.8
Reference implementation of the Zeth protocol by Clearmatics
parse_r1cs.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
3 # Copyright (c) 2015-2022 Clearmatics Technologies Ltd
4 #
5 # SPDX-License-Identifier: LGPL-3.0+
6 
7 import json
8 import os
9 import re
10 
11 def get_index(annotation_set, annotation):
12  """
13  Finds the index corresponding to `annotation`
14  in the annotation set (which has the structure below)
15 
16  "variables_annotations":
17  [
18  { "index": INDEX, "annotation": ANNOTATION },
19 
20  ...
21 
22  { "index": INDEX, "annotation": ANNOTATION }
23  ]
24  """
25 
26  for i in range(len(annotation_set)):
27  if annotation_set[i]["annotation"] == annotation:
28  return annotation_set[i]["index"]
29 
30 
31 def get_constraints(constraints_set, annotation_index):
32  """
33  Returns the set of constraints in which a given wire figures
34  (wire = index of a variable annotation)
35  The set of constraints has the structure below:
36 
37 
38  "constraints":
39  [
40  {
41  "constraint_id": ID,
42  "constraint_annotation": ANNOTATION
43  "linear_combination": {
44  # `index:` Index of the wire/variable
45  # `value:` Scalar by which the wire value is multiplied
46  # by in the linear combination A
47  "A": [
48  { "index": "0", "value": "0x1" }
49  ],
50  "B": [
51  { "index": "530", "scalar": "0x1" },
52  { "index": "531", "scalar": "0x2" },
53  { "index": "532", "scalar": "0x4" }
54  ],
55  "C": [
56  { "index": "2", "scalar": "0x1" }
57  ]
58  }
59  }
60  ]
61  """
62 
63  # Array of ID of the constraints using the provided annotation index
64  constraints_id = []
65  for i in range(len(constraints_set)):
66  lin_com_a = constraints_set[i]["linear_combination"]["A"]
67  lin_com_b = constraints_set[i]["linear_combination"]["B"]
68  lin_com_c = constraints_set[i]["linear_combination"]["C"]
69  found_in_a = is_in_lin_comb(lin_com_a, annotation_index)
70  found_in_b = is_in_lin_comb(lin_com_b, annotation_index)
71  found_in_c = is_in_lin_comb(lin_com_c, annotation_index)
72  if found_in_a or found_in_b or found_in_c:
73  constraints_id.append(constraints_set[i]["constraint_id"])
74  print("Constraint: ", str(constraints_set[i]))
75  return constraints_id
76 
77 def get_constraints_from_annotation_pattern(constraints_set, annotation_pattern):
78  """
79  Returns a set of constraints which annotation matches the given pattern.
80  The regex is given by the user (which can be quite dangerous but
81  the goal of this script is not to be robust anyway)
82  """
83 
84  # Array of ID of the constraints using the provided annotation index
85  constraints_id = []
86  for i in range(len(constraints_set)):
87  constraint_annotation = constraints_set[i]["constraint_annotation"]
88  x = re.search(annotation_pattern, constraint_annotation)
89  # If there has been a match
90  if x is not None:
91  constraints_id.append(constraints_set[i]["constraint_id"])
92  print("Constraint: ", str(constraints_set[i]))
93  return constraints_id
94 
95 
96 def is_in_lin_comb(linear_combination, annotation_index):
97  """
98  Inspects all the elements of the linear combination and returns
99  true is the variable corresponding to the annotation_index
100  is used in the linear combination
101  """
102 
103  # Inspect all the linear terms
104  for i in range(len(linear_combination)):
105  if linear_combination[i]["index"] == annotation_index:
106  return True
107 
108 
109 if __name__ == "__main__":
110  path_zeth = os.environ["ZETH_DEBUG_DIR"]
111  filename = "r1cs.json"
112 
113  # Read file
114  file_path = os.path.join(path_zeth, filename)
115  with open(file_path, 'r') as r1cs_file:
116  data=r1cs_file.read()
117 
118  # Parse file
119  r1cs_obj = json.loads(data)
120  r1cs_variables_nb = r1cs_obj["num_variables"]
121  r1cs_constraints_nb = r1cs_obj["num_constraints"]
122 
123  print("R1CS successfully loaded, vars: {}, constraints: {}"
124  .format(r1cs_variables_nb, r1cs_variables_nb))
125 
126  variables_annotations_set = r1cs_obj["variables_annotations"]
127  constraints_set = r1cs_obj["constraints"]
128 
129  # Some basic happy path tests are written below to try some of the
130  # functions defined above
131  #
132  # Eg: Check the 31th bit of phi
133  annotation_to_check = "joinsplit_gadget phi bits_31"
134  annotation_index = get_index(variables_annotations_set, annotation_to_check)
135  print("Index of the annotation to check: {}".format(annotation_index))
136 
137  print("Fetching constraints using annotation: {} of index: {}..."
138  .format(annotation_to_check, annotation_index))
139  constraints_using_annotation = get_constraints(constraints_set, annotation_index)
140  print("Result: {}".format(constraints_using_annotation))
141 
142  regex = "rho"
143  print("Testing the regex matching. Query: {}".format(regex))
144  res = get_constraints_from_annotation_pattern(constraints_set, regex)
145  #print(f"Result: {res}")
test_commands.mock.str
str
Definition: mock.py:18
analyzer.parse_r1cs.get_constraints_from_annotation_pattern
def get_constraints_from_annotation_pattern(constraints_set, annotation_pattern)
Definition: parse_r1cs.py:77
analyzer.parse_r1cs.get_index
def get_index(annotation_set, annotation)
Definition: parse_r1cs.py:11
analyzer.parse_r1cs.is_in_lin_comb
def is_in_lin_comb(linear_combination, annotation_index)
Definition: parse_r1cs.py:96
analyzer.parse_r1cs.get_constraints
def get_constraints(constraints_set, annotation_index)
Definition: parse_r1cs.py:31