JSTprove 1.0.0__py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. jstprove-1.0.0.dist-info/METADATA +397 -0
  2. jstprove-1.0.0.dist-info/RECORD +81 -0
  3. jstprove-1.0.0.dist-info/WHEEL +6 -0
  4. jstprove-1.0.0.dist-info/entry_points.txt +2 -0
  5. jstprove-1.0.0.dist-info/licenses/LICENSE +26 -0
  6. jstprove-1.0.0.dist-info/top_level.txt +1 -0
  7. python/__init__.py +0 -0
  8. python/core/__init__.py +3 -0
  9. python/core/binaries/__init__.py +0 -0
  10. python/core/binaries/expander-exec +0 -0
  11. python/core/binaries/onnx_generic_circuit_1-0-0 +0 -0
  12. python/core/circuit_models/__init__.py +0 -0
  13. python/core/circuit_models/generic_onnx.py +231 -0
  14. python/core/circuit_models/simple_circuit.py +133 -0
  15. python/core/circuits/__init__.py +0 -0
  16. python/core/circuits/base.py +1000 -0
  17. python/core/circuits/errors.py +188 -0
  18. python/core/circuits/zk_model_base.py +25 -0
  19. python/core/model_processing/__init__.py +0 -0
  20. python/core/model_processing/converters/__init__.py +0 -0
  21. python/core/model_processing/converters/base.py +143 -0
  22. python/core/model_processing/converters/onnx_converter.py +1181 -0
  23. python/core/model_processing/errors.py +147 -0
  24. python/core/model_processing/onnx_custom_ops/__init__.py +16 -0
  25. python/core/model_processing/onnx_custom_ops/conv.py +111 -0
  26. python/core/model_processing/onnx_custom_ops/custom_helpers.py +56 -0
  27. python/core/model_processing/onnx_custom_ops/gemm.py +91 -0
  28. python/core/model_processing/onnx_custom_ops/maxpool.py +79 -0
  29. python/core/model_processing/onnx_custom_ops/onnx_helpers.py +173 -0
  30. python/core/model_processing/onnx_custom_ops/relu.py +43 -0
  31. python/core/model_processing/onnx_quantizer/__init__.py +0 -0
  32. python/core/model_processing/onnx_quantizer/exceptions.py +168 -0
  33. python/core/model_processing/onnx_quantizer/layers/__init__.py +0 -0
  34. python/core/model_processing/onnx_quantizer/layers/base.py +396 -0
  35. python/core/model_processing/onnx_quantizer/layers/constant.py +118 -0
  36. python/core/model_processing/onnx_quantizer/layers/conv.py +180 -0
  37. python/core/model_processing/onnx_quantizer/layers/gemm.py +171 -0
  38. python/core/model_processing/onnx_quantizer/layers/maxpool.py +140 -0
  39. python/core/model_processing/onnx_quantizer/layers/relu.py +76 -0
  40. python/core/model_processing/onnx_quantizer/onnx_op_quantizer.py +200 -0
  41. python/core/model_templates/__init__.py +0 -0
  42. python/core/model_templates/circuit_template.py +57 -0
  43. python/core/utils/__init__.py +0 -0
  44. python/core/utils/benchmarking_helpers.py +163 -0
  45. python/core/utils/constants.py +4 -0
  46. python/core/utils/errors.py +117 -0
  47. python/core/utils/general_layer_functions.py +268 -0
  48. python/core/utils/helper_functions.py +1138 -0
  49. python/core/utils/model_registry.py +166 -0
  50. python/core/utils/scratch_tests.py +66 -0
  51. python/core/utils/witness_utils.py +291 -0
  52. python/frontend/__init__.py +0 -0
  53. python/frontend/cli.py +115 -0
  54. python/frontend/commands/__init__.py +17 -0
  55. python/frontend/commands/args.py +100 -0
  56. python/frontend/commands/base.py +199 -0
  57. python/frontend/commands/bench/__init__.py +54 -0
  58. python/frontend/commands/bench/list.py +42 -0
  59. python/frontend/commands/bench/model.py +172 -0
  60. python/frontend/commands/bench/sweep.py +212 -0
  61. python/frontend/commands/compile.py +58 -0
  62. python/frontend/commands/constants.py +5 -0
  63. python/frontend/commands/model_check.py +53 -0
  64. python/frontend/commands/prove.py +50 -0
  65. python/frontend/commands/verify.py +73 -0
  66. python/frontend/commands/witness.py +64 -0
  67. python/scripts/__init__.py +0 -0
  68. python/scripts/benchmark_runner.py +833 -0
  69. python/scripts/gen_and_bench.py +482 -0
  70. python/tests/__init__.py +0 -0
  71. python/tests/circuit_e2e_tests/__init__.py +0 -0
  72. python/tests/circuit_e2e_tests/circuit_model_developer_test.py +1158 -0
  73. python/tests/circuit_e2e_tests/helper_fns_for_tests.py +190 -0
  74. python/tests/circuit_e2e_tests/other_e2e_test.py +217 -0
  75. python/tests/circuit_parent_classes/__init__.py +0 -0
  76. python/tests/circuit_parent_classes/test_circuit.py +969 -0
  77. python/tests/circuit_parent_classes/test_onnx_converter.py +201 -0
  78. python/tests/circuit_parent_classes/test_ort_custom_layers.py +116 -0
  79. python/tests/test_cli.py +1021 -0
  80. python/tests/utils_testing/__init__.py +0 -0
  81. python/tests/utils_testing/test_helper_functions.py +891 -0
@@ -0,0 +1,212 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from typing import TYPE_CHECKING, ClassVar
5
+
6
+ if TYPE_CHECKING:
7
+ import argparse
8
+
9
+ from python.core.utils.helper_functions import run_subprocess
10
+ from python.frontend.commands.args import ArgSpec
11
+ from python.frontend.commands.base import BaseCommand
12
+
13
+ SWEEP_CHOICES: tuple[str, ...] = ("depth", "breadth", "lenet")
14
+
15
+ DEPTH_MIN = ArgSpec(
16
+ name="depth_min",
17
+ flag="--depth-min",
18
+ help_text="(depth) minimum conv depth",
19
+ arg_type=int,
20
+ )
21
+
22
+ DEPTH_MAX = ArgSpec(
23
+ name="depth_max",
24
+ flag="--depth-max",
25
+ help_text="(depth) maximum conv depth",
26
+ arg_type=int,
27
+ )
28
+
29
+ INPUT_HW = ArgSpec(
30
+ name="input_hw",
31
+ flag="--input-hw",
32
+ help_text="(depth) input H=W (e.g., 56)",
33
+ arg_type=int,
34
+ )
35
+
36
+ ARCH_DEPTH = ArgSpec(
37
+ name="arch_depth",
38
+ flag="--arch-depth",
39
+ help_text="(breadth) conv blocks at fixed topology",
40
+ arg_type=int,
41
+ )
42
+
43
+ INPUT_HW_LIST = ArgSpec(
44
+ name="input_hw_list",
45
+ flag="--input-hw-list",
46
+ help_text="(breadth) sizes like '28,56,84,112' or '32:160:32'",
47
+ )
48
+
49
+ ITERATIONS = ArgSpec(
50
+ name="iterations",
51
+ flag="--iterations",
52
+ help_text="E2E loops per model (default 3 in sweeps)",
53
+ arg_type=int,
54
+ )
55
+
56
+ RESULTS = ArgSpec(
57
+ name="results",
58
+ flag="--results",
59
+ help_text="Path to JSONL results (e.g., benchmarking/depth_sweep.jsonl)",
60
+ )
61
+
62
+ ONNX_DIR = ArgSpec(
63
+ name="onnx_dir",
64
+ flag="--onnx-dir",
65
+ help_text="Override ONNX output dir (else chosen by sweep)",
66
+ )
67
+
68
+ INPUTS_DIR = ArgSpec(
69
+ name="inputs_dir",
70
+ flag="--inputs-dir",
71
+ help_text="Override inputs output dir (else chosen by sweep)",
72
+ )
73
+
74
+ POOL_CAP = ArgSpec(
75
+ name="pool_cap",
76
+ flag="--pool-cap",
77
+ help_text="Max pool blocks at start (Lenet-like: 2)",
78
+ arg_type=int,
79
+ )
80
+
81
+ STOP_AT_HW = ArgSpec(
82
+ name="stop_at_hw",
83
+ flag="--stop-at-hw",
84
+ help_text="Allow pooling while H >= this",
85
+ arg_type=int,
86
+ )
87
+
88
+ CONV_OUT_CH = ArgSpec(
89
+ name="conv_out_ch",
90
+ flag="--conv-out-ch",
91
+ help_text="Conv output channels",
92
+ arg_type=int,
93
+ )
94
+
95
+ FC_HIDDEN = ArgSpec(
96
+ name="fc_hidden",
97
+ flag="--fc-hidden",
98
+ help_text="Fully-connected hidden size",
99
+ arg_type=int,
100
+ )
101
+
102
+ N_ACTIONS = ArgSpec(
103
+ name="n_actions",
104
+ flag="--n-actions",
105
+ help_text="Classifier outputs (classes)",
106
+ arg_type=int,
107
+ )
108
+
109
+ TAG = ArgSpec(
110
+ name="tag",
111
+ flag="--tag",
112
+ help_text="Optional tag suffix for filenames",
113
+ )
114
+
115
+ MODE = ArgSpec(
116
+ name="mode",
117
+ flag="mode",
118
+ help_text="Sweep type: depth, breadth, or lenet.",
119
+ extra_kwargs={"choices": list(SWEEP_CHOICES)},
120
+ )
121
+
122
+
123
+ class SweepCommand(BaseCommand):
124
+ """Generate ONNX models and benchmark parameter sweeps (depth/breadth)."""
125
+
126
+ name: ClassVar[str] = "sweep"
127
+ aliases: ClassVar[list[str]] = []
128
+ help: ClassVar[str] = (
129
+ "Generate ONNX models and benchmark parameter sweeps (depth/breadth)."
130
+ )
131
+
132
+ SCRIPT_GEN_AND_BENCH: ClassVar[str] = "python.scripts.gen_and_bench"
133
+
134
+ DEPTH_DEFAULTS: ClassVar[tuple[tuple[ArgSpec, str], ...]] = (
135
+ (DEPTH_MIN, "1"),
136
+ (DEPTH_MAX, "16"),
137
+ (ITERATIONS, "3"),
138
+ (RESULTS, "benchmarking/depth_sweep.jsonl"),
139
+ )
140
+
141
+ BREADTH_DEFAULTS: ClassVar[tuple[tuple[ArgSpec, str], ...]] = (
142
+ (ARCH_DEPTH, "5"),
143
+ (INPUT_HW_LIST, "28,56,84,112"),
144
+ (ITERATIONS, "3"),
145
+ (RESULTS, "benchmarking/breadth_sweep.jsonl"),
146
+ (POOL_CAP, "2"),
147
+ (CONV_OUT_CH, "16"),
148
+ (FC_HIDDEN, "256"),
149
+ )
150
+
151
+ SWEEP_CONFIGS: ClassVar[dict[str, tuple[tuple[ArgSpec, str], ...]]] = {
152
+ SWEEP_CHOICES[0]: DEPTH_DEFAULTS,
153
+ SWEEP_CHOICES[1]: BREADTH_DEFAULTS,
154
+ }
155
+
156
+ SWEEP_ARGS: ClassVar[tuple[ArgSpec, ...]] = (
157
+ DEPTH_MIN,
158
+ DEPTH_MAX,
159
+ INPUT_HW,
160
+ ARCH_DEPTH,
161
+ INPUT_HW_LIST,
162
+ ITERATIONS,
163
+ RESULTS,
164
+ ONNX_DIR,
165
+ INPUTS_DIR,
166
+ POOL_CAP,
167
+ STOP_AT_HW,
168
+ CONV_OUT_CH,
169
+ FC_HIDDEN,
170
+ N_ACTIONS,
171
+ TAG,
172
+ )
173
+
174
+ OPTIONAL_SWEEP_ARGS: ClassVar[tuple[ArgSpec, ...]] = (ONNX_DIR, INPUTS_DIR, TAG)
175
+
176
+ @classmethod
177
+ def configure_parser(
178
+ cls: type[SweepCommand],
179
+ parser: argparse.ArgumentParser,
180
+ ) -> None:
181
+ MODE.add_to_parser(parser)
182
+
183
+ for arg_spec in cls.SWEEP_ARGS:
184
+ arg_spec.add_to_parser(parser)
185
+
186
+ @classmethod
187
+ def run(cls: type[SweepCommand], args: argparse.Namespace) -> None:
188
+ if not args.mode:
189
+ msg = "Specify sweep type: depth, breadth, or lenet"
190
+ raise ValueError(msg)
191
+
192
+ cls._run_sweep_benchmark(args, args.mode)
193
+
194
+ @classmethod
195
+ def _run_sweep_benchmark(
196
+ cls: type[SweepCommand],
197
+ args: argparse.Namespace,
198
+ sweep: str,
199
+ ) -> None:
200
+ provided_knobs = [getattr(args, spec.name, None) for spec in cls.SWEEP_ARGS]
201
+ simple = all(v is None for v in provided_knobs)
202
+
203
+ cmd = [sys.executable, "-m", cls.SCRIPT_GEN_AND_BENCH, "--sweep", sweep]
204
+
205
+ if simple:
206
+ defaults = cls.SWEEP_CONFIGS.get(sweep, ())
207
+ BaseCommand.append_args_from_specs(cmd, defaults)
208
+ BaseCommand.append_args_from_namespace(cmd, args, cls.OPTIONAL_SWEEP_ARGS)
209
+ else:
210
+ BaseCommand.append_args_from_namespace(cmd, args, cls.SWEEP_ARGS)
211
+
212
+ run_subprocess(cmd)
@@ -0,0 +1,58 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+ from typing import TYPE_CHECKING, ClassVar
5
+
6
+ if TYPE_CHECKING:
7
+ import argparse
8
+
9
+ from python.core.circuits.errors import CircuitRunError
10
+ from python.core.utils.helper_functions import CircuitExecutionConfig, RunType
11
+ from python.frontend.commands.args import CIRCUIT_PATH, MODEL_PATH
12
+ from python.frontend.commands.base import BaseCommand
13
+
14
+
15
+ class CompileCommand(BaseCommand):
16
+ """Compile an ONNX model to a circuit."""
17
+
18
+ name: ClassVar[str] = "compile"
19
+ aliases: ClassVar[list[str]] = ["comp"]
20
+ help: ClassVar[str] = (
21
+ "Compile a circuit (writes circuit + quantized model + weights)."
22
+ )
23
+
24
+ @classmethod
25
+ def configure_parser(
26
+ cls: type[CompileCommand],
27
+ parser: argparse.ArgumentParser,
28
+ ) -> None:
29
+ MODEL_PATH.add_to_parser(parser)
30
+ CIRCUIT_PATH.add_to_parser(
31
+ parser,
32
+ "Output path for the compiled circuit (e.g., circuit.txt).",
33
+ )
34
+
35
+ @classmethod
36
+ @BaseCommand.validate_required(MODEL_PATH, CIRCUIT_PATH)
37
+ @BaseCommand.validate_paths(MODEL_PATH)
38
+ @BaseCommand.validate_parent_paths(CIRCUIT_PATH)
39
+ def run(cls: type[CompileCommand], args: argparse.Namespace) -> None:
40
+ model_name_hint = Path(args.model_path).stem
41
+ circuit = cls._build_circuit(model_name_hint)
42
+
43
+ circuit.model_file_name = args.model_path
44
+ circuit.onnx_path = args.model_path
45
+ circuit.model_path = args.model_path
46
+
47
+ try:
48
+ circuit.base_testing(
49
+ CircuitExecutionConfig(
50
+ run_type=RunType.COMPILE_CIRCUIT,
51
+ circuit_path=args.circuit_path,
52
+ dev_mode=False,
53
+ ),
54
+ )
55
+ except CircuitRunError as e:
56
+ raise RuntimeError(e) from e
57
+
58
+ print(f"[compile] done → circuit={args.circuit_path}") # noqa: T201
@@ -0,0 +1,5 @@
1
+ """Constants for CLI commands."""
2
+
3
+ # Circuit defaults
4
+ DEFAULT_CIRCUIT_MODULE = "python.core.circuit_models.generic_onnx"
5
+ DEFAULT_CIRCUIT_CLASS = "GenericModelONNX"
@@ -0,0 +1,53 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, ClassVar
4
+
5
+ if TYPE_CHECKING:
6
+ import argparse
7
+
8
+ from python.frontend.commands.args import MODEL_PATH
9
+ from python.frontend.commands.base import BaseCommand
10
+
11
+
12
+ class ModelCheckCommand(BaseCommand):
13
+ """Check if a model is supported for quantization."""
14
+
15
+ name: ClassVar[str] = "model_check"
16
+ aliases: ClassVar[list[str]] = ["check"]
17
+ help: ClassVar[str] = "Check if the model is supported for quantization."
18
+
19
+ @classmethod
20
+ def configure_parser(
21
+ cls: type[ModelCheckCommand],
22
+ parser: argparse.ArgumentParser,
23
+ ) -> None:
24
+ MODEL_PATH.add_to_parser(parser)
25
+
26
+ @classmethod
27
+ @BaseCommand.validate_required(MODEL_PATH)
28
+ @BaseCommand.validate_paths(MODEL_PATH)
29
+ def run(cls: type[ModelCheckCommand], args: argparse.Namespace) -> None:
30
+ import onnx # noqa: PLC0415
31
+
32
+ from python.core.model_processing.onnx_quantizer.exceptions import ( # noqa: PLC0415
33
+ InvalidParamError,
34
+ UnsupportedOpError,
35
+ )
36
+ from python.core.model_processing.onnx_quantizer.onnx_op_quantizer import ( # noqa: PLC0415
37
+ ONNXOpQuantizer,
38
+ )
39
+
40
+ model = onnx.load(args.model_path)
41
+ quantizer = ONNXOpQuantizer()
42
+ try:
43
+ quantizer.check_model(model)
44
+ print(f"Model {args.model_path} is supported.") # noqa: T201
45
+ except UnsupportedOpError as e:
46
+ msg = (
47
+ f"Model {args.model_path} is NOT supported: "
48
+ f"Unsupported operations {e.unsupported_ops}"
49
+ )
50
+ raise RuntimeError(msg) from e
51
+ except InvalidParamError as e:
52
+ msg = f"Model {args.model_path} is NOT supported: {e.message}"
53
+ raise RuntimeError(msg) from e
@@ -0,0 +1,50 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, ClassVar
4
+
5
+ if TYPE_CHECKING:
6
+ import argparse
7
+
8
+ from python.core.circuits.errors import CircuitRunError
9
+ from python.core.utils.helper_functions import CircuitExecutionConfig, RunType
10
+ from python.frontend.commands.args import CIRCUIT_PATH, PROOF_PATH, WITNESS_PATH
11
+ from python.frontend.commands.base import BaseCommand
12
+
13
+
14
+ class ProveCommand(BaseCommand):
15
+ """Generate proof from witness."""
16
+
17
+ name: ClassVar[str] = "prove"
18
+ aliases: ClassVar[list[str]] = ["prov"]
19
+ help: ClassVar[str] = "Generate a proof from a circuit and witness."
20
+
21
+ @classmethod
22
+ def configure_parser(
23
+ cls: type[ProveCommand],
24
+ parser: argparse.ArgumentParser,
25
+ ) -> None:
26
+ CIRCUIT_PATH.add_to_parser(parser)
27
+ WITNESS_PATH.add_to_parser(parser, "Path to an existing witness.")
28
+ PROOF_PATH.add_to_parser(parser)
29
+
30
+ @classmethod
31
+ @BaseCommand.validate_required(CIRCUIT_PATH, WITNESS_PATH, PROOF_PATH)
32
+ @BaseCommand.validate_paths(CIRCUIT_PATH, WITNESS_PATH)
33
+ @BaseCommand.validate_parent_paths(PROOF_PATH)
34
+ def run(cls: type[ProveCommand], args: argparse.Namespace) -> None:
35
+ circuit = cls._build_circuit("cli")
36
+
37
+ try:
38
+ circuit.base_testing(
39
+ CircuitExecutionConfig(
40
+ run_type=RunType.PROVE_WITNESS,
41
+ circuit_path=args.circuit_path,
42
+ witness_file=args.witness_path,
43
+ proof_file=args.proof_path,
44
+ ecc=False,
45
+ ),
46
+ )
47
+ except CircuitRunError as e:
48
+ raise RuntimeError(e) from e
49
+
50
+ print(f"[prove] wrote proof → {args.proof_path}") # noqa: T201
@@ -0,0 +1,73 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, ClassVar
4
+
5
+ if TYPE_CHECKING:
6
+ import argparse
7
+
8
+ from python.core.circuits.errors import CircuitRunError
9
+ from python.core.utils.helper_functions import CircuitExecutionConfig, RunType
10
+ from python.frontend.commands.args import (
11
+ CIRCUIT_PATH,
12
+ INPUT_PATH,
13
+ OUTPUT_PATH,
14
+ PROOF_PATH,
15
+ WITNESS_PATH,
16
+ )
17
+ from python.frontend.commands.base import BaseCommand
18
+
19
+
20
+ class VerifyCommand(BaseCommand):
21
+ """Verify a proof."""
22
+
23
+ name: ClassVar[str] = "verify"
24
+ aliases: ClassVar[list[str]] = ["ver"]
25
+ help: ClassVar[str] = "Verify a proof."
26
+
27
+ @classmethod
28
+ def configure_parser(
29
+ cls: type[VerifyCommand],
30
+ parser: argparse.ArgumentParser,
31
+ ) -> None:
32
+ CIRCUIT_PATH.add_to_parser(parser)
33
+ INPUT_PATH.add_to_parser(parser)
34
+ OUTPUT_PATH.add_to_parser(parser, "Path to expected outputs JSON.")
35
+ WITNESS_PATH.add_to_parser(parser)
36
+ PROOF_PATH.add_to_parser(parser)
37
+
38
+ @classmethod
39
+ @BaseCommand.validate_required(
40
+ CIRCUIT_PATH,
41
+ INPUT_PATH,
42
+ OUTPUT_PATH,
43
+ WITNESS_PATH,
44
+ PROOF_PATH,
45
+ )
46
+ @BaseCommand.validate_paths(
47
+ CIRCUIT_PATH,
48
+ INPUT_PATH,
49
+ OUTPUT_PATH,
50
+ WITNESS_PATH,
51
+ PROOF_PATH,
52
+ )
53
+ def run(cls: type[VerifyCommand], args: argparse.Namespace) -> None:
54
+ circuit = cls._build_circuit("cli")
55
+
56
+ try:
57
+ circuit.base_testing(
58
+ CircuitExecutionConfig(
59
+ run_type=RunType.GEN_VERIFY,
60
+ circuit_path=args.circuit_path,
61
+ input_file=args.input_path,
62
+ output_file=args.output_path,
63
+ witness_file=args.witness_path,
64
+ proof_file=args.proof_path,
65
+ ecc=False,
66
+ ),
67
+ )
68
+ except CircuitRunError as e:
69
+ raise RuntimeError(e) from e
70
+
71
+ print( # noqa: T201
72
+ f"[verify] verification complete for proof → {args.proof_path}",
73
+ )
@@ -0,0 +1,64 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, ClassVar
4
+
5
+ if TYPE_CHECKING:
6
+ import argparse
7
+
8
+ from python.core.circuits.errors import CircuitRunError
9
+ from python.core.utils.helper_functions import CircuitExecutionConfig, RunType
10
+ from python.frontend.commands.args import (
11
+ CIRCUIT_PATH,
12
+ INPUT_PATH,
13
+ OUTPUT_PATH,
14
+ WITNESS_PATH,
15
+ )
16
+ from python.frontend.commands.base import BaseCommand
17
+
18
+
19
+ class WitnessCommand(BaseCommand):
20
+ """Generate witness from circuit and inputs."""
21
+
22
+ name: ClassVar[str] = "witness"
23
+ aliases: ClassVar[list[str]] = ["wit"]
24
+ help: ClassVar[str] = "Generate witness using a compiled circuit."
25
+
26
+ @classmethod
27
+ def configure_parser(
28
+ cls: type[WitnessCommand],
29
+ parser: argparse.ArgumentParser,
30
+ ) -> None:
31
+ CIRCUIT_PATH.add_to_parser(parser)
32
+ INPUT_PATH.add_to_parser(parser)
33
+ OUTPUT_PATH.add_to_parser(parser)
34
+ WITNESS_PATH.add_to_parser(parser)
35
+
36
+ @classmethod
37
+ @BaseCommand.validate_required(
38
+ CIRCUIT_PATH,
39
+ INPUT_PATH,
40
+ OUTPUT_PATH,
41
+ WITNESS_PATH,
42
+ )
43
+ @BaseCommand.validate_paths(CIRCUIT_PATH, INPUT_PATH)
44
+ @BaseCommand.validate_parent_paths(OUTPUT_PATH, WITNESS_PATH)
45
+ def run(cls: type[WitnessCommand], args: argparse.Namespace) -> None:
46
+ circuit = cls._build_circuit("cli")
47
+
48
+ try:
49
+ circuit.base_testing(
50
+ CircuitExecutionConfig(
51
+ run_type=RunType.GEN_WITNESS,
52
+ circuit_path=args.circuit_path,
53
+ input_file=args.input_path,
54
+ output_file=args.output_path,
55
+ witness_file=args.witness_path,
56
+ ),
57
+ )
58
+ except CircuitRunError as e:
59
+ raise RuntimeError(e) from e
60
+
61
+ print( # noqa: T201
62
+ f"[witness] wrote witness → {args.witness_path} "
63
+ f"and outputs → {args.output_path}",
64
+ )
File without changes