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
8#include "barretenberg/bbapi/generated/bb_types.hpp"
14
15namespace bb {
16
17namespace {
18
19void write_vk_outputs(const bbapi::wire::CircuitComputeVkResponse& vk_response,
20 const std::filesystem::path& output_dir,
21 const API::Flags& flags)
22{
23 if (flags.output_format == "json") {
24 auto fields = bbapi::uint256_vec_from_wire(vk_response.fields);
25 std::string json_content = VkJson::build(fields, bytes_to_hex_string(vk_response.hash), flags.scheme);
26 write_file(output_dir / "vk.json", std::vector<uint8_t>(json_content.begin(), json_content.end()));
27 info("VK (JSON) saved to ", output_dir / "vk.json");
28 } else {
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
36void write_proof_outputs(const bbapi::wire::CircuitProveResponse& prove_response,
37 const std::filesystem::path& output_dir,
38 const API::Flags& flags)
39{
40 if (flags.output_format == "json") {
41 std::string vk_hash = bytes_to_hex_string(prove_response.vk.hash);
42 auto proof_domain = bbapi::uint256_vec_from_wire(prove_response.proof);
43 auto pi_domain = bbapi::uint256_vec_from_wire(prove_response.public_inputs);
44 std::string proof_json = ProofJson::build(proof_domain, vk_hash, flags.scheme);
45 write_file(output_dir / "proof.json", std::vector<uint8_t>(proof_json.begin(), proof_json.end()));
46 info("Proof (JSON) saved to ", output_dir / "proof.json");
47
48 std::string pi_json = PublicInputsJson::build(pi_domain, flags.scheme);
49 write_file(output_dir / "public_inputs.json", std::vector<uint8_t>(pi_json.begin(), pi_json.end()));
50 info("Public inputs (JSON) saved to ", output_dir / "public_inputs.json");
51 } else {
52 auto pi_domain = bbapi::uint256_vec_from_wire(prove_response.public_inputs);
53 auto proof_domain = bbapi::uint256_vec_from_wire(prove_response.proof);
54 auto public_inputs_buf = to_buffer(pi_domain);
55 auto proof_buf = to_buffer(proof_domain);
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
64} // anonymous namespace
65
66bool UltraHonkAPI::check([[maybe_unused]] const Flags& flags,
67 [[maybe_unused]] const std::filesystem::path& bytecode_path,
68 [[maybe_unused]] const std::filesystem::path& witness_path)
69{
70 throw_or_abort("API function check_witness not implemented");
71 return false;
72}
73
74void UltraHonkAPI::prove(const Flags& flags,
75 const std::filesystem::path& bytecode_path,
76 const std::filesystem::path& witness_path,
77 const std::filesystem::path& vk_path,
78 const std::filesystem::path& output_dir)
79{
80 BB_BENCH_NAME("UltraHonkAPI::prove");
81 // Validate output directory
82 if (output_dir == "-") {
83 throw_or_abort("Stdout output is not supported. Please specify an output directory.");
84 }
85
86 bbapi::wire::ProofSystemSettings settings{ .ipa_accumulation = flags.ipa_accumulation,
87 .oracle_hash_type = flags.oracle_hash_type,
88 .disable_zk = flags.disable_zk };
89
90 auto bytecode = get_bytecode(bytecode_path);
91 auto witness = get_bytecode(witness_path);
92
93 std::vector<uint8_t> vk_bytes;
94 if (!vk_path.empty() && !flags.write_vk) {
95 vk_bytes = read_file(vk_path);
96 }
97
98 bbapi::BBApiRequest request;
99 auto response =
101 bbapi::wire::CircuitProve{
102 .circuit = bbapi::wire::CircuitInput{ .name = "circuit",
103 .bytecode = std::move(bytecode),
104 .verification_key = std::move(vk_bytes) },
105 .witness = std::move(witness),
106 .settings = std::move(settings),
107 });
108 write_proof_outputs(response, output_dir, flags);
109 if (flags.write_vk) {
110 write_vk_outputs(response.vk, output_dir, flags);
111 }
112}
113
114bool UltraHonkAPI::verify(const Flags& flags,
115 const std::filesystem::path& public_inputs_path,
116 const std::filesystem::path& proof_path,
117 const std::filesystem::path& vk_path)
118{
119 BB_BENCH_NAME("UltraHonkAPI::verify");
120
121 // Read and parse input files (auto-detect JSON vs binary format)
122 std::vector<uint256_t> public_inputs;
124 std::vector<uint8_t> vk_bytes;
125
126 auto public_inputs_content = read_file(public_inputs_path);
127 if (auto json = try_parse_json(public_inputs_content)) {
128 public_inputs = PublicInputsJson::parse(*json);
129 } else {
130 public_inputs = many_from_buffer_exact<uint256_t>(public_inputs_content, "UltraHonk public inputs file");
131 }
132
133 auto proof_content = read_file(proof_path);
134 if (auto json = try_parse_json(proof_content)) {
135 proof = ProofJson::parse(*json);
136 } else {
137 proof = many_from_buffer_exact<uint256_t>(proof_content, "UltraHonk proof file");
138 }
139
140 auto vk_content = read_file(vk_path);
141 if (auto json = try_parse_json(vk_content)) {
142 vk_bytes = VkJson::parse_to_bytes(*json);
143 } else {
144 vk_bytes = std::move(vk_content);
145 }
146
147 bbapi::wire::ProofSystemSettings settings{ .ipa_accumulation = flags.ipa_accumulation,
148 .oracle_hash_type = flags.oracle_hash_type,
149 .disable_zk = flags.disable_zk };
150
151 bbapi::BBApiRequest request;
152 auto response = bbapi::handle_circuit_verify(request,
153 bbapi::wire::CircuitVerify{
154 .verification_key = std::move(vk_bytes),
155 .public_inputs = bbapi::uint256_vec_to_wire(public_inputs),
156 .proof = bbapi::uint256_vec_to_wire(proof),
157 .settings = settings,
158 });
159
160 return response.verified;
161}
162
163bool UltraHonkAPI::prove_and_verify([[maybe_unused]] const Flags& flags,
164 [[maybe_unused]] const std::filesystem::path& bytecode_path,
165 [[maybe_unused]] const std::filesystem::path& witness_path)
166{
167 throw_or_abort("API function prove_and_verify not implemented");
168 return false;
169}
170
172 const std::filesystem::path& bytecode_path,
173 const std::filesystem::path& output_dir)
174{
175 BB_BENCH_NAME("UltraHonkAPI::write_vk");
176 // Validate output directory
177 if (output_dir == "-") {
178 throw_or_abort("Stdout output is not supported. Please specify an output directory.");
179 }
180
181 auto bytecode = get_bytecode(bytecode_path);
182
183 bbapi::wire::ProofSystemSettings settings{ .ipa_accumulation = flags.ipa_accumulation,
184 .oracle_hash_type = flags.oracle_hash_type,
185 .disable_zk = flags.disable_zk };
186
187 bbapi::BBApiRequest request;
188 auto response = bbapi::handle_circuit_compute_vk(
189 request,
190 bbapi::wire::CircuitComputeVk{
191 .circuit = bbapi::wire::CircuitInputNoVK{ .name = "circuit", .bytecode = std::move(bytecode) },
192 .settings = settings,
193 });
194
195 write_vk_outputs(response, output_dir, flags);
196}
197
198void UltraHonkAPI::gates([[maybe_unused]] const Flags& flags,
199 [[maybe_unused]] const std::filesystem::path& bytecode_path)
200{
201 BB_BENCH_NAME("UltraHonkAPI::gates");
202 // Get the bytecode directly
203 auto bytecode = get_bytecode(bytecode_path);
204
205 // All circuit reports will be built into the string below
206 std::string functions_string = "{\"functions\": [\n ";
207
208 // For now, treat the entire bytecode as a single circuit
209 // Convert flags to ProofSystemSettings
210 bbapi::wire::ProofSystemSettings settings{ .ipa_accumulation = flags.ipa_accumulation,
211 .oracle_hash_type = flags.oracle_hash_type,
212 .disable_zk = flags.disable_zk };
213
214 bbapi::BBApiRequest request;
215 auto response = bbapi::handle_circuit_stats(
216 request,
217 bbapi::wire::CircuitStats{
218 .circuit = bbapi::wire::CircuitInput{ .name = "circuit", .bytecode = bytecode, .verification_key = {} },
219 .include_gates_per_opcode = flags.include_gates_per_opcode,
220 .settings = settings,
221 });
222
223 vinfo("Calculated circuit size in gate_count: ", response.num_gates);
224
225 // Build individual circuit report to match original gate_count output
226 std::string gates_per_opcode_str;
227 if (flags.include_gates_per_opcode) {
228 size_t i = 0;
229 for (size_t count : response.gates_per_opcode) {
230 if (i != 0) {
231 gates_per_opcode_str += ",";
232 }
233 gates_per_opcode_str += std::to_string(count);
234 i++;
235 }
236 }
237
238 // For now, we'll use the CircuitStats response which includes circuit statistics
239 // The num_acir_opcodes is not directly available from bytecode alone
240 auto result_string = format(
241 "{\n \"acir_opcodes\": ",
242 response.num_acir_opcodes,
243 ",\n \"circuit_size\": ",
244 response.num_gates,
245 (flags.include_gates_per_opcode ? format(",\n \"gates_per_opcode\": [", gates_per_opcode_str, "]") : ""),
246 "\n }");
247
248 functions_string = format(functions_string, result_string);
249 std::cout << format(functions_string, "\n]}");
250}
251
253 const std::filesystem::path& output_path,
254 const std::filesystem::path& vk_path)
255{
256 BB_BENCH_NAME("UltraHonkAPI::write_solidity_verifier");
257 // Read VK file
258 auto vk_bytes = read_vk_file(vk_path);
259
260 bbapi::wire::ProofSystemSettings settings{ .ipa_accumulation = flags.ipa_accumulation,
261 .oracle_hash_type = flags.oracle_hash_type,
262 .disable_zk = flags.disable_zk,
263 .optimized_solidity_verifier = flags.optimized_solidity_verifier };
264
265 bbapi::BBApiRequest request;
267 request, bbapi::wire::CircuitWriteSolidityVerifier{ .verification_key = vk_bytes, .settings = settings });
268
269 // Write output
270 if (output_path == "-") {
271 std::cout << response.solidity_code;
272 } else {
273 write_file(output_path,
274 std::span<const uint8_t>(reinterpret_cast<const uint8_t*>(response.solidity_code.c_str()),
275 response.solidity_code.size()));
276 if (flags.disable_zk) {
277 info("Honk solidity verifier saved to ", output_path);
278 } else {
279 info("ZK Honk solidity verifier saved to ", output_path);
280 }
281 }
282}
283} // namespace bb
std::shared_ptr< Napi::ThreadSafeFunction > bytecode
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:264
Non-template handler declarations for the bb service.
Shared type definitions for the Barretenberg RPC API.
Wire <-> domain conversion helpers for the bbapi handlers.
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)
wire::CircuitProveResponse handle_circuit_prove(BBApiRequest &ctx, wire::CircuitProve &&cmd)
std::vector< Uint256 > uint256_vec_to_wire(const std::vector< bb::numeric::uint256_t > &d)
std::vector< bb::numeric::uint256_t > uint256_vec_from_wire(const std::vector< Uint256 > &w)
wire::CircuitInfoResponse handle_circuit_stats(BBApiRequest &ctx, wire::CircuitStats &&cmd)
wire::CircuitVerifyResponse handle_circuit_verify(BBApiRequest &ctx, wire::CircuitVerify &&cmd)
wire::CircuitComputeVkResponse handle_circuit_compute_vk(BBApiRequest &ctx, wire::CircuitComputeVk &&cmd)
wire::CircuitWriteSolidityVerifierResponse handle_circuit_write_solidity_verifier(BBApiRequest &ctx, wire::CircuitWriteSolidityVerifier &&cmd)
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
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:146
std::optional< nlohmann::json > try_parse_json(const std::vector< uint8_t > &content)
Try to parse file content as JSON.
std::vector< uint8_t > read_file(const std::string &filename, size_t bytes=0)
Definition file_io.hpp:31
void write_file(const std::string &filename, std::span< const uint8_t > data)
Definition file_io.hpp:101
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:28
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
static std::vector< uint256_t > parse(const nlohmann::json &json)
static std::string build(const std::vector< T > &fields, const std::string &vk_hash, const std::string &scheme)
static std::vector< uint256_t > parse(const nlohmann::json &json)
static std::string build(const std::vector< T > &fields, const std::string &scheme)
static std::vector< uint8_t > parse_to_bytes(const nlohmann::json &json)
static std::string build(const std::vector< T > &fields, const std::string &hash, const std::string &scheme)
void throw_or_abort(std::string const &err)