26static constexpr size_t NUM_FRS_COMM = NativeTranscript::Codec::template calc_num_fields<NativeG1>();
34 using type =
typename Curve::Builder;
50 for (
size_t i = 0; i < num_ops; ++i) {
51 op_queue->add_accumulate(NativeG1::random_element());
53 op_queue->eq_and_reset();
59 const size_t max_op_queue_ops = 10;
61 for (
size_t i = 0; i < n; ++i) {
63 op_queue->initialize_new_subtable();
78 std::vector<bb::fr> round_inputs;
79 bb::fr previous_challenge(0);
80 bool is_first_challenge =
true;
82 for (
size_t subtable_idx = 0; subtable_idx < N; ++subtable_idx) {
84 if (!is_first_challenge) {
85 round_inputs.push_back(previous_challenge);
87 for (
size_t col = 0; col < NUM_WIRES; ++col) {
88 const size_t global_col_idx = (subtable_idx * NUM_WIRES) + col;
89 const size_t base = (global_col_idx * NUM_FRS_COMM);
90 for (
size_t j = 0; j < NUM_FRS_COMM; ++j) {
91 round_inputs.push_back(proof[base + j]);
97 previous_challenge = full_hash;
98 is_first_challenge =
false;
101 return previous_challenge;
131 size_t N = subtable_cols.size();
133 std::vector<size_t> shift_sizes(N);
134 size_t max_shift_size = 0;
135 for (
size_t i = 0; i < N; ++i) {
136 shift_sizes[i] = subtable_cols[i][0].size();
137 max_shift_size =
std::max(max_shift_size, shift_sizes[i]);
142 for (
size_t idx = 0; idx < N; ++idx) {
143 for (
size_t col = 0; col <
NUM_WIRES; ++col) {
154 for (
size_t idx = N; idx < M; ++idx) {
155 for (
size_t col = 0; col <
NUM_WIRES; ++col) {
156 const bool non_infinity_padding =
168 for (
size_t col = 0; col <
NUM_WIRES; ++col) {
170 Polynomial larger_zk_col(zk_columns[col], zk_columns[col].size() + 1);
171 larger_zk_col.
at(larger_zk_col.
size() - 1) =
FF(1);
172 zk_columns[col] =
std::move(larger_zk_col);
176 for (
size_t col = 0; col <
NUM_WIRES; ++col) {
180 max_shift_size =
std::max(max_shift_size, zk_columns[0].size());
185 for (
size_t col = 0; col <
NUM_WIRES; ++col) {
186 flattened_cols.push_back(
std::move(zk_columns[col]));
188 for (
auto& subtable_col : subtable_cols) {
189 for (
size_t col = 0; col <
NUM_WIRES; ++col) {
193 flattened_cols.push_back(
std::move(subtable_col[col]));
199 uint32_t sent_num_subtables =
static_cast<uint32_t
>(N);
201 sent_num_subtables = 0;
203 transcript->send_to_verifier(
"NUM_SUBTABLES", sent_num_subtables);
204 for (
size_t i = 0; i < M; ++i) {
205 uint32_t sent_shift_size =
static_cast<uint32_t
>(i < N ? shift_sizes[i] : 0);
211 sent_shift_size =
static_cast<uint32_t
>(shift_sizes[0] - 1);
222 merged_table[0].at(0) +=
FF(1);
224 for (
size_t col = 0; col <
NUM_WIRES; ++col) {
228 for (
size_t col = 0; col <
NUM_WIRES; ++col) {
234 const FF degree_check_challenge =
transcript->template get_challenge<FF>(
"DEGREE_CHECK_CHALLENGE");
236 std::vector<FF> degree_check_challenges = {
FF(1), degree_check_challenge };
237 for (
size_t idx = 2; idx < num_degree_check_challenges; ++idx) {
238 degree_check_challenges.push_back(degree_check_challenges.back() * degree_check_challenge);
245 size_t diff = flattened_cols.size() - num_degree_check_challenges;
246 for (
size_t idx = 0; idx < diff *
NUM_WIRES; ++idx) {
248 degree_check_challenges.push_back(degree_check_challenges.back() * degree_check_challenge);
258 degree_check_challenges.pop_back();
262 degree_check_poly.
at(0) +=
FF(1);
268 const FF kappa =
transcript->template get_challenge<FF>(
"KAPPA");
269 const FF kappa_inv = kappa.
invert();
272 std::vector<FF> evals;
275 for (
size_t flat_idx = 0; flat_idx < num_flattened_col_evals; ++flat_idx) {
277 if (flat_idx < num_actual_flattened_cols) {
278 eval = flattened_cols[flat_idx].evaluate(kappa);
282 evals.push_back(eval);
286 for (
size_t col = 0; col <
NUM_WIRES; ++col) {
287 evals.push_back(merged_table[col].evaluate(kappa));
291 evals.push_back(degree_check_poly.
evaluate(kappa_inv));
292 transcript->send_to_verifier(
"DEGREE_CHECK_EVAL", evals.back());
297 opening_claims.reserve(num_opening_claims);
299 for (
size_t idx = 0; idx < num_flattened_col_evals; ++idx) {
300 if (idx < num_actual_flattened_cols) {
301 opening_claims.push_back({
std::move(flattened_cols[idx]), { kappa, evals[idx] } });
303 opening_claims.push_back({
Polynomial(1), { kappa,
FF(0) } });
307 for (
size_t idx = 0; idx <
NUM_WIRES; ++idx) {
308 opening_claims.push_back(
312 opening_claims.push_back({
std::move(degree_check_poly), { kappa_inv, evals.back() } });
333 using Curve =
typename Param::CurveType;
367 auto hash = FF::from_witness(&
builder, native_hash);
368 hash.unset_free_witness_tag();
388 bool wrong_hash =
false,
389 bool check_manifest =
false)
392 std::vector<bb::fr> native_proof;
395 if (check_manifest) {
399 native_proof = prover.construct_proof();
400 if (check_manifest) {
401 prover_manifest = prover.transcript->get_manifest();
405 if (check_manifest) {
409 native_proof = prover.construct_proof();
410 if (check_manifest) {
411 prover_manifest = prover.transcript->get_manifest();
425 if (check_manifest) {
430 if (check_manifest) {
432 auto verifier_manifest = verifier.
transcript->get_manifest();
433 EXPECT_EQ(prover_manifest.
size(), verifier_manifest.size());
434 for (
size_t i = 0; i < prover_manifest.
size(); ++i) {
435 EXPECT_EQ(prover_manifest[i], verifier_manifest[i]);
447using TestParams = ::testing::Types<TestParam<curve::BN254, 9>,
458 auto res = TestFixture::prove_and_verify(op_queue,
FaultMode::NONE,
false,
true);
459 EXPECT_TRUE(res.reduction_ok);
460 EXPECT_TRUE(res.pairing_ok);
461 EXPECT_TRUE(res.circuit_ok);
467 auto res = TestFixture::prove_and_verify(op_queue);
468 EXPECT_TRUE(res.reduction_ok);
469 EXPECT_TRUE(res.pairing_ok);
470 EXPECT_TRUE(res.circuit_ok);
480 EXPECT_FALSE(res.reduction_ok);
481 EXPECT_TRUE(res.pairing_ok);
482 if constexpr (TestFixture::IsRecursive) {
483 EXPECT_FALSE(res.circuit_ok);
489 if constexpr (!TestFixture::Curve::is_stdlib_type) {
490 GTEST_SKIP() <<
"This test in native setting fails due to a deserialization failure. The verifier path in the "
491 "same for native and recursive code, so it's enough to test the recursive code.";
496 EXPECT_FALSE(res.reduction_ok);
497 EXPECT_FALSE(res.pairing_ok);
498 if constexpr (TestFixture::IsRecursive) {
499 EXPECT_FALSE(res.circuit_ok);
508 EXPECT_FALSE(res.reduction_ok);
509 EXPECT_TRUE(res.pairing_ok);
510 if constexpr (TestFixture::IsRecursive) {
511 EXPECT_FALSE(res.circuit_ok);
518 auto res = TestFixture::prove_and_verify(op_queue,
FaultMode::NONE,
true);
519 EXPECT_FALSE(res.reduction_ok);
520 EXPECT_TRUE(res.pairing_ok);
521 if constexpr (TestFixture::IsRecursive) {
522 EXPECT_FALSE(res.circuit_ok);
530 EXPECT_FALSE(res.reduction_ok);
531 EXPECT_TRUE(res.pairing_ok);
532 if constexpr (TestFixture::IsRecursive) {
533 EXPECT_FALSE(res.circuit_ok);
541 EXPECT_FALSE(res.reduction_ok);
542 EXPECT_TRUE(res.pairing_ok);
543 if constexpr (TestFixture::IsRecursive) {
544 EXPECT_FALSE(res.circuit_ok);
552 EXPECT_FALSE(res.reduction_ok);
553 EXPECT_TRUE(res.pairing_ok);
554 if constexpr (TestFixture::IsRecursive) {
555 EXPECT_FALSE(res.circuit_ok);
563 EXPECT_FALSE(res.reduction_ok);
564 EXPECT_TRUE(res.pairing_ok);
565 if constexpr (TestFixture::IsRecursive) {
566 EXPECT_FALSE(res.circuit_ok);
575 if constexpr (!TestFixture::IsRecursive) {
576 GTEST_SKIP() <<
"Graph description analysis only applies to stdlib (recursive) verifier circuits.";
578 using BuilderType =
typename TestFixture::BuilderType;
579 using FF =
typename TestFixture::FF;
580 using Proof =
typename TestFixture::Proof;
581 using Verifier =
typename TestFixture::Verifier;
589 Proof proof = TestFixture::create_proof(
builder, native_proof);
590 FF hash = TestFixture::create_hash(
builder, native_hash);
597 auto result = verifier.reduce_to_pairing_check(proof, hash);
602 result.pairing_points.fix_witness();
608 auto graph = Analyzer(
builder);
609 auto [cc, variables_in_one_gate] = graph.analyze_circuit(
true);
611 EXPECT_EQ(cc.size(), 1);
612 EXPECT_EQ(variables_in_one_gate.size(), 0);
#define BB_ASSERT_GT(left, right,...)
#define BB_DISABLE_ASSERTS()
Common transcript class for both parties. Stores the data for the current round, as well as the manif...
static constexpr size_t NUM_WIRES
CommitmentKey pcs_commitment_key
std::shared_ptr< Transcript > transcript
std::shared_ptr< ECCOpQueue > op_queue
std::vector< FF > MergeProof
MergeProof construct_proof()
Construct the batch merge proof.
static Polynomial compute_degree_check_polynomial(const std::vector< Polynomial > &flattened_columns, const std::vector< FF > °ree_check_challenges, const size_t max_size)
static constexpr size_t ZK_OFFSET
typename Verifier::Transcript Transcript
typename Param::CurveType Curve
static Proof create_proof(BuilderType &builder, const std::vector< bb::fr > &native_proof)
static constexpr bool IsRecursive
static constexpr size_t NumSubtables
typename Verifier::Proof Proof
static bool check_circuit(BuilderType &builder)
static void SetUpTestSuite()
static FF create_hash(BuilderType &builder, const bb::fr &native_hash)
typename BuilderTypeHelper< Curve >::type BuilderType
static constexpr size_t VERIFIER_NUM_GATES
static VerifyResult prove_and_verify(const std::shared_ptr< ECCOpQueue > &op_queue, FaultMode fault_mode=FaultMode::NONE, bool wrong_hash=false, bool check_manifest=false)
typename Curve::ScalarField FF
Unified batch verifier for the batch Goblin ECC op queue merge protocol.
std::shared_ptr< Transcript > transcript
ReductionResult reduce_to_pairing_check(const Proof &proof, const FF hash)
Reduce the batch merge proof to a pairing check.
TranscriptFor_t< Curve > Transcript
Commitment commit(PolynomialSpan< const Fr > polynomial) const
Uses the ProverSRS to create a commitment to p(X)
static void compute_opening_proof(const CK &ck, const ProverOpeningClaim< Curve > &opening_claim, const std::shared_ptr< Transcript > &prover_trancript)
Computes the KZG commitment to an opening proof polynomial at a single evaluation point.
static constexpr size_t NUM_WIRES
Fr evaluate(const Fr &z) const
Fr & at(size_t index)
Our mutable accessor, unlike operator[]. We abuse precedent a bit to differentiate at() and operator[...
Polynomial p and an opening pair (r,v) such that p(r) = v.
static ProverOpeningClaim< Curve > prove(const CommitmentKey< Curve > &commitment_key, std::span< ProverOpeningClaim< Curve > > opening_claims, const std::shared_ptr< Transcript > &transcript, std::span< ProverOpeningClaim< Curve > > libra_opening_claims={}, std::span< ProverOpeningClaim< Curve > > sumcheck_round_claims={}, const size_t virtual_log_n=0)
Returns a batched opening claim equivalent to a set of opening claims consisting of polynomials,...
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
TweakableBatchMergeProver(const std::shared_ptr< ECCOpQueue > &op_queue, size_t max_subtables, FaultMode mode=FaultMode::NONE)
bb::Polynomial< FF > Polynomial
MergeProof construct_proof()
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
typename Group::affine_element AffineElement
static constexpr bool is_stdlib_type
A simple wrapper around a vector of stdlib field elements representing a proof.
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
Entry point for Barretenberg command-line interface.
@ ZK_TABLE_DEGREE_TOO_HIGH
TYPED_TEST_SUITE(CommitmentKeyTest, Curves)
field< Bn254FrParams > fr
bb::fr compute_running_hash(const std::vector< bb::fr > &proof, size_t N)
void populate_subtable(const std::shared_ptr< ECCOpQueue > &op_queue, size_t num_ops)
TYPED_TEST(CommitmentKeyTest, CommitToZeroPoly)
NativeCurve::AffineElement NativeG1
std::shared_ptr< ECCOpQueue > make_op_queue_with_n_subtables(size_t n)
::testing::Types< TestParam< curve::BN254, 9 >, TestParam< curve::BN254, CHONK_MAX_NUM_CIRCUITS >, TestParam< stdlib::bn254< MegaCircuitBuilder >, 9 >, TestParam< stdlib::bn254< MegaCircuitBuilder >, CHONK_MAX_NUM_CIRCUITS > > TestParams
BaseTranscript< FrCodec, bb::crypto::Poseidon2< bb::crypto::Poseidon2Bn254ScalarFieldParams > > NativeTranscript
StaticAnalyzer_< bb::fr, bb::MegaCircuitBuilder > MegaStaticAnalyzer
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::string to_string(bb::avm2::ValueTag tag)
typename Curve::Builder type
static constexpr size_t NumSubtables
constexpr field invert() const noexcept
static field random_element(numeric::RNG *engine=nullptr) noexcept