Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
118 commits
Select commit Hold shift + click to select a range
4bc2037
[empty] Start merge-train. Choo choo.
Jul 4, 2025
07532e6
Merge branch 'next' into merge-train/barretenberg
Jul 4, 2025
57c7aac
Merge branch 'next' into merge-train/barretenberg
Jul 4, 2025
e261704
chore: stdlib bool internal audit (#15070)
iakovenkos Jul 4, 2025
f3526c9
feat: improve Shplonk api (#15422)
federicobarbacovi Jul 4, 2025
fa5e1d4
Merge branch 'next' into merge-train/barretenberg
Jul 4, 2025
11769c5
Merge branch 'next' into merge-train/barretenberg
Jul 4, 2025
ea1b864
Merge branch 'next' into merge-train/barretenberg
Jul 4, 2025
8a9fcf5
fix(merge-train): don't queue merge if merge-train failed queue, pass…
ludamad Jul 4, 2025
6078b94
chore: nuke bit array (#15522)
iakovenkos Jul 4, 2025
3330e1c
chore: remove template parameters (#15530)
iakovenkos Jul 4, 2025
a0d7e8b
Merge branch 'next' into merge-train/barretenberg
Jul 4, 2025
7c9bf78
Merge branch 'next' into merge-train/barretenberg
Jul 4, 2025
1a71de0
Merge branch 'next' into merge-train/barretenberg
Jul 4, 2025
480a06b
Merge branch 'next' into merge-train/barretenberg
Jul 5, 2025
21e4a81
Merge branch 'next' into merge-train/barretenberg
Jul 5, 2025
c430496
Merge branch 'next' into merge-train/barretenberg
Jul 5, 2025
6bf35ca
chore: no PK (#15386)
ledwards2225 Jul 5, 2025
1f9bbd9
Merge branch 'next' into merge-train/barretenberg
Jul 7, 2025
2a31570
chore!: Correct public inputs propagation in the tube (#15547)
ledwards2225 Jul 7, 2025
fa4f63a
chore: use `batch_invert` in native IPA verifier (#15557)
notnotraju Jul 8, 2025
04045ba
chore: Move `stdlib::uint_plookup` to `stdlib::uint` (#15460)
suyash67 Jul 8, 2025
42b65c1
chore: use const ref commitment keys (#15584)
johnathan79717 Jul 8, 2025
eab81f2
Merge remote-tracking branch 'origin/next' into merge-train/barretenberg
ludamad Jul 8, 2025
110418e
Comments
federicobarbacovi Jul 4, 2025
b5e6c56
Restructure merge prover, verifier and recursive verifier
federicobarbacovi Jul 4, 2025
aca761a
Improve code
federicobarbacovi Jul 7, 2025
df16981
Precompute inverse vanishing evals
federicobarbacovi Jul 7, 2025
223fecc
Extend tests; fix verifiers' algorithms
federicobarbacovi Jul 7, 2025
ec9562c
Fixes; extend tests
federicobarbacovi Jul 7, 2025
fccab37
Cleanup; update constants
federicobarbacovi Jul 7, 2025
a5a87ca
Comments
federicobarbacovi Jul 7, 2025
af74cd8
Fix boomerang variables
federicobarbacovi Jul 8, 2025
282cf5b
Refactoring
federicobarbacovi Jul 8, 2025
2d058b2
Clean up
federicobarbacovi Jul 8, 2025
009b877
Merge commit '42b65c12b46f46aac143fb8792440e1ea3720218' into merge-tr…
ludamad Jul 8, 2025
4d3d27e
fix: hiding circuit vk computed only once (#15589)
iakovenkos Jul 8, 2025
0c7b576
Merge branch 'next' into merge-train/barretenberg
Jul 8, 2025
d7ef5da
feat: transcript can hash objects independently (#15510)
lucasxia01 Jul 8, 2025
5aa598e
chore: readme for benchmarking remotely (#15512)
johnathan79717 Jul 8, 2025
2715013
chore: fix avm test (#15592)
ledwards2225 Jul 8, 2025
6672183
chore: hash more stuff for IPA. (#15519)
notnotraju Jul 8, 2025
6feebd6
chore: fix avm build in merge-train/bb (#15594)
lucasxia01 Jul 8, 2025
7caf428
Merge branch 'next' into merge-train/barretenberg
Jul 8, 2025
ea2dc29
feat!: structured public inputs via kernel io (#15383)
ledwards2225 Jul 8, 2025
45e13d7
Merge branch 'next' into merge-train/barretenberg
Jul 8, 2025
459d6c3
Merge branch 'next' into merge-train/barretenberg
Jul 8, 2025
5631fe6
fix!: aggregate correct nested pairing points in the hiding circuit (…
ledwards2225 Jul 8, 2025
32f2614
fix: bb merge-train conflicts (#15617)
iakovenkos Jul 9, 2025
c627773
chore: Refactor shplonk verifier api (#15618)
federicobarbacovi Jul 9, 2025
74beeaa
Merge branch 'merge-train/barretenberg' into fb/merge_with_degree_check
federicobarbacovi Jul 9, 2025
87968cc
Merge remote-tracking branch 'origin/next' into merge-train/barretenberg
lucasxia01 Jul 9, 2025
2cdecf4
Refactor
federicobarbacovi Jul 9, 2025
803dce4
Merge remote-tracking branch 'origin/next' into merge-train/barretenberg
lucasxia01 Jul 9, 2025
b47e5e9
Clean up
federicobarbacovi Jul 9, 2025
539ea86
Update tests
federicobarbacovi Jul 9, 2025
e0b5159
chore!: databus consistency checks in the hiding circuit (#15599)
ledwards2225 Jul 9, 2025
0999e1b
feat!: VK hash consistency check (#15591)
lucasxia01 Jul 9, 2025
886668e
Merge branch 'next' into merge-train/barretenberg
Jul 9, 2025
0a200eb
Merge branch 'next' into merge-train/barretenberg
Jul 9, 2025
5ba068d
Merge branch 'next' into merge-train/barretenberg
Jul 9, 2025
4ef2dd8
Merge branch 'next' into merge-train/barretenberg
Jul 9, 2025
1501441
[empty] Start train.
ludamad Jul 9, 2025
747c4b6
Merge branch 'merge-train/barretenberg' into fb/merge_with_degree_check
federicobarbacovi Jul 10, 2025
d7e0ff6
Merge remote-tracking branch 'origin/merge-train/barretenberg' into f…
federicobarbacovi Jul 10, 2025
05087eb
Merge branch 'next' into merge-train/barretenberg
Jul 10, 2025
0201111
Merge branch 'next' into merge-train/barretenberg
Jul 10, 2025
e8a0aee
feat: merge protocol correctly processes both appending and prependin…
Jul 10, 2025
8d867b9
Merge branch 'next' into merge-train/barretenberg
Jul 10, 2025
adbc4a3
Address minor comments
federicobarbacovi Jul 10, 2025
2e12c3c
Removed shplonk getter and simplified rec merge verifier code
federicobarbacovi Jul 10, 2025
2211bc3
Merge branch 'next' into merge-train/barretenberg
Jul 10, 2025
b228c2a
Prover stores tables
federicobarbacovi Jul 10, 2025
234bc71
Revert prover to monolithic structure
federicobarbacovi Jul 10, 2025
4e905a8
Merge branch 'next' into merge-train/barretenberg
Jul 10, 2025
9bada48
Revert native verifier to monolithic structure
federicobarbacovi Jul 10, 2025
780dbcf
Return rec merge verifier to monolithic structure
federicobarbacovi Jul 10, 2025
67e2202
Fixes
federicobarbacovi Jul 10, 2025
3de14b6
chore!: use kernel/app io mechanism in CIVC (#15603)
ledwards2225 Jul 10, 2025
88a7c16
Merge branch 'next' into merge-train/barretenberg
Jul 10, 2025
2d705b7
Merge branch 'next' into merge-train/barretenberg
Jul 10, 2025
bb6b66e
Comments
federicobarbacovi Jul 10, 2025
871adcc
Remove unused code
federicobarbacovi Jul 10, 2025
c2f2a9c
Merge branch 'next' into merge-train/barretenberg
Jul 10, 2025
e674a62
Improve comments for merge prover
federicobarbacovi Jul 10, 2025
d2df7c4
Improve verifier's comments
federicobarbacovi Jul 10, 2025
548b5aa
Comments
federicobarbacovi Jul 10, 2025
1911ac9
feat: fiat-shamir VK in ECCVM and Translator (#15640)
lucasxia01 Jul 10, 2025
06a3d42
chore(bb): instrument tracy fully (#14820)
ludamad Jul 10, 2025
841fab1
chore: remove large vk constructors meant for msgpack (#15654)
ludamad Jul 10, 2025
97b793c
Merge branch 'next' into merge-train/barretenberg
Jul 10, 2025
6dc5fb5
chore: ECCVM and Translator VK/Proof tests (#15658)
lucasxia01 Jul 10, 2025
7eb602c
fix: correct pub inputs propagation in hiding kernel (#15657)
ledwards2225 Jul 10, 2025
bef3f04
Merge branch 'next' into merge-train/barretenberg
Jul 10, 2025
a898e8d
chore(msgpack): vk boilerplate reduction (#15659)
ludamad Jul 10, 2025
2817839
feat(bbapi): rename bbrpc=>bbapi, move CIVC CLI to use bbapi (#15502)
ludamad Jul 10, 2025
6ba0151
chore: remove DatabusPropagationData altogether (#15611)
ledwards2225 Jul 11, 2025
08177af
Merge branch 'next' into merge-train/barretenberg
Jul 11, 2025
cee6f9f
Revert "feat(bbapi): rename bbrpc=>bbapi, move CIVC CLI to use bbapi"…
ludamad Jul 11, 2025
0bfd814
Merge remote-tracking branch 'origin/merge-train/barretenberg' into f…
federicobarbacovi Jul 11, 2025
f3f3806
Comment
federicobarbacovi Jul 11, 2025
dcfc83e
Minor changes to restart working
federicobarbacovi Jul 11, 2025
cf372d8
feat: KZG handles empty polynomial (#15652)
federicobarbacovi Jul 11, 2025
a4cce67
Merge branch 'next' into merge-train/barretenberg
Jul 11, 2025
fd98c6d
WIP
federicobarbacovi Jul 11, 2025
3f00ca5
Update merge provers/verifiers
federicobarbacovi Jul 11, 2025
e5d2707
Update tests
federicobarbacovi Jul 11, 2025
bb6ff82
Merge remote-tracking branch 'origin/merge-train/barretenberg' into f…
federicobarbacovi Jul 11, 2025
e2cb591
Fix
federicobarbacovi Jul 11, 2025
62a8808
Fix pow; remove append only merge test
federicobarbacovi Jul 14, 2025
8013c1f
Clean up
federicobarbacovi Jul 14, 2025
7c5a895
[empty] Start merge-train. Choo choo.
Jul 14, 2025
1747df4
Merge remote-tracking branch 'origin/merge-train/barretenberg' into f…
federicobarbacovi Jul 14, 2025
620891b
Revert changes to mega flavor
federicobarbacovi Jul 14, 2025
312c4da
Address comments
federicobarbacovi Jul 14, 2025
5a089d5
Merge remote-tracking branch 'origin/merge-train/barretenberg' into f…
federicobarbacovi Jul 15, 2025
958433e
Update mock verifier inputs
federicobarbacovi Jul 15, 2025
55c579e
Style
federicobarbacovi Jul 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ cd ..
# - Generate a hash for versioning: sha256sum bb-civc-inputs.tar.gz
# - Upload the compressed results: aws s3 cp bb-civc-inputs.tar.gz s3://aztec-ci-artifacts/protocol/bb-civc-inputs-[hash(0:8)].tar.gz
# Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0
pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-c8814328.tar.gz"
pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-79e2c5e0.tar.gz"

# For easily rerunning the inputs generation
if [[ "${1:-}" == "--update_inputs" ]]; then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,9 @@ template <typename Curve> class ShplonkVerifier_ {

commitments.insert(commitments.end(), polynomial_commitments.begin(), polynomial_commitments.end());
scalars.insert(scalars.end(), commitments.size() - 1, Fr(0)); // Initialised as circuit constants
for (size_t idx = 0; idx < num_claims; idx++) {
// The first two powers of nu have already been initialized, we need another `num_claims - 2` powers to batch
// all the claims
for (size_t idx = 0; idx < num_claims - 2; idx++) {
Comment thread
federicobarbacovi marked this conversation as resolved.
pows_of_nu.emplace_back(pows_of_nu.back() * pows_of_nu[1]);
}

Expand Down Expand Up @@ -481,6 +483,7 @@ template <typename Curve> class ShplonkVerifier_ {
* @param g1_identity
* @return BatchOpeningClaim<Curve>
*/
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1475): Compute g1_identity inside the function body
BatchOpeningClaim<Curve> export_batch_opening_claim(const Commitment& g1_identity)
{
commitments.emplace_back(g1_identity);
Expand Down
2 changes: 1 addition & 1 deletion barretenberg/cpp/src/barretenberg/constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ static constexpr uint32_t NUM_LIBRA_COMMITMENTS = 3;
// extra evaluations
static constexpr uint32_t NUM_SMALL_IPA_EVALUATIONS = 4;

static constexpr uint32_t MERGE_PROOF_SIZE = 49; // used to ensure mock proofs are generated correctly
static constexpr uint32_t MERGE_PROOF_SIZE = 65; // used to ensure mock proofs are generated correctly

// There are 5 distinguished wires in ECCVM that have to be opened as univariates to establish the connection between
// ECCVM and Translator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,10 @@ Goblin::MergeProof create_mock_merge_proof()
// Populate mock subtable size
proof.emplace_back(mock_val);

// There are 8 entities in the merge protocol (4 columns x 2 components; aggregate transcript, previous aggregate
// transcript) and 12 evalations (4 columns x 3 components; aggregate transcript, previous aggregate
// transcript, current transcript)
const size_t NUM_TRANSCRIPT_ENTITIES = 8;
const size_t NUM_TRANSCRIPT_EVALUATIONS = 12;
// There are 12 entities in the merge protocol (4 columns x 3 components: T_{prev,j}, T_j, g_j(X) = X^{l-1} t_j(X))
// and 8 evaluations (4 columns x 2 components: g_j(kappa), t_j(1/kappa))
const size_t NUM_TRANSCRIPT_ENTITIES = 12;
const size_t NUM_TRANSCRIPT_EVALUATIONS = 8;

// Transcript poly commitments
for (size_t i = 0; i < NUM_TRANSCRIPT_ENTITIES; ++i) {
Expand All @@ -193,7 +192,13 @@ Goblin::MergeProof create_mock_merge_proof()
for (size_t i = 0; i < NUM_TRANSCRIPT_EVALUATIONS; ++i) {
proof.emplace_back(mock_val);
}
// Batched KZG quotient commitment

// Shplonk proof: commitment to the quotient
for (const FF& val : mock_commitment_frs) {
proof.emplace_back(val);
}

// KZG proof: commitment to W
for (const FF& val : mock_commitment_frs) {
proof.emplace_back(val);
}
Expand Down
12 changes: 12 additions & 0 deletions barretenberg/cpp/src/barretenberg/polynomials/polynomial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,18 @@ template <typename Fr> Polynomial<Fr> Polynomial<Fr>::right_shifted(const size_t
return result;
}

template <typename Fr> Polynomial<Fr> Polynomial<Fr>::reverse() const
{
const size_t end_index = this->end_index();
const size_t start_index = this->start_index();
const size_t poly_size = this->size();
Polynomial reversed(/*size=*/poly_size, /*virtual_size=*/end_index);
for (size_t idx = end_index; idx > start_index; --idx) {
reversed.at(end_index - idx) = this->at(idx - 1);
}
return reversed;
}

template class Polynomial<bb::fr>;
template class Polynomial<grumpkin::fr>;
} // namespace bb
9 changes: 9 additions & 0 deletions barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,15 @@ template <typename Fr> class Polynomial {
*/
Polynomial right_shifted(const size_t magnitude) const;

/**
* @brief Returns the polynomial equal to the reverse of self
*
* @details If the coefficients of self are \f$(a_0, \dots, a_n)\f$, we return the polynomial with coefficients
* \f$(a_n, \dots, a_0)\f$
* @note Resulting polynomial uses new backing memory; n = self->size()
*/
Polynomial reverse() const;

/**
* @brief evaluate multi-linear extension p(X_0,…,X_{n-1}) = \sum_i a_i*L_i(X_0,…,X_{n-1}) at u =
* (u_0,…,u_{n-1}) If the polynomial is embedded into a lower dimension k<n, i.e, start_index + size <= 2^k, we
Expand Down
33 changes: 31 additions & 2 deletions barretenberg/cpp/src/barretenberg/polynomials/polynomial.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ TEST(Polynomial, RightShifted)
const size_t SIZE = 10;
const size_t VIRTUAL_SIZE = 20;
const size_t START_IDX = 2;
const size_t END_IDX = SIZE + START_IDX;
const size_t SHIFT_MAGNITUDE = 5;
auto poly = Polynomial::random(SIZE, VIRTUAL_SIZE, START_IDX);

Expand All @@ -46,17 +47,45 @@ TEST(Polynomial, RightShifted)
EXPECT_EQ(poly_shifted.virtual_size(), poly.virtual_size());

// The shift is indeed the shift
for (size_t i = 0; i < SIZE; ++i) {
for (size_t i = 0; i < END_IDX; ++i) {
EXPECT_EQ(poly_shifted.get(i + SHIFT_MAGNITUDE), poly.get(i));
}

// If I change the original polynomial, the shift is updated accordingly
poly.at(3) = 25;
for (size_t i = 0; i < SIZE; ++i) {
for (size_t i = 0; i < END_IDX; ++i) {
EXPECT_EQ(poly_shifted.get(i + SHIFT_MAGNITUDE), poly.get(i));
}
}

// Simple test/demonstration of reverse functionality
TEST(Polynomial, Reversed)
{
using FF = bb::fr;
using Polynomial = bb::Polynomial<FF>;
const size_t SIZE = 10;
const size_t VIRTUAL_SIZE = 20;
const size_t START_IDX = 2;
const size_t END_IDX = SIZE + START_IDX;
auto poly = Polynomial::random(SIZE, VIRTUAL_SIZE, START_IDX);

// Instantiate the shift via the right_shifted method
auto poly_reversed = poly.reverse();

EXPECT_EQ(poly_reversed.size(), poly.size());
EXPECT_EQ(poly_reversed.virtual_size(), poly.end_index());

// The reversed is indeed the reversed
for (size_t i = 0; i < END_IDX; ++i) {
EXPECT_EQ(poly_reversed.get(END_IDX - 1 - i), poly.get(i));
}

// If I change the original polynomial, the reversed polynomial is not updated
FF initial_value = poly.at(3);
poly.at(3) = 25;
EXPECT_EQ(poly_reversed.at(END_IDX - 4), initial_value);
}

// Simple test/demonstration of share functionality
TEST(Polynomial, Share)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// =====================

#include "barretenberg/stdlib/merge_verifier/merge_recursive_verifier.hpp"
#include "barretenberg/commitment_schemes/shplonk/shplonk.hpp"

namespace bb::stdlib::recursion::goblin {

Expand All @@ -18,98 +19,139 @@ MergeRecursiveVerifier_<CircuitBuilder>::MergeRecursiveVerifier_(CircuitBuilder*
{}

/**
* @brief Computes inputs to a pairing check that, if verified, establishes proper construction of the aggregate Goblin
* ECC op queue polynomials T_j, j = 1,2,3,4.
* @details Let T_j be the jth column of the aggregate ecc op table after prepending the subtable columns t_j containing
* the contribution from a single circuit. T_{j,prev} corresponds to the columns of the aggregate table at the
* previous stage. For each column we have the relationship T_j = t_j + right_shift(T_{j,prev}, k), where k is the
* length of the subtable columns t_j. This protocol demonstrates, assuming the length of t is at most k, that the
* aggregate ecc op table has been constructed correctly via the simple Schwartz-Zippel check:
* @brief Computes inputs to a pairing check that, if verified, establishes proper construction of the aggregate
* Goblin ECC op queue polynomials T_j, j = 1,2,3,4.
* @details Let \f$l_j\f$, \f$r_j\f$, \f$m_j\f$ be three vectors. The Merge wants to convince the verifier that the
* polynomials l_j, r_j, m_j for which they have sent commitments [l_j], [r_j], [m_j] satisfy
* - m_j(X) = l_j(X) + X^l r_j(X) (1)
* - deg(l_j(X)) < k (2)
* where k = shift_size.
*
* T_j(\kappa) = t_j(\kappa) + \kappa^k * (T_{j,prev}(\kappa)).
* To check condition (1), the verifier samples a challenge kappa and request from the prover a proof that
* the polynomial
* p_j(X) = l_j(kappa) + kappa^k r_j(kappa) - m_j(kappa)
* opens to 0 at kappa.
*
* To check condition (2), the verifier requests from the prover the commitment to a polynomial g_j, and
* then requests proofs that
* l_j(1/kappa) = c g_j(kappa) = d
* Then, they verify c * kappa^{k-1} = d, which implies, up to negligible probability, that
* g_j(X) = X^{l-1} l_j(1/X), which means that deg(l_j(X)) < l.
*
* The verifier must therefore check 12 opening claims: p_j(kappa) = 0, l_j(1/kappa), g_j(kappa)
* We use Shplonk to verify the claims with a single MSM (instead of computing [p_j] from [l_j], [r_j], [m_j]
* and then open it). We initialize the Shplonk verifier with the following commitments:
* [l_1], [r_1], [m_1], [g_1], ..., [l_4], [r_4], [m_4], [g_4]
* Then, we verify the various claims:
* - p_j(kappa) = 0: The commitment to p_j is constructed from the commitments to l_j, r_j, m_j, so
* the claim passed to the Shplonk verifier specifies the indices of these commitments in
* the above vector: {4 * (j-1), 4 * (j-1) + 1, 4 * (j-1) + 2}, the coefficients
* reconstructing p_j from l_j, r_j, m_j: {1, kappa^k, -1}, and the claimed
* evaluation: 0.
* - l_j(1/kappa) = v_j: The index in this case is {4 * (j-1)}, the coefficient is { 1 }, and the evaluation is
* v_j.
* - g_j(kappa) = w_j: The index is {3 + 4 * (j-1)}, the coefficient is { 1 }, and the evaluation is w_j.
* The claims are passed in the following order:
* {kappa, 0}, {kappa, 0}, {kappa, 0}, {kappa, 0}, {1/kappa, v_1}, {kappa, w_1}, .., {1/kappa, v_4}, {kappa, w_4}
*
* In the Goblin scenario, we have:
* - \f$l_j = t_j, r_j = T_{prev,j}, m_j = T_j\f$ if we are prepending the subtable
* - \f$l_j = T_{prev,j}, r_j = t_j, m_j = T_j\f$ if we are appending the subtable
*
* @tparam CircuitBuilder
* @param proof
* @param t_commitments The commitments to t_j read from the transcript by the PG recursive verifier with which the
* Merge recursive verifier shares a transcript
* @return std::array<typename Flavor::GroupElement, 2> Inputs to final pairing
* @param t_commitments The commitments to t_j read from the transcript by the PG recursive verifier with which
* the Merge recursive verifier shares a transcript
* @return PairingPoints Inputs to final pairing
*/
template <typename CircuitBuilder>
MergeRecursiveVerifier_<CircuitBuilder>::PairingPoints MergeRecursiveVerifier_<CircuitBuilder>::verify_proof(
const stdlib::Proof<CircuitBuilder>& proof, const RefArray<Commitment, NUM_WIRES> t_commitments)
{
// Transform proof into a stdlib object
using Claims = typename ShplonkVerifier_<Curve>::LinearCombinationOfClaims;

transcript->load_proof(proof);

FF subtable_size = transcript->template receive_from_prover<FF>("subtable_size");
FF shift_size = transcript->template receive_from_prover<FF>("shift_size");
BB_ASSERT_GT(shift_size.get_value(), 0U, "Shift size should always be bigger than 0");

// Receive table column polynomial commitments [T_{j,prev}], and [T_j], j = 1,2,3,4
std::array<Commitment, NUM_WIRES> T_prev_commitments;
// Vector of commitments to be passed to the Shplonk verifier
// The vector is composed of: [l_1], [r_1], [m_1], [g_1], ..., [l_4], [r_4], [m_4], [g_4]
std::vector<Commitment> table_commitments;
for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
std::string suffix = std::to_string(idx);
T_prev_commitments[idx] = transcript->template receive_from_prover<Commitment>("T_PREV_" + suffix);
T_commitments[idx] = transcript->template receive_from_prover<Commitment>("T_CURRENT_" + suffix);
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1473): remove receiving commitment to T_prev
auto T_prev_commitment = transcript->template receive_from_prover<Commitment>("T_PREV_" + std::to_string(idx));
auto left_table = settings == MergeSettings::PREPEND ? t_commitments[idx] : T_prev_commitment;
auto right_table = settings == MergeSettings::PREPEND ? T_prev_commitment : t_commitments[idx];

table_commitments.emplace_back(left_table);
table_commitments.emplace_back(right_table);
table_commitments.emplace_back(
transcript->template receive_from_prover<Commitment>("MERGED_TABLE_" + std::to_string(idx)));
table_commitments.emplace_back(
transcript->template receive_from_prover<Commitment>("LEFT_TABLE_REVERSED_" + std::to_string(idx)));
}

FF kappa = transcript->template get_challenge<FF>("kappa");

// Receive evaluations t_j(\kappa), T_{j,prev}(\kappa), T_j(\kappa), j = 1,2,3,4
std::array<FF, NUM_WIRES> t_evals;
std::array<FF, NUM_WIRES> T_prev_evals;
std::array<FF, NUM_WIRES> T_evals;
std::vector<OpeningClaim> opening_claims;
for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
t_evals[idx] = transcript->template receive_from_prover<FF>("t_eval_" + std::to_string(idx + 1));
opening_claims.emplace_back(OpeningClaim{ { kappa, t_evals[idx] }, t_commitments[idx] });
}
for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
T_prev_evals[idx] = transcript->template receive_from_prover<FF>("T_prev_eval_" + std::to_string(idx + 1));
opening_claims.emplace_back(OpeningClaim{ { kappa, T_prev_evals[idx] }, T_prev_commitments[idx] });
}
for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
T_evals[idx] = transcript->template receive_from_prover<FF>("T_eval_" + std::to_string(idx + 1));
opening_claims.emplace_back(OpeningClaim{ { kappa, T_evals[idx] }, T_commitments[idx] });
// Store T_commitments of the verifier
size_t commitment_idx = 2; // Index of [m_j = T_j] in the vector of commitments
for (auto& commitment : T_commitments) {
commitment = table_commitments[commitment_idx];
commitment_idx += NUM_WIRES;
}

// Check the appropriate identity based on the given merge settings
// Evaluation challenge
const FF kappa = transcript->template get_challenge<FF>("kappa");
const FF kappa_inv = kappa.invert();
const FF pow_kappa = kappa.pow(shift_size);
const FF pow_kappa_minus_one = pow_kappa * kappa_inv;

// Opening claims to be passed to the Shplonk verifier
std::vector<Claims> opening_claims;

// Add opening claim for p_j(X) = l_j(X) + X^k r_j(X) - m_j(X)
commitment_idx = 0;
for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
if (settings == MergeSettings::PREPEND) {
// T_j(\kappa) = t_j(\kappa) + \kappa^m * T_{j,prev}(\kappa)
FF T_prev_shifted_eval_reconstructed = T_prev_evals[idx] * kappa.pow(subtable_size);
T_evals[idx].assert_equal(t_evals[idx] + T_prev_shifted_eval_reconstructed);
} else {
// T_j(\kappa) = T_{j,prev}(\kappa) + \kappa^m * t_j(\kappa)
FF t_shifted_eval_reconstructed = t_evals[idx] * kappa.pow(subtable_size);
T_evals[idx].assert_equal(T_prev_evals[idx] + t_shifted_eval_reconstructed);
}
opening_claims.emplace_back(Claims{ { /*index of [l_j]*/ commitment_idx,
/*index of [r_j]*/ commitment_idx + 1,
/*index of [m_j]*/ commitment_idx + 2 },
{ FF(1), pow_kappa, FF(-1) },
{ kappa, FF(0) } });

// Move commitment_idx to the index of [l_{j+1}]
commitment_idx += NUM_WIRES;
}

FF alpha = transcript->template get_challenge<FF>("alpha");

// Constuct inputs to batched commitment and batched evaluation from constituents using batching challenge \alpha
std::vector<FF> scalars;
std::vector<Commitment> commitments;
scalars.emplace_back(FF(builder, 1));
commitments.emplace_back(opening_claims[0].commitment);
auto batched_eval = opening_claims[0].opening_pair.evaluation;
auto alpha_pow = alpha;
for (size_t idx = 1; idx < opening_claims.size(); ++idx) {
auto& claim = opening_claims[idx];
scalars.emplace_back(alpha_pow);
commitments.emplace_back(claim.commitment);
batched_eval += alpha_pow * claim.opening_pair.evaluation;
if (idx < opening_claims.size() - 1) {
alpha_pow *= alpha;
}
// Add opening claim for l_j(1/kappa), g_j(kappa) and check g_j(kappa) = l_j(1/kappa) * kappa^{k-1}
commitment_idx = 0;
for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
// Opening claim for l_j(1/kappa)
FF left_table_eval_kappa_inv =
transcript->template receive_from_prover<FF>("left_table_eval_kappa_inv_" + std::to_string(idx));
opening_claims.emplace_back(
Claims{ { /*index of [l_j]*/ commitment_idx }, { FF(1) }, { kappa_inv, left_table_eval_kappa_inv } });

// Opening claim for g_j(kappa)
FF left_table_reversed_eval =
transcript->template receive_from_prover<FF>("left_table_reversed_eval_" + std::to_string(idx));
opening_claims.emplace_back(
Claims{ { /*index of [g_j]*/ commitment_idx + 3 }, { FF(1) }, { kappa, left_table_reversed_eval } });

// Move commitment_idx to index of left_table_{j+1}
commitment_idx += NUM_WIRES;

// Degree identity
left_table_reversed_eval.assert_equal(left_table_eval_kappa_inv * pow_kappa_minus_one);
}

auto batched_commitment = Commitment::batch_mul(commitments, scalars, /*max_num_bits=*/0, /*with_edgecases=*/true);

OpeningClaim batched_claim = { { kappa, batched_eval }, batched_commitment };
// Initialize Shplonk verifier
ShplonkVerifier_<Curve> verifier(table_commitments, transcript, opening_claims.size());
verifier.reduce_verification_vector_claims_no_finalize(opening_claims);

auto pairing_points = KZG::reduce_verify(batched_claim, transcript);
// Export batched claim
auto batch_opening_claim = verifier.export_batch_opening_claim(Commitment::one(kappa.get_context()));

return { pairing_points[0], pairing_points[1] };
// KZG verifier
return KZG::reduce_verify_batch_opening_claim(batch_opening_claim, transcript);
}

template class MergeRecursiveVerifier_<MegaCircuitBuilder>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,17 @@ template <typename CircuitBuilder> class MergeRecursiveVerifier_ {
using Commitment = typename Curve::Element;
using GroupElement = typename Curve::Element;
using KZG = ::bb::KZG<Curve>;
using OpeningClaim = ::bb::OpeningClaim<Curve>;
using Transcript = bb::BaseTranscript<bb::stdlib::recursion::honk::StdlibTranscriptParams<CircuitBuilder>>;
using PairingPoints = stdlib::recursion::PairingPoints<CircuitBuilder>;

CircuitBuilder* builder;
std::shared_ptr<Transcript> transcript;
MergeSettings settings;

// Number of columns that jointly constitute the op_queue, should be the same as the number of wires in the
// MegaCircuitBuilder
static constexpr size_t NUM_WIRES = MegaExecutionTraceBlocks::NUM_WIRES;

std::array<Commitment, NUM_WIRES> T_commitments;

explicit MergeRecursiveVerifier_(CircuitBuilder* builder,
Expand Down
Loading
Loading