Skip to content

Commit f437cb8

Browse files
chore(bb): Add verification after proof generation in bbapi_ultrahonk
Add verification after proof generation in bbapi_ultrahonk
1 parent 2c6023a commit f437cb8

1 file changed

Lines changed: 53 additions & 43 deletions

File tree

barretenberg/cpp/src/barretenberg/bbapi/bbapi_ultra_honk.cpp

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -60,49 +60,6 @@ std::shared_ptr<ProverInstance_<Flavor>> _compute_prover_instance(std::vector<ui
6060

6161
return prover_instance;
6262
}
63-
template <typename Flavor, typename IO>
64-
CircuitProve::Response _prove(std::vector<uint8_t>&& bytecode,
65-
std::vector<uint8_t>&& witness,
66-
std::vector<uint8_t>&& vk_bytes)
67-
{
68-
using Proof = typename Flavor::Transcript::Proof;
69-
using VerificationKey = typename Flavor::VerificationKey;
70-
71-
auto prover_instance = _compute_prover_instance<Flavor, IO>(std::move(bytecode), std::move(witness));
72-
73-
// Create or deserialize VK
74-
std::shared_ptr<VerificationKey> vk;
75-
if (vk_bytes.empty()) {
76-
info("WARNING: computing verification key while proving. Pass in a precomputed vk for better performance.");
77-
vk = std::make_shared<VerificationKey>(prover_instance->get_precomputed());
78-
} else {
79-
validate_vk_size<VerificationKey>(vk_bytes);
80-
vk = std::make_shared<VerificationKey>(from_buffer<VerificationKey>(vk_bytes));
81-
}
82-
83-
// Construct proof
84-
UltraProver_<Flavor> prover{ prover_instance, vk };
85-
Proof full_proof = prover.construct_proof();
86-
87-
// Compute where to split (inner public inputs vs everything else)
88-
size_t num_public_inputs = prover.num_public_inputs();
89-
BB_ASSERT_GTE(num_public_inputs, IO::PUBLIC_INPUTS_SIZE, "Public inputs should contain the expected IO structure.");
90-
size_t num_inner_public_inputs = num_public_inputs - IO::PUBLIC_INPUTS_SIZE;
91-
92-
// Optimization: if vk not provided, include it in response
93-
CircuitComputeVk::Response vk_response;
94-
if (vk_bytes.empty()) {
95-
vk_response = { .bytes = to_buffer(*vk), .fields = vk_to_uint256_fields(*vk), .hash = to_buffer(vk->hash()) };
96-
}
97-
98-
// Split proof: inner public inputs at front, rest is the "proof"
99-
return { .public_inputs =
100-
std::vector<uint256_t>{ full_proof.begin(),
101-
full_proof.begin() + static_cast<std::ptrdiff_t>(num_inner_public_inputs) },
102-
.proof = std::vector<uint256_t>{ full_proof.begin() + static_cast<std::ptrdiff_t>(num_inner_public_inputs),
103-
full_proof.end() },
104-
.vk = std::move(vk_response) };
105-
}
10663

10764
template <typename Flavor, typename IO>
10865
bool _verify(const std::vector<uint8_t>& vk_bytes,
@@ -145,6 +102,59 @@ bool _verify(const std::vector<uint8_t>& vk_bytes,
145102
return verified;
146103
}
147104

105+
template <typename Flavor, typename IO>
106+
CircuitProve::Response _prove(std::vector<uint8_t>&& bytecode,
107+
std::vector<uint8_t>&& witness,
108+
std::vector<uint8_t>&& vk_bytes)
109+
{
110+
using Proof = typename Flavor::Transcript::Proof;
111+
using VerificationKey = typename Flavor::VerificationKey;
112+
113+
auto prover_instance = _compute_prover_instance<Flavor, IO>(std::move(bytecode), std::move(witness));
114+
115+
// Create or deserialize VK
116+
std::shared_ptr<VerificationKey> vk;
117+
if (vk_bytes.empty()) {
118+
info("WARNING: computing verification key while proving. Pass in a precomputed vk for better performance.");
119+
vk = std::make_shared<VerificationKey>(prover_instance->get_precomputed());
120+
} else {
121+
validate_vk_size<VerificationKey>(vk_bytes);
122+
vk = std::make_shared<VerificationKey>(from_buffer<VerificationKey>(vk_bytes));
123+
}
124+
125+
// Construct proof
126+
UltraProver_<Flavor> prover{ prover_instance, vk };
127+
Proof full_proof = prover.construct_proof();
128+
129+
// Compute where to split (inner public inputs vs everything else)
130+
size_t num_public_inputs = prover.num_public_inputs();
131+
BB_ASSERT_GTE(num_public_inputs, IO::PUBLIC_INPUTS_SIZE, "Public inputs should contain the expected IO structure.");
132+
size_t num_inner_public_inputs = num_public_inputs - IO::PUBLIC_INPUTS_SIZE;
133+
134+
// Optimization: if vk not provided, include it in response
135+
CircuitComputeVk::Response vk_response;
136+
if (vk_bytes.empty()) {
137+
vk_response = { .bytes = to_buffer(*vk), .fields = vk_to_uint256_fields(*vk), .hash = to_buffer(vk->hash()) };
138+
}
139+
140+
// Split proof: inner public inputs at front, rest is the "proof"
141+
CircuitProve::Response response{
142+
.public_inputs =
143+
std::vector<uint256_t>{ full_proof.begin(),
144+
full_proof.begin() + static_cast<std::ptrdiff_t>(num_inner_public_inputs) },
145+
.proof = std::vector<uint256_t>{ full_proof.begin() + static_cast<std::ptrdiff_t>(num_inner_public_inputs),
146+
full_proof.end() },
147+
.vk = std::move(vk_response)
148+
};
149+
150+
// Sanity-check the generated proof
151+
if (!_verify<Flavor, IO>(to_buffer(*vk), response.public_inputs, response.proof)) {
152+
throw_or_abort("Failed to verify the generated proof!");
153+
}
154+
155+
return response;
156+
}
157+
148158
CircuitProve::Response CircuitProve::execute(BB_UNUSED const BBApiRequest& request) &&
149159
{
150160
BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);

0 commit comments

Comments
 (0)