Skip to content

Commit 99549bc

Browse files
authored
feat: merge-train/barretenberg (#16599)
See [merge-train-readme.md](https://github.com/AztecProtocol/aztec-packages/blob/next/.github/workflows/merge-train-readme.md). This is a merge-train.
2 parents 4b3dd11 + d63c09f commit 99549bc

15 files changed

+106
-87
lines changed

barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp

Lines changed: 65 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -104,75 +104,62 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks(
104104
{
105105
using MergeCommitments = Goblin::MergeRecursiveVerifier::InputCommitments;
106106

107-
// Witness commitments and public inputs corresponding to the incoming instance
108-
WitnessCommitments witness_commitments;
109107
// The pairing points produced by the verification of the decider proof
110108
PairingPoints decider_pairing_points;
111-
std::vector<StdlibFF> public_inputs;
112109

113110
// Input commitments to be passed to the merge recursive verification
114-
MergeCommitments merge_commitments;
115-
merge_commitments.T_prev_commitments = T_prev_commitments;
111+
MergeCommitments merge_commitments{ .T_prev_commitments = T_prev_commitments };
112+
113+
auto verifier_instance =
114+
std::make_shared<RecursiveDeciderVerificationKey>(&circuit, verifier_inputs.honk_vk_and_hash);
115+
116116
std::shared_ptr<ClientIVC::RecursiveDeciderVerificationKey> output_stdlib_verifier_accumulator;
117117
std::optional<StdlibFF> prev_accum_hash = std::nullopt;
118118
// The decider proof exists if the tail kernel has been accumulated
119119
bool is_hiding_kernel = !decider_proof.empty();
120120

121121
switch (verifier_inputs.type) {
122-
case QUEUE_TYPE::PG_TAIL:
123-
case QUEUE_TYPE::PG: {
124-
BB_ASSERT_NEQ(input_stdlib_verifier_accumulator, nullptr);
125-
if (verifier_inputs
126-
.is_kernel) { // this is what I'm using to determine if this is the first circuit we're folding...
127-
// Fiat-Shamir the accumulator.
128-
prev_accum_hash =
129-
input_stdlib_verifier_accumulator->hash_through_transcript("", *accumulation_recursive_transcript);
130-
accumulation_recursive_transcript->add_to_hash_buffer("accum_hash", *prev_accum_hash);
131-
info("Previous accumulator hash in PG rec verifier: ", *prev_accum_hash);
132-
}
133-
// Perform folding recursive verification to update the verifier accumulator
134-
FoldingRecursiveVerifier verifier{ &circuit,
135-
input_stdlib_verifier_accumulator,
136-
{ verifier_inputs.honk_vk_and_hash },
137-
accumulation_recursive_transcript };
138-
output_stdlib_verifier_accumulator =
139-
verifier.verify_folding_proof(verifier_inputs.proof); // WORKTODO: connect this to previous/next accumulator
140-
141-
witness_commitments = std::move(verifier.keys_to_fold[1]->witness_commitments);
142-
public_inputs = std::move(verifier.public_inputs);
143-
144-
break;
145-
}
146-
147122
case QUEUE_TYPE::OINK: {
148123
BB_ASSERT_EQ(input_stdlib_verifier_accumulator, nullptr);
149-
// Construct an incomplete stdlib verifier accumulator from the corresponding stdlib verification key
150-
output_stdlib_verifier_accumulator =
151-
std::make_shared<RecursiveDeciderVerificationKey>(&circuit, verifier_inputs.honk_vk_and_hash);
152124

153125
// Perform oink recursive verification to complete the initial verifier accumulator
154-
OinkRecursiveVerifier verifier{ &circuit,
155-
output_stdlib_verifier_accumulator,
156-
accumulation_recursive_transcript };
126+
OinkRecursiveVerifier verifier{ &circuit, verifier_instance, accumulation_recursive_transcript };
157127
verifier.verify_proof(verifier_inputs.proof);
158128

129+
output_stdlib_verifier_accumulator = verifier_instance;
159130
output_stdlib_verifier_accumulator->target_sum = StdlibFF::from_witness_index(&circuit, circuit.zero_idx);
160131
output_stdlib_verifier_accumulator->gate_challenges.assign(
161132
CONST_PG_LOG_N, StdlibFF::from_witness_index(&circuit, circuit.zero_idx));
162133

163-
witness_commitments = std::move(output_stdlib_verifier_accumulator->witness_commitments);
164-
public_inputs = std::move(verifier.public_inputs);
165-
166134
// T_prev = 0 in the first recursive verification
167135
merge_commitments.T_prev_commitments = stdlib::recursion::honk::empty_ecc_op_tables(circuit);
168136

169137
break;
170138
}
139+
case QUEUE_TYPE::PG:
140+
case QUEUE_TYPE::PG_TAIL: {
141+
BB_ASSERT_NEQ(input_stdlib_verifier_accumulator, nullptr);
142+
if (verifier_inputs
143+
.is_kernel) { // this is what I'm using to determine if this is the first circuit we're folding...
144+
// Fiat-Shamir the accumulator.
145+
prev_accum_hash =
146+
input_stdlib_verifier_accumulator->hash_through_transcript("", *accumulation_recursive_transcript);
147+
accumulation_recursive_transcript->add_to_hash_buffer("accum_hash", *prev_accum_hash);
148+
info("Previous accumulator hash in PG rec verifier: ", *prev_accum_hash);
149+
}
150+
// Perform folding recursive verification to update the verifier accumulator
151+
FoldingRecursiveVerifier verifier{
152+
&circuit, input_stdlib_verifier_accumulator, verifier_instance, accumulation_recursive_transcript
153+
};
154+
output_stdlib_verifier_accumulator =
155+
verifier.verify_folding_proof(verifier_inputs.proof); // WORKTODO: connect this to previous/next accumulator
156+
157+
break;
158+
}
171159
case QUEUE_TYPE::PG_FINAL: {
172160
BB_ASSERT_NEQ(input_stdlib_verifier_accumulator, nullptr);
173161
BB_ASSERT_EQ(stdlib_verification_queue.size(), size_t(1));
174-
auto stdlib_proof = verifier_inputs.proof;
175-
auto stdlib_vk_and_hash = verifier_inputs.honk_vk_and_hash;
162+
176163
// Note: reinstate this.
177164
// BB_ASSERT_EQ(num_circuits_accumulated,
178165
// num_circuits - 1,
@@ -184,6 +171,7 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks(
184171
// Propagate the public inputs of the tail kernel by converting them to public inputs of the hiding circuit.
185172
auto num_public_inputs = static_cast<size_t>(honk_vk->num_public_inputs);
186173
num_public_inputs -= KernelIO::PUBLIC_INPUTS_SIZE; // exclude fixed kernel_io public inputs
174+
auto stdlib_proof = verifier_inputs.proof;
187175
for (size_t i = 0; i < num_public_inputs; i++) {
188176
stdlib_proof[i].set_public();
189177
}
@@ -195,16 +183,11 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks(
195183
info("Previous accumulator hash in PG rec verifier: ", *prev_accum_hash);
196184
// Perform recursive folding verification of the last folding proof
197185
FoldingRecursiveVerifier folding_verifier{
198-
&circuit, input_stdlib_verifier_accumulator, { stdlib_vk_and_hash }, accumulation_recursive_transcript
186+
&circuit, input_stdlib_verifier_accumulator, verifier_instance, accumulation_recursive_transcript
199187
};
200188
auto recursive_verifier_native_accum = folding_verifier.verify_folding_proof(verifier_inputs.proof);
201189
verification_queue.clear();
202190

203-
// // Get the completed decider verification key corresponding to the tail kernel from the folding verifier
204-
public_inputs = folding_verifier.public_inputs;
205-
206-
witness_commitments = folding_verifier.keys_to_fold[1]->witness_commitments;
207-
208191
// Perform recursive decider verification
209192
DeciderRecursiveVerifier decider{ &circuit, recursive_verifier_native_accum };
210193
BB_ASSERT_EQ(decider_proof.empty(), false, "Decider proof is empty!");
@@ -219,6 +202,10 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks(
219202
}
220203
}
221204

205+
// Extract the witness commitments and public inputs from the incoming verifier instance
206+
WitnessCommitments witness_commitments = std::move(verifier_instance->witness_commitments);
207+
std::vector<StdlibFF> public_inputs = std::move(verifier_instance->public_inputs);
208+
222209
PairingPoints nested_pairing_points; // to be extracted from public inputs of app or kernel proof just verified
223210

224211
if (verifier_inputs.is_kernel) {
@@ -414,14 +401,14 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr<MegaVer
414401
prover_accumulation_transcript = std::make_shared<Transcript>();
415402
}
416403

417-
VerifierInputs queue_entry{ .honk_vk = honk_vk,
418-
// first circuit accumulated should be an app
419-
.is_kernel = is_kernel };
404+
// make a copy of the prover_accumulation_transcript for the verifier to use
405+
auto verifier_transcript =
406+
Transcript::convert_prover_transcript_to_verifier_transcript(prover_accumulation_transcript);
407+
408+
VerifierInputs queue_entry{ .honk_vk = honk_vk, .is_kernel = is_kernel };
420409
if (num_circuits_accumulated == 0) { // First circuit in the IVC
421-
BB_ASSERT_EQ(queue_entry.is_kernel, false, "First circuit accumulated is always be an app");
410+
BB_ASSERT_EQ(queue_entry.is_kernel, false, "First circuit accumulated must always be an app");
422411
// For first circuit in the IVC, use oink to complete the decider proving key and generate an oink proof
423-
auto oink_verifier_transcript =
424-
Transcript::convert_prover_transcript_to_verifier_transcript(prover_accumulation_transcript);
425412
MegaOinkProver oink_prover{ proving_key, honk_vk, prover_accumulation_transcript };
426413
vinfo("computing oink proof...");
427414
oink_prover.prove();
@@ -430,26 +417,17 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr<MegaVer
430417

431418
fold_output.accumulator = proving_key; // initialize the prover accum with the completed key
432419

433-
auto decider_vk = std::make_shared<DeciderVerificationKey>(honk_vk);
434-
oink_verifier_transcript->load_proof(oink_proof);
435-
OinkVerifier<Flavor> oink_verifier{ decider_vk, oink_verifier_transcript };
436-
oink_verifier.verify();
437-
native_verifier_accum = decider_vk;
438-
native_verifier_accum->gate_challenges = std::vector<FF>(CONST_PG_LOG_N, 0);
439-
440420
queue_entry.type = QUEUE_TYPE::OINK;
441421
queue_entry.proof = oink_proof;
442422
} else if (num_circuits_accumulated == num_circuits - 1) {
443-
queue_entry.type = QUEUE_TYPE::MEGA;
444423
// construct the mega proof of the hiding circuit
445424
auto mega_proof = prove_hiding_circuit(circuit);
425+
426+
queue_entry.type = QUEUE_TYPE::MEGA;
446427
queue_entry.proof = mega_proof;
447428
} else { // Otherwise, fold the new key into the accumulator
448429
vinfo("computing folding proof");
449430
auto vk = std::make_shared<DeciderVerificationKey_<Flavor>>(honk_vk);
450-
// make a copy of the prover_accumulation_transcript for the verifier to use
451-
auto verifier_accumulation_transcript =
452-
Transcript::convert_prover_transcript_to_verifier_transcript(prover_accumulation_transcript);
453431
// Only fiat shamir if this is a kernel with the assumption that kernels are always the first being recursively
454432
// verified.
455433
if (is_kernel) {
@@ -464,14 +442,6 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr<MegaVer
464442
trace_usage_tracker);
465443
fold_output = folding_prover.prove();
466444
vinfo("constructed folding proof");
467-
if (is_kernel) {
468-
// Fiat-Shamir the verifier accumulator
469-
FF accum_hash = native_verifier_accum->hash_through_transcript("", *verifier_accumulation_transcript);
470-
verifier_accumulation_transcript->add_to_hash_buffer("accum_hash", accum_hash);
471-
info("Accumulator hash in PG verifier: ", accum_hash);
472-
}
473-
FoldingVerifier folding_verifier({ native_verifier_accum, vk }, verifier_accumulation_transcript);
474-
native_verifier_accum = folding_verifier.verify_folding_proof(fold_output.proof);
475445

476446
if (num_circuits_accumulated == num_circuits - 2) {
477447
// we are folding in the "Tail" kernel, so the verification_queue entry should have type PG_FINAL
@@ -490,6 +460,7 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr<MegaVer
490460

491461
// Construct merge proof for the present circuit (skipped for hiding since merge proof constructed in goblin prove)
492462
if (num_circuits_accumulated != num_circuits - 1) {
463+
update_native_verifier_accumulator(queue_entry, verifier_transcript);
493464
goblin.prove_merge(prover_accumulation_transcript);
494465
}
495466

@@ -726,4 +697,26 @@ ClientIVC::VerificationKey ClientIVC::get_vk() const
726697
return { honk_vk, std::make_shared<ECCVMVerificationKey>(), std::make_shared<TranslatorVerificationKey>() };
727698
}
728699

700+
void ClientIVC::update_native_verifier_accumulator(const VerifierInputs& queue_entry,
701+
const std::shared_ptr<Transcript>& verifier_transcript)
702+
{
703+
auto decider_vk = std::make_shared<DeciderVerificationKey>(queue_entry.honk_vk);
704+
if (queue_entry.type == QUEUE_TYPE::OINK) {
705+
verifier_transcript->load_proof(queue_entry.proof);
706+
OinkVerifier<Flavor> oink_verifier{ decider_vk, verifier_transcript };
707+
oink_verifier.verify();
708+
native_verifier_accum = decider_vk;
709+
native_verifier_accum->gate_challenges = std::vector<FF>(CONST_PG_LOG_N, 0);
710+
} else {
711+
if (queue_entry.is_kernel) {
712+
// Fiat-Shamir the verifier accumulator
713+
FF accum_hash = native_verifier_accum->hash_through_transcript("", *verifier_transcript);
714+
verifier_transcript->add_to_hash_buffer("accum_hash", accum_hash);
715+
info("Accumulator hash in PG verifier: ", accum_hash);
716+
}
717+
FoldingVerifier folding_verifier({ native_verifier_accum, decider_vk }, verifier_transcript);
718+
native_verifier_accum = folding_verifier.verify_folding_proof(queue_entry.proof);
719+
}
720+
}
721+
729722
} // namespace bb

barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,16 @@ class ClientIVC {
284284
HonkProof decider_prove();
285285

286286
VerificationKey get_vk() const;
287+
288+
private:
289+
/**
290+
* @brief Update the native verifier accumulator based on the provided queue entry and transcript.
291+
*
292+
* @param queue_entry The verifier inputs from the queue.
293+
* @param verifier_transcript Verifier transcript corresponding to the prover transcript.
294+
*/
295+
void update_native_verifier_accumulator(const VerifierInputs& queue_entry,
296+
const std::shared_ptr<Transcript>& verifier_transcript);
287297
};
288298

289299
} // namespace bb

barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ void ProtogalaxyVerifier_<DeciderVerificationKeys>::run_oink_verifier_on_each_in
2929
domain_separator = std::to_string(1);
3030
OinkVerifier<Flavor> oink_verifier{ key, transcript, domain_separator + '_' };
3131
oink_verifier.verify();
32-
public_inputs = std::move(oink_verifier.public_inputs);
3332
}
3433

3534
template <typename FF, size_t NUM>

barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ template <class DeciderVerificationKeys> class ProtogalaxyVerifier_ {
2828

2929
DeciderVerificationKeys keys_to_fold;
3030

31-
std::vector<FF> public_inputs; // extracted from the incoming instance
32-
3331
std::shared_ptr<Transcript> transcript = std::make_shared<Transcript>();
3432

3533
ProtogalaxyVerifier_(const std::vector<std::shared_ptr<DeciderVK>>& keys,

barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ template <typename Flavor> void OinkRecursiveVerifier_<Flavor>::verify()
5959

6060
size_t num_public_inputs =
6161
static_cast<size_t>(static_cast<uint32_t>(decider_vk->vk_and_hash->vk->num_public_inputs.get_value()));
62+
std::vector<FF> public_inputs;
6263
for (size_t i = 0; i < num_public_inputs; ++i) {
6364
public_inputs.emplace_back(
6465
transcript->template receive_from_prover<FF>(domain_separator + "public_input_" + std::to_string(i)));
@@ -125,6 +126,7 @@ template <typename Flavor> void OinkRecursiveVerifier_<Flavor>::verify()
125126
RelationParameters<FF>{ eta, eta_two, eta_three, beta, gamma, public_input_delta };
126127
decider_vk->witness_commitments = std::move(commitments);
127128
decider_vk->alphas = std::move(alphas);
129+
decider_vk->public_inputs = std::move(public_inputs);
128130
decider_vk->is_complete = true; // instance has been completely populated
129131
}
130132

barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ template <typename Flavor> class OinkRecursiveVerifier_ {
6262
void verify_proof(const OinkProof& proof);
6363

6464
std::shared_ptr<RecursiveDeciderVK> decider_vk;
65-
std::vector<FF> public_inputs;
6665
Builder* builder;
6766
std::shared_ptr<Transcript> transcript = std::make_shared<Transcript>();
6867
std::string domain_separator; // used in PG to distinguish between verification_keys in transcript

barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ UltraRecursiveVerifier_<Flavor>::Output UltraRecursiveVerifier_<Flavor>::verify_
6666
transcript->load_proof(honk_proof);
6767
OinkVerifier oink_verifier{ builder, key, transcript };
6868
oink_verifier.verify();
69-
const std::vector<FF>& public_inputs = oink_verifier.public_inputs;
69+
const std::vector<FF>& public_inputs = key->public_inputs;
7070

7171
VerifierCommitments commitments{ key->vk_and_hash->vk, key->witness_commitments };
7272
static constexpr size_t VIRTUAL_LOG_N = Flavor::NativeFlavor::VIRTUAL_LOG_N;

barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ void ProtogalaxyRecursiveVerifier_<DeciderVerificationKeys>::run_oink_verifier_o
3131
domain_separator = std::to_string(1);
3232
OinkRecursiveVerifier_<Flavor> oink_verifier{ builder, key, transcript, domain_separator + '_' };
3333
oink_verifier.verify();
34-
public_inputs = std::move(oink_verifier.public_inputs);
3534
}
3635

3736
template <class DeciderVerificationKeys>

barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ template <class DeciderVerificationKeys> class ProtogalaxyRecursiveVerifier_ {
3232

3333
DeciderVerificationKeys keys_to_fold;
3434

35-
std::vector<FF> public_inputs; // extracted from the incoming instance
36-
3735
std::shared_ptr<Transcript> transcript = std::make_shared<Transcript>();
3836

3937
ProtogalaxyRecursiveVerifier_(Builder* builder,
@@ -44,6 +42,14 @@ template <class DeciderVerificationKeys> class ProtogalaxyRecursiveVerifier_ {
4442
, keys_to_fold(DeciderVerificationKeys(builder, accumulator, vk_and_hashs))
4543
, transcript(transcript) {};
4644

45+
ProtogalaxyRecursiveVerifier_(Builder* builder,
46+
const std::shared_ptr<DeciderVK>& accumulator,
47+
const std::shared_ptr<DeciderVK>& incoming_instance,
48+
const std::shared_ptr<Transcript>& transcript)
49+
: builder(builder)
50+
, keys_to_fold(DeciderVerificationKeys(builder, accumulator, incoming_instance))
51+
, transcript(transcript) {};
52+
4753
/**
4854
* @brief Process the public data ϕ for the decider verification keys to be folded.
4955
*/

barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_key.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ template <IsRecursiveFlavor Flavor> class RecursiveDeciderVerificationKey_ {
3636

3737
std::shared_ptr<VKAndHash> vk_and_hash;
3838

39-
bool is_complete = false; // whether this instance has been completely populated
39+
bool is_complete = false; // whether this instance has been completely populated
40+
std::vector<FF> public_inputs; // to be extracted from the corresponding proof
4041

4142
// An array {1, α₁, …, αₖ}, where k = NUM_SUBRELATIONS - 1.
4243
SubrelationSeparators alphas;

0 commit comments

Comments
 (0)