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
18#include <optional>
19
20namespace bb {
21
22namespace {
23
24void write_vk_outputs(const bbapi::CircuitComputeVk::Response& vk_response,
25 const std::filesystem::path& output_dir,
26 const API::Flags& flags)
27{
28 if (flags.output_format == "json") {
29 std::string json_content =
30 build_json_output(vk_response.fields, "vk", flags, bytes_to_hex_string(vk_response.hash));
31 write_file(output_dir / "vk.json", std::vector<uint8_t>(json_content.begin(), json_content.end()));
32 info("VK (JSON) saved to ", output_dir / "vk.json");
33 } else {
34 write_file(output_dir / "vk", vk_response.bytes);
35 info("VK saved to ", output_dir / "vk");
36 write_file(output_dir / "vk_hash", vk_response.hash);
37 info("VK Hash saved to ", output_dir / "vk_hash");
38 }
39}
40
41void write_proof_outputs(const bbapi::CircuitProve::Response& prove_response,
42 const std::filesystem::path& output_dir,
43 const API::Flags& flags)
44{
45 if (flags.output_format == "json") {
46 std::string vk_hash = bytes_to_hex_string(prove_response.vk.hash);
47 std::string proof_json = build_json_output(prove_response.proof, "proof", flags, vk_hash);
48 write_file(output_dir / "proof.json", std::vector<uint8_t>(proof_json.begin(), proof_json.end()));
49 info("Proof (JSON) saved to ", output_dir / "proof.json");
50
51 std::string pi_json = build_json_output(prove_response.public_inputs, "public_inputs", flags);
52 write_file(output_dir / "public_inputs.json", std::vector<uint8_t>(pi_json.begin(), pi_json.end()));
53 info("Public inputs (JSON) saved to ", output_dir / "public_inputs.json");
54 } else {
55 auto public_inputs_buf = to_buffer(prove_response.public_inputs);
56 auto proof_buf = to_buffer(prove_response.proof);
57
58 write_file(output_dir / "public_inputs", public_inputs_buf);
59 write_file(output_dir / "proof", proof_buf);
60 info("Public inputs saved to ", output_dir / "public_inputs");
61 info("Proof saved to ", output_dir / "proof");
62 }
63}
64
65} // anonymous namespace
66
67bool UltraHonkAPI::check([[maybe_unused]] const Flags& flags,
68 [[maybe_unused]] const std::filesystem::path& bytecode_path,
69 [[maybe_unused]] const std::filesystem::path& witness_path)
70{
71 throw_or_abort("API function check_witness not implemented");
72 return false;
73}
74
75void UltraHonkAPI::prove(const Flags& flags,
76 const std::filesystem::path& bytecode_path,
77 const std::filesystem::path& witness_path,
78 const std::filesystem::path& vk_path,
79 const std::filesystem::path& output_dir)
80{
81 BB_BENCH_NAME("UltraHonkAPI::prove");
82 // Validate output directory
83 if (output_dir == "-") {
84 throw_or_abort("Stdout output is not supported. Please specify an output directory.");
85 }
86
87 // Convert flags to ProofSystemSettings
89 .oracle_hash_type = flags.oracle_hash_type,
90 .disable_zk = flags.disable_zk };
91
92 // Read input files
93 auto bytecode = get_bytecode(bytecode_path);
94 auto witness = get_bytecode(witness_path);
95
96 // Handle VK
97 std::vector<uint8_t> vk_bytes;
98
99 if (!vk_path.empty() && !flags.write_vk) {
100 vk_bytes = read_file(vk_path);
101 }
102
103 // Prove
104 auto response = bbapi::CircuitProve{ .circuit = { .name = "circuit",
105 .bytecode = std::move(bytecode),
106 .verification_key = std::move(vk_bytes) },
107 .witness = std::move(witness),
108 .settings = std::move(settings) }
109 .execute();
110 write_proof_outputs(response, output_dir, flags);
111 if (flags.write_vk) {
112 write_vk_outputs(response.vk, output_dir, flags);
113 }
114}
115
116bool UltraHonkAPI::verify(const Flags& flags,
117 const std::filesystem::path& public_inputs_path,
118 const std::filesystem::path& proof_path,
119 const std::filesystem::path& vk_path)
120{
121 BB_BENCH_NAME("UltraHonkAPI::verify");
122 // Read input files
123 auto public_inputs = many_from_buffer<uint256_t>(read_file(public_inputs_path));
124 auto proof = many_from_buffer<uint256_t>(read_file(proof_path));
125 auto vk_bytes = read_vk_file(vk_path);
126
127 // Convert flags to ProofSystemSettings
129 .oracle_hash_type = flags.oracle_hash_type,
130 .disable_zk = flags.disable_zk };
131
132 // Execute verify command
133 auto response = bbapi::CircuitVerify{ .verification_key = std::move(vk_bytes),
134 .public_inputs = std::move(public_inputs),
135 .proof = std::move(proof),
136 .settings = settings }
137 .execute();
138
139 return response.verified;
140}
141
142bool UltraHonkAPI::prove_and_verify([[maybe_unused]] const Flags& flags,
143 [[maybe_unused]] const std::filesystem::path& bytecode_path,
144 [[maybe_unused]] const std::filesystem::path& witness_path)
145{
146 throw_or_abort("API function prove_and_verify not implemented");
147 return false;
148}
149
151 const std::filesystem::path& bytecode_path,
152 const std::filesystem::path& output_dir)
153{
154 BB_BENCH_NAME("UltraHonkAPI::write_vk");
155 // Validate output directory
156 if (output_dir == "-") {
157 throw_or_abort("Stdout output is not supported. Please specify an output directory.");
158 }
159
160 // Read bytecode
161 auto bytecode = get_bytecode(bytecode_path);
162
163 // Convert flags to ProofSystemSettings
165 .oracle_hash_type = flags.oracle_hash_type,
166 .disable_zk = flags.disable_zk };
167
168 auto response = bbapi::CircuitComputeVk{ .circuit = { .name = "circuit", .bytecode = std::move(bytecode) },
169 .settings = settings }
170 .execute();
171
172 write_vk_outputs(response, output_dir, flags);
173}
174
175void UltraHonkAPI::gates([[maybe_unused]] const Flags& flags,
176 [[maybe_unused]] const std::filesystem::path& bytecode_path)
177{
178 BB_BENCH_NAME("UltraHonkAPI::gates");
179 // Get the bytecode directly
180 auto bytecode = get_bytecode(bytecode_path);
181
182 // All circuit reports will be built into the string below
183 std::string functions_string = "{\"functions\": [\n ";
184
185 // For now, treat the entire bytecode as a single circuit
186 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1074): Handle multi-circuit programs properly
187 // Convert flags to ProofSystemSettings
188 bbapi::ProofSystemSettings settings{ .ipa_accumulation = flags.ipa_accumulation,
189 .oracle_hash_type = flags.oracle_hash_type,
190 .disable_zk = flags.disable_zk };
191
192 // Execute CircuitStats command
193 auto response = bbapi::CircuitStats{ .circuit = { .name = "circuit", .bytecode = bytecode, .verification_key = {} },
194 .include_gates_per_opcode = flags.include_gates_per_opcode,
195 .settings = settings }
196 .execute();
197
198 vinfo("Calculated circuit size in gate_count: ", response.num_gates);
199
200 // Build individual circuit report to match original gate_count output
201 std::string gates_per_opcode_str;
202 if (flags.include_gates_per_opcode) {
203 size_t i = 0;
204 for (size_t count : response.gates_per_opcode) {
205 if (i != 0) {
206 gates_per_opcode_str += ",";
207 }
208 gates_per_opcode_str += std::to_string(count);
209 i++;
210 }
211 }
212
213 // For now, we'll use the CircuitStats response which includes circuit statistics
214 // The num_acir_opcodes is not directly available from bytecode alone
215 auto result_string = format(
216 "{\n \"acir_opcodes\": ",
217 response.num_acir_opcodes,
218 ",\n \"circuit_size\": ",
219 response.num_gates,
220 (flags.include_gates_per_opcode ? format(",\n \"gates_per_opcode\": [", gates_per_opcode_str, "]") : ""),
221 "\n }");
222
223 functions_string = format(functions_string, result_string);
224 std::cout << format(functions_string, "\n]}");
225}
226
228 const std::filesystem::path& output_path,
229 const std::filesystem::path& vk_path)
230{
231 BB_BENCH_NAME("UltraHonkAPI::write_solidity_verifier");
232 // Read VK file
233 auto vk_bytes = read_vk_file(vk_path);
234
235 // Convert flags to ProofSystemSettings
237 .oracle_hash_type = flags.oracle_hash_type,
238 .disable_zk = flags.disable_zk,
239 .optimized_solidity_verifier = flags.optimized_solidity_verifier };
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
std::shared_ptr< Napi::ThreadSafeFunction > bytecode
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:219
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:23
#define info(...)
Definition log.hpp:93
#define vinfo(...)
Definition log.hpp:94
std::vector< uint8_t > get_bytecode(const std::string &bytecodePath)
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
std::string build_json_output(const std::vector< T > &fields, const std::string &file_kind, const API::Flags &flags, const std::string &vk_hash="")
Build JSON output string using msgpack serialization.
std::vector< uint8_t > read_vk_file(const std::filesystem::path &vk_path)
Read a verification key file with an actionable error message if not found.
Definition file_io.hpp:112
std::vector< uint8_t > read_file(const std::string &filename, size_t bytes=0)
Definition file_io.hpp:30
void write_file(const std::string &filename, std::vector< uint8_t > const &data)
Definition file_io.hpp:59
std::string bytes_to_hex_string(const std::vector< uint8_t > &bytes)
Convert bytes to a hex string with 0x prefix.
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 optimized_solidity_verifier
Definition api.hpp:27
bool write_vk
Definition api.hpp:21
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 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)