Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
api_ultra_honk.cpp
Go to the documentation of this file.
1#include "api_ultra_honk.hpp"
2
16#include <iomanip>
17#include <optional>
18#include <sstream>
19
20namespace bb {
21
22namespace {
23
24void write_vk_outputs(const bbapi::CircuitComputeVk::Response& vk_response,
25 const std::string& output_format,
26 const std::filesystem::path& output_dir)
27{
28 if (output_format == "bytes" || output_format == "bytes_and_fields") {
29 write_file(output_dir / "vk", vk_response.bytes);
30 info("VK saved to ", output_dir / "vk");
31 write_file(output_dir / "vk_hash", vk_response.hash);
32 info("VK Hash saved to ", output_dir / "vk_hash");
33 }
34
35 if (output_format == "fields" || output_format == "bytes_and_fields") {
36 // Use the fields directly from vk_response
37 std::string vk_json = field_elements_to_json(vk_response.fields);
38 write_file(output_dir / "vk_fields.json", { vk_json.begin(), vk_json.end() });
39 info("VK fields saved to ", output_dir / "vk_fields.json");
40
41 // For vk_hash fields - convert the bytes to fr and then to JSON
42 auto vk_hash_fr = from_buffer<fr>(vk_response.hash);
43 std::string vk_hash_json = format("\"", vk_hash_fr, "\"");
44 write_file(output_dir / "vk_hash_fields.json", { vk_hash_json.begin(), vk_hash_json.end() });
45 info("VK Hash fields saved to ", output_dir / "vk_hash_fields.json");
46 }
47}
48
49void write_proof_outputs(const bbapi::CircuitProve::Response& prove_response,
50 const std::string& output_format,
51 const std::filesystem::path& output_dir)
52{
53 if (output_format == "bytes" || output_format == "bytes_and_fields") {
54 auto public_inputs_buf = to_buffer(prove_response.public_inputs);
55 auto proof_buf = to_buffer(prove_response.proof);
56
57 write_file(output_dir / "public_inputs", public_inputs_buf);
58 write_file(output_dir / "proof", proof_buf);
59 info("Public inputs saved to ", output_dir / "public_inputs");
60 info("Proof saved to ", output_dir / "proof");
61 }
62
63 if (output_format == "fields" || output_format == "bytes_and_fields") {
64 std::string public_inputs_json = field_elements_to_json(prove_response.public_inputs);
65 std::string proof_json = field_elements_to_json(prove_response.proof);
66
67 write_file(output_dir / "public_inputs_fields.json", { public_inputs_json.begin(), public_inputs_json.end() });
68 write_file(output_dir / "proof_fields.json", { proof_json.begin(), proof_json.end() });
69 info("Public inputs fields saved to ", output_dir / "public_inputs_fields.json");
70 info("Proof fields saved to ", output_dir / "proof_fields.json");
71 }
72}
73} // namespace
74
75bool UltraHonkAPI::check([[maybe_unused]] const Flags& flags,
76 [[maybe_unused]] const std::filesystem::path& bytecode_path,
77 [[maybe_unused]] const std::filesystem::path& witness_path)
78{
79 throw_or_abort("API function check_witness not implemented");
80 return false;
81}
82
83void UltraHonkAPI::prove(const Flags& flags,
84 const std::filesystem::path& bytecode_path,
85 const std::filesystem::path& witness_path,
86 const std::filesystem::path& vk_path,
87 const std::filesystem::path& output_dir)
88{
89 // Validate output directory
90 if (output_dir == "-") {
91 throw_or_abort("Stdout output is not supported. Please specify an output directory.");
92 }
93
94 // Convert flags to ProofSystemSettings
96 .oracle_hash_type = flags.oracle_hash_type,
97 .disable_zk = flags.disable_zk };
98 // Handle VK
99 std::vector<uint8_t> vk_bytes;
100 if (!vk_path.empty() && !flags.write_vk) {
101 vk_bytes = read_file(vk_path);
102 }
103
104 // Prove
105 auto response = bbapi::CircuitProve{ .circuit = { .name = "circuit",
106 .bytecode = get_bytecode(bytecode_path),
107 .verification_key = std::move(vk_bytes) },
108 .witness = get_bytecode(witness_path),
109 .settings = std::move(settings) }
110 .execute();
111
112 // Write proof outputs (not VK - that's handled above)
113 write_proof_outputs(response, flags.output_format, output_dir);
114 if (flags.write_vk) {
115 write_vk_outputs(response.vk, flags.output_format, output_dir);
116 }
117}
118
119bool UltraHonkAPI::verify(const Flags& flags,
120 const std::filesystem::path& public_inputs_path,
121 const std::filesystem::path& proof_path,
122 const std::filesystem::path& vk_path)
123{
124 // Read input files
125 auto public_inputs = many_from_buffer<uint256_t>(read_file(public_inputs_path));
126 auto proof = many_from_buffer<uint256_t>(read_file(proof_path));
127 auto vk_bytes = read_file(vk_path);
128
129 // Convert flags to ProofSystemSettings
131 .oracle_hash_type = flags.oracle_hash_type,
132 .disable_zk = flags.disable_zk };
133
134 // Execute verify command
135 auto response = bbapi::CircuitVerify{ .verification_key = std::move(vk_bytes),
136 .public_inputs = std::move(public_inputs),
137 .proof = std::move(proof),
138 .settings = settings }
139 .execute();
140
141 return response.verified;
142}
143
144bool UltraHonkAPI::prove_and_verify([[maybe_unused]] const Flags& flags,
145 [[maybe_unused]] const std::filesystem::path& bytecode_path,
146 [[maybe_unused]] const std::filesystem::path& witness_path)
147{
148 throw_or_abort("API function prove_and_verify not implemented");
149 return false;
150}
151
153 const std::filesystem::path& bytecode_path,
154 const std::filesystem::path& output_dir)
155{
156 // Validate output directory
157 if (output_dir == "-") {
158 throw_or_abort("Stdout output is not supported. Please specify an output directory.");
159 }
160
161 // Read bytecode
162 auto bytecode = get_bytecode(bytecode_path);
163
164 // Convert flags to ProofSystemSettings
166 .oracle_hash_type = flags.oracle_hash_type,
167 .disable_zk = flags.disable_zk };
168
169 // Execute compute VK command
170 auto response = bbapi::CircuitComputeVk{ .circuit = { .name = "circuit", .bytecode = std::move(bytecode) },
171 .settings = settings }
172 .execute();
173
174 // Write VK outputs using the helper function
175 write_vk_outputs(response, flags.output_format, output_dir);
176}
177
178void UltraHonkAPI::gates([[maybe_unused]] const Flags& flags,
179 [[maybe_unused]] const std::filesystem::path& bytecode_path)
180{
181 // Get the bytecode directly
182 auto bytecode = get_bytecode(bytecode_path);
183
184 // All circuit reports will be built into the string below
185 std::string functions_string = "{\"functions\": [\n ";
186
187 // For now, treat the entire bytecode as a single circuit
188 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1074): Handle multi-circuit programs properly
189 // Convert flags to ProofSystemSettings
190 bbapi::ProofSystemSettings settings{ .ipa_accumulation = flags.ipa_accumulation,
191 .oracle_hash_type = flags.oracle_hash_type,
192 .disable_zk = flags.disable_zk };
193
194 // Execute CircuitStats command
195 auto response = bbapi::CircuitStats{ .circuit = { .name = "circuit", .bytecode = bytecode, .verification_key = {} },
196 .include_gates_per_opcode = flags.include_gates_per_opcode,
197 .settings = settings }
198 .execute();
199
200 vinfo("Calculated circuit size in gate_count: ", response.num_gates);
201
202 // Build individual circuit report to match original gate_count output
203 std::string gates_per_opcode_str;
204 if (flags.include_gates_per_opcode) {
205 size_t i = 0;
206 for (size_t count : response.gates_per_opcode) {
207 if (i != 0) {
208 gates_per_opcode_str += ",";
209 }
210 gates_per_opcode_str += std::to_string(count);
211 i++;
212 }
213 }
214
215 // For now, we'll use the CircuitStats response which includes circuit statistics
216 // The num_acir_opcodes is not directly available from bytecode alone
217 auto result_string = format(
218 "{\n \"acir_opcodes\": ",
219 response.num_acir_opcodes,
220 ",\n \"circuit_size\": ",
221 response.num_gates,
222 (flags.include_gates_per_opcode ? format(",\n \"gates_per_opcode\": [", gates_per_opcode_str, "]") : ""),
223 "\n }");
224
225 functions_string = format(functions_string, result_string);
226 std::cout << format(functions_string, "\n]}");
227}
228
230 const std::filesystem::path& output_path,
231 const std::filesystem::path& vk_path)
232{
233 // Read VK file
234 auto vk_bytes = read_file(vk_path);
235
236 // Convert flags to ProofSystemSettings
238 .oracle_hash_type = flags.oracle_hash_type,
239 .disable_zk = flags.disable_zk };
240
241 // Execute solidity verifier command
242 auto response = bbapi::CircuitWriteSolidityVerifier{ .verification_key = vk_bytes, .settings = settings }.execute();
243
244 // Write output
245 if (output_path == "-") {
246 std::cout << response.solidity_code;
247 } else {
248 write_file(output_path, { response.solidity_code.begin(), response.solidity_code.end() });
249 if (flags.disable_zk) {
250 info("Honk solidity verifier saved to ", output_path);
251 } else {
252 info("ZK Honk solidity verifier saved to ", output_path);
253 }
254 }
255}
256} // namespace bb
UltraHonk-specific command definitions for the Barretenberg RPC API.
void prove(const Flags &flags, const std::filesystem::path &bytecode_path, const std::filesystem::path &witness_path, const std::filesystem::path &vk_path, const std::filesystem::path &output_dir)
void write_vk(const Flags &flags, const std::filesystem::path &bytecode_path, const std::filesystem::path &output_path) override
bool verify(const Flags &flags, const std::filesystem::path &public_inputs_path, const std::filesystem::path &proof_path, const std::filesystem::path &vk_path) override
bool check(const Flags &flags, const std::filesystem::path &bytecode_path, const std::filesystem::path &witness_path) override
bool prove_and_verify(const Flags &flags, const std::filesystem::path &bytecode_path, const std::filesystem::path &witness_path)
void gates(const Flags &flags, const std::filesystem::path &bytecode_path) override
void write_solidity_verifier(const Flags &flags, const std::filesystem::path &output_path, const std::filesystem::path &vk_path) override
std::string format(Args... args)
Definition log.hpp:20
void vinfo(Args... args)
Definition log.hpp:76
void info(Args... args)
Definition log.hpp:70
std::vector< uint8_t > get_bytecode(const std::string &bytecodePath)
Entry point for Barretenberg command-line interface.
std::vector< uint8_t > read_file(const std::string &filename, size_t bytes=0)
Definition file_io.hpp:29
void write_file(const std::string &filename, std::vector< uint8_t > const &data)
Definition file_io.hpp:58
std::string field_elements_to_json(const std::vector< Fr > &fields)
Definition file_io.hpp:90
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
std::vector< uint8_t > to_buffer(T const &value)
bool write_vk
Definition api.hpp:23
bool disable_zk
Definition api.hpp:13
bool ipa_accumulation
Definition api.hpp:17
std::string oracle_hash_type
Definition api.hpp:19
std::string output_format
Definition api.hpp:20
std::string name
Human-readable name for the circuit.
std::string name
Human-readable name for the circuit.
Represents a request to generate a proof. Currently, UltraHonk is the only proving system supported b...
Consolidated command for retrieving circuit information. Combines gate count, circuit size,...
Verify a proof against a verification key and public inputs.
std::vector< uint8_t > verification_key
Command to generate Solidity verifier contract.
bool ipa_accumulation
Optional flag to indicate if the proof should be generated with IPA accumulation (i....
void throw_or_abort(std::string const &err)