Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
api_ultra_honk.test.cpp
Go to the documentation of this file.
1#include "api_ultra_honk.hpp"
11#include <chrono>
12#include <cstddef>
13#include <cstdlib>
14#include <filesystem>
15#include <gtest/gtest.h>
16#include <math.h>
17#include <sstream>
18#include <string_view>
19
20namespace bb {
21std::vector<uint8_t> compress(const std::vector<uint8_t>& input);
22std::vector<uint8_t> decompress(const void* bytes, size_t size);
23} // namespace bb
24
25using namespace bb;
26
27namespace {
28// Create a unique temporary directory for each test run
29// Uniqueness needed because tests are run in parallel and write to same file names.
30std::filesystem::path get_test_dir(const std::string_view& test_name)
31{
32 std::filesystem::path temp_dir = "tmp_api_ultra_honk_test";
33 std::filesystem::create_directories(temp_dir);
34 std::filesystem::create_directories(temp_dir / test_name);
35 return temp_dir / test_name;
36}
37
38// Create test data
39std::pair<std::filesystem::path, std::filesystem::path> create_test_circuit_files(const std::filesystem::path& test_dir)
40{
41 auto [bytecode, witness] = acir_bincode_mocks::create_simple_circuit_bytecode();
42
43 auto bytecode_path = test_dir / "circuit.gz";
44 auto witness_path = test_dir / "witness.gz";
45
46 write_file(bytecode_path, bb::compress(bytecode));
47 write_file(witness_path, bb::compress(witness));
48
49 return { bytecode_path, witness_path };
50}
51
52} // namespace
53
54class ApiUltraHonkTest : public ::testing::Test {
55 protected:
57
58 void SetUp() override
59 {
60 const auto* info = ::testing::UnitTest::GetInstance()->current_test_info();
61 test_dir = get_test_dir(info->name());
62 }
63
64 void TearDown() override
65 {
66 if (std::filesystem::exists(test_dir)) {
67 std::filesystem::remove_all(test_dir);
68 }
69 }
70
71 std::filesystem::path test_dir;
72};
73
74TEST_F(ApiUltraHonkTest, ProveAndVerify)
75{
76 auto [bytecode_path, witness_path] = create_test_circuit_files(test_dir);
77
78 API::Flags flags;
79 flags.output_format = "bytes";
80 flags.oracle_hash_type = "poseidon2"; // Set default oracle hash type
81
82 UltraHonkAPI api;
83
84 // Generate VK first
85 auto vk_output_path = test_dir / "vk";
86 std::filesystem::create_directories(vk_output_path);
87 api.write_vk(flags, bytecode_path, vk_output_path);
88 EXPECT_TRUE(std::filesystem::exists(vk_output_path / "vk"));
89
90 // Generate proof
91 auto proof_output_dir = test_dir / "proof";
92 std::filesystem::create_directories(proof_output_dir);
93 api.prove(flags, bytecode_path, witness_path, vk_output_path / "vk", proof_output_dir);
94
95 // Check that proof files were created
96 EXPECT_TRUE(std::filesystem::exists(proof_output_dir / "proof"));
97 EXPECT_TRUE(std::filesystem::exists(proof_output_dir / "public_inputs"));
98
99 // Verify the proof
100 bool verified =
101 api.verify(flags, proof_output_dir / "public_inputs", proof_output_dir / "proof", vk_output_path / "vk");
102 EXPECT_TRUE(verified);
103}
104
105TEST_F(ApiUltraHonkTest, ProveWithWriteVk)
106{
107 auto [bytecode_path, witness_path] = create_test_circuit_files(test_dir);
108
109 API::Flags flags;
110 flags.output_format = "bytes_and_fields"; // Test both output formats
111 flags.oracle_hash_type = "poseidon2";
112 flags.write_vk = true;
113
114 UltraHonkAPI api;
115
116 // Generate proof with write_vk flag (will compute and write VK)
117 auto proof_output_dir = test_dir / "proof";
118 std::filesystem::create_directories(proof_output_dir);
119 api.prove(flags, bytecode_path, witness_path, "", proof_output_dir);
120
121 // Check that proof and VK files were created
122 EXPECT_TRUE(std::filesystem::exists(proof_output_dir / "proof"));
123 EXPECT_TRUE(std::filesystem::exists(proof_output_dir / "public_inputs"));
124 EXPECT_TRUE(std::filesystem::exists(proof_output_dir / "vk"));
125 EXPECT_TRUE(std::filesystem::exists(proof_output_dir / "vk_hash"));
126 EXPECT_TRUE(std::filesystem::exists(proof_output_dir / "vk_fields.json"));
127 EXPECT_TRUE(std::filesystem::exists(proof_output_dir / "vk_hash_fields.json"));
128
129 // Verify the proof
130 bool verified =
131 api.verify(flags, proof_output_dir / "public_inputs", proof_output_dir / "proof", proof_output_dir / "vk");
132 EXPECT_TRUE(verified);
133}
134
135TEST_F(ApiUltraHonkTest, ProveAndVerifyWithFields)
136{
137 auto [bytecode_path, witness_path] = create_test_circuit_files(test_dir);
138
139 // First generate VK in bytes format for the prove step
140 API::Flags vk_flags;
141 vk_flags.output_format = "bytes";
142 vk_flags.oracle_hash_type = "poseidon2";
143
144 UltraHonkAPI api;
145
146 auto vk_output_path = test_dir / "vk";
147 std::filesystem::create_directories(vk_output_path);
148 api.write_vk(vk_flags, bytecode_path, vk_output_path);
149 EXPECT_TRUE(std::filesystem::exists(vk_output_path / "vk"));
150
151 // Now test fields format for proof generation
152 API::Flags flags;
153 flags.output_format = "fields";
154 flags.oracle_hash_type = "poseidon2";
155
156 // Generate proof with fields output
157 auto proof_output_dir = test_dir / "proof";
158 std::filesystem::create_directories(proof_output_dir);
159 api.prove(flags, bytecode_path, witness_path, vk_output_path / "vk", proof_output_dir);
160
161 // Check that proof field files were created
162 EXPECT_TRUE(std::filesystem::exists(proof_output_dir / "proof_fields.json"));
163 EXPECT_TRUE(std::filesystem::exists(proof_output_dir / "public_inputs_fields.json"));
164}
165
166TEST_F(ApiUltraHonkTest, ProveWithDifferentSettings)
167{
168 auto [bytecode_path, witness_path] = create_test_circuit_files(test_dir);
169
170 // Test different oracle hash types
171 const std::vector<std::pair<std::string, bool>> test_cases = { { "poseidon2",
172 false }, // oracle_hash_type, disable_zk
173 { "poseidon2", true },
174 { "keccak", false },
175 { "keccak", true } };
176
177 for (const auto& [oracle_hash_type, disable_zk] : test_cases) {
178 API::Flags flags;
179 flags.output_format = "bytes";
180 flags.oracle_hash_type = oracle_hash_type;
181 flags.disable_zk = disable_zk;
182 flags.write_vk = true;
183
184 auto case_dir = test_dir / (oracle_hash_type + "_" + (disable_zk ? "no_zk" : "zk"));
185 std::filesystem::create_directories(case_dir);
186
187 UltraHonkAPI api;
188
189 // Generate proof
190 api.prove(flags, bytecode_path, witness_path, "", case_dir);
191
192 // Verify the proof
193 bool verified = api.verify(flags, case_dir / "public_inputs", case_dir / "proof", case_dir / "vk");
194 EXPECT_TRUE(verified) << "Failed with oracle_hash_type=" << oracle_hash_type << ", disable_zk=" << disable_zk;
195 }
196}
197
199{
200 auto [bytecode_path, witness_path] = create_test_circuit_files(test_dir);
201
202 // Smoke test fields format (no real verification)
203 {
204 API::Flags flags;
205 flags.output_format = "fields";
206 flags.oracle_hash_type = "poseidon2";
207
208 UltraHonkAPI api;
209 api.write_vk(flags, bytecode_path, test_dir);
210
211 EXPECT_TRUE(std::filesystem::exists(test_dir / "vk_fields.json"));
212 EXPECT_TRUE(std::filesystem::exists(test_dir / "vk_hash_fields.json"));
213
214 EXPECT_FALSE(std::filesystem::exists(test_dir / "vk"));
215 EXPECT_FALSE(std::filesystem::exists(test_dir / "vk_hash"));
216 }
217
218 // Test with bytes format, simple vk recalculation
219 {
220 API::Flags flags;
221 flags.output_format = "bytes";
222 flags.oracle_hash_type = "poseidon2";
223
224 UltraHonkAPI api;
225 api.write_vk(flags, bytecode_path, test_dir);
226
227 // Test against bbapi::CircuitComputeVk
228 auto bytecode = read_file(bytecode_path);
229 auto expected_vk =
230 bbapi::CircuitComputeVk({ .circuit = { .bytecode = bb::decompress(bytecode.data(), bytecode.size()) },
231 .settings = { .oracle_hash_type = flags.oracle_hash_type } })
232 .execute();
233
234 info("after write_vk, expected_vk size: {}", expected_vk.bytes.size());
235 EXPECT_EQ(expected_vk.bytes, read_file(test_dir / "vk"));
236 EXPECT_EQ(expected_vk.hash, read_file(test_dir / "vk_hash"));
237 }
238}
239
240// NOTE: very light test
241TEST_F(ApiUltraHonkTest, GatesWithOpcodesSmokeTest)
242{
243 auto [bytecode_path, witness_path] = create_test_circuit_files(test_dir);
244
245 // Capture stdout
246 testing::internal::CaptureStdout();
247
248 API::Flags flags;
249 flags.oracle_hash_type = "poseidon2";
250 flags.include_gates_per_opcode = true;
251 UltraHonkAPI api;
252 api.gates(flags, bytecode_path);
253
254 std::string output = testing::internal::GetCapturedStdout();
255
256 // Check that output contains per-opcode information
257 EXPECT_TRUE(output.find("gates_per_opcode") != std::string::npos);
258}
TEST_F(ApiUltraHonkTest, ProveAndVerify)
UltraHonk-specific command definitions for the Barretenberg RPC API.
void TearDown() override
static void SetUpTestSuite()
std::filesystem::path test_dir
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
void gates(const Flags &flags, const std::filesystem::path &bytecode_path) override
void info(Args... args)
Definition log.hpp:70
std::pair< std::vector< uint8_t >, std::vector< uint8_t > > create_simple_circuit_bytecode()
Helper function to create a minimal circuit bytecode and witness for testing.
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
Entry point for Barretenberg command-line interface.
std::vector< uint8_t > compress(const std::vector< uint8_t > &input)
std::vector< uint8_t > decompress(const void *bytes, size_t size)
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
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
bool include_gates_per_opcode
Definition api.hpp:24
bool write_vk
Definition api.hpp:23
bool disable_zk
Definition api.hpp:13
std::string oracle_hash_type
Definition api.hpp:19
std::string output_format
Definition api.hpp:20