14#include <gtest/gtest.h>
54template <
typename RecursiveFlavor_,
bool IsRootRollup_,
size_t N_, std::array<
size_t, N_> LayerSizes_>
59 static constexpr size_t N = N_;
60 static constexpr std::array<size_t, N>
LayerSizes = LayerSizes_;
63template <
typename RecursiveFlavor,
bool IsRootRollup,
size_t N, std::array<
size_t, N> LayerSizes>
68 for (
size_t idx = 0; idx < N - 1; idx++) {
69 if (LayerSizes[idx + 1] > LayerSizes[idx]) {
79 if constexpr (IsRootRollup) {
80 return HasIPAAccumulator<RecursiveFlavor> && N == 1 && LayerSizes[0] == 2;
98 if constexpr (HasIPAAccumulator<InnerFlavor>) {
100 }
else if constexpr (InnerFlavor::HasZK) {
110 using Builder = RecursiveFlavor::CircuitBuilder;
122 if constexpr (IsRootRollup) {
131 if constexpr (IsRootRollup) {
135 return {
"None",
"VKHash",
"VK",
"Proof" };
152 builder.add_public_variable(InnerBuilder::FF::random_element());
174 auto shift_by_offset = [&
offset](std::vector<uint32_t>& indices) {
175 for (
auto& witness_idx : indices) {
180 shift_by_offset(honk_recursion_constraint.
key);
181 shift_by_offset(honk_recursion_constraint.
proof);
187 for (
auto [constraint, witnesses] :
zip_view(constraints, witness_vectors)) {
188 offset_recursion_constraint(constraint, witness_values.size());
190 constraint.proof_type = IsRootRollup ?
ROOT_ROLLUP_HONK : constraint.proof_type;
191 witness_values.insert(witness_values.end(), witnesses.begin(), witnesses.end());
195 return constraints[0];
210 builder.add_public_variable(InnerBuilder::FF::random_element());
215 InnerProver prover(prover_instance, verification_key);
222 verification_key->to_field_elements(),
223 verification_key->hash(),
225 builder.num_public_inputs() - InnerIO::PUBLIC_INPUTS_SIZE,
228 return { recursion_constraint, witness_values };
245 switch (invalid_witness_target) {
251 witness_values[honk_recursion_constraints.key_hash] +=
fr::one();
253 witness_values[honk_recursion_constraints[0].key_hash] +=
fr::one();
259 std::vector<uint32_t> vk_indices;
261 witness_values[honk_recursion_constraints.key[0]] +=
fr::one();
263 witness_values[honk_recursion_constraints[0].key[0]] +=
fr::one();
270 std::vector<uint32_t> proof_indices;
272 proof_indices = honk_recursion_constraints.proof;
274 proof_indices = honk_recursion_constraints[0].proof;
276 size_t commitment_size = FrCodec::template calc_num_fields<typename InnerFlavor::Commitment>();
278 for (
size_t idx = 0; idx < commitment_size; idx++) {
279 witness_values[proof_indices[InnerIO::PUBLIC_INPUTS_SIZE + idx]] = mock_proof_element[idx];
285 return { honk_recursion_constraints, witness_values };
293 for (
size_t layer_idx = 0; layer_idx < N; layer_idx++) {
294 size_t current_layer_size = LayerSizes[layer_idx];
295 for (
size_t idx = 0; idx < current_layer_size; idx++) {
296 if (layer_idx == 0) {
299 auto [constraint, witnesses] = []() {
303 constraints.emplace_back(
std::move(constraint));
304 witness_vectors.emplace_back(
std::move(witnesses));
312 recursion_constraint,
static_cast<uint32_t
>(witnesses.size()) - 1);
316 std::tie(constraints[idx], witness_vectors[idx]) = [&]() {
329template <
typename Params>
331 :
public ::testing::Test,
333 Params::IsRootRollup,
335 Params::LayerSizes>> {
347 testing::Types<HonkRecursionTestParams<UltraRecursiveFlavor_<UltraCircuitBuilder>,
false, 1, { 1 }>,
361 typename TestFixture::RecursiveFlavor::NativeFlavor>;
362 TestFixture::template test_vk_independence<Flavor>();
368 TestFixture::test_constant_true(TestFixture::InvalidWitnessTarget::VKHash);
374 TestFixture::test_witness_true(TestFixture::InvalidWitnessTarget::VKHash);
380 TestFixture::test_witness_false_slow();
385 using RecursiveFlavor = TestFixture::RecursiveFlavor;
386 using Builder = TestFixture::Builder;
387 using InvalidWitnessTarget = TestFixture::InvalidWitnessTarget;
389 typename TestFixture::AcirConstraint constraint;
391 TestFixture::Base::generate_constraints(constraint, witness_values);
395 .invalid_witness = InvalidWitnessTarget::None };
396 auto [updated_constraint, updated_witness_values] =
397 TestFixture::update_witness_based_on_predicate(constraint, witness_values, predicate);
400 updated_constraint,
static_cast<uint32_t
>(updated_witness_values.size()) - 1);
402 AcirProgram program{ constraint_system, updated_witness_values };
405 auto builder = create_circuit<Builder>(program, metadata);
408 EXPECT_EQ(program.constraints.gates_per_opcode.size(), 1);
411 auto [EXPECTED_GATE_COUNT, EXPECTED_ULTRA_OPS] = HONK_RECURSION_CONSTANTS<RecursiveFlavor>(predicate_mode);
414 EXPECT_EQ(program.constraints.gates_per_opcode[0], EXPECTED_GATE_COUNT);
418 size_t actual_ultra_ops =
builder.op_queue->get_current_subtable_size();
419 EXPECT_EQ(actual_ultra_ops, EXPECTED_ULTRA_OPS);
424template <
typename Params>
426 :
public ::testing::Test,
427 public TestClass<HonkRecursionConstraintTestingFunctions<typename Params::RecursiveFlavor,
428 Params::IsRootRollup,
430 Params::LayerSizes>> {
459 if constexpr (TypeParam::IsRootRollup) {
460 TestFixture::template test_vk_independence<UltraZKFlavor>();
466 typename TestFixture::RecursiveFlavor::NativeFlavor>;
468 TestFixture::template test_vk_independence<Flavor>();
475 [[maybe_unused]] std::vector<std::string> _ = TestFixture::test_tampering();
480 using Builder = TestFixture::Builder;
482 if constexpr (!TestFixture::IsRootRollup) {
486 typename TestFixture::AcirConstraint constraint;
488 TestFixture::Base::generate_constraints(constraint, witness_values);
493 AcirProgram program{ constraint_system, witness_values };
496 auto builder = create_circuit<Builder>(program, metadata);
499 EXPECT_EQ(program.constraints.gates_per_opcode.size(), 2);
#define BB_DISABLE_ASSERTS()
static void SetUpTestSuite()
static constexpr bool IsRootRollup
Params::RecursiveFlavor RecursiveFlavor
Params::RecursiveFlavor RecursiveFlavor
static void SetUpTestSuite()
static constexpr bool IsRootRollup
InnerFlavor::VerificationKey InnerVerificationKey
static constexpr uint32_t InnerProofType
std::conditional_t< IS_SINGLE_RECURSIVE_VERIFICATION, RecursionConstraint, std::vector< RecursionConstraint > > AcirConstraint
static InnerBuilder create_inner_circuit()
Create a dummy circuit.
static void generate_constraints(AcirConstraint &honk_recursion_constraint, WitnessVector &witness_values)
static constexpr size_t NUM_PUBLIC_INPUTS
std::conditional_t< HasIPAAccumulator< InnerFlavor >, bb::stdlib::recursion::honk::RollupIO, bb::stdlib::recursion::honk::DefaultIO< InnerBuilder > > InnerIO
static ProgramMetadata generate_metadata()
Generate the metadata for the circuit recursively verifying the top layer circuits.
InnerFlavor::CircuitBuilder InnerBuilder
static constexpr bool IS_SINGLE_RECURSIVE_VERIFICATION
static std::pair< AcirConstraint, WitnessVector > invalidate_witness(AcirConstraint honk_recursion_constraints, WitnessVector witness_values, const InvalidWitness::Target &invalid_witness_target)
RecursiveFlavor::NativeFlavor InnerFlavor
RecursiveFlavor::CircuitBuilder Builder
static std::pair< RecursionConstraint, WitnessVector > circuit_to_recursion_constraint(InnerBuilder &builder)
Convert a circuit into a recursion constraint: prove the circuit and add the proof,...
static AcirConstraint merge_recursion_constraints(std::vector< RecursionConstraint > &constraints, std::vector< WitnessVector > &witness_vectors, WitnessVector &witness_values)
Merge a series of recursion constraints by offsetting the relevant indices and concatenating the witn...
static constexpr bool IsRootRollup
static constexpr size_t N
RecursiveFlavor_ RecursiveFlavor
static constexpr std::array< size_t, N > LayerSizes
static std::vector< fr > serialize_to_fields(const T &val)
Conversion from transcript values to bb::frs.
static void add_lookup_gates(Builder &builder, size_t num_iterations=1)
Add lookup gates using the uint32 XOR lookup table (table size 4096)
static void add_arithmetic_gates(Builder &builder, const size_t num_gates=4)
Add a specified number of arithmetic gates to the provided circuit.
A ProverInstance is normally constructed from a finalized circuit and it contains all the information...
A simple wrapper around a vector of stdlib field elements representing a proof.
Manages the data that is propagated on the public inputs of an application/function circuit.
The data that is propagated on the public inputs of a rollup circuit.
testing::Types< HonkRecursionTestParams< UltraRecursiveFlavor_< UltraCircuitBuilder >, false, 1, { 1 }>, HonkRecursionTestParams< UltraZKRecursiveFlavor_< UltraCircuitBuilder >, false, 1, { 1 }>, HonkRecursionTestParams< UltraRollupRecursiveFlavor_< UltraCircuitBuilder >, false, 1, { 1 }>, HonkRecursionTestParams< UltraRecursiveFlavor_< MegaCircuitBuilder >, false, 1, { 1 }>, HonkRecursionTestParams< UltraZKRecursiveFlavor_< MegaCircuitBuilder >, false, 1, { 1 }> > HonkRecursionTypesWithPredicate
testing::Types< HonkRecursionTestParams< UltraRecursiveFlavor_< UltraCircuitBuilder >, false, 1, { 2 }>, HonkRecursionTestParams< UltraZKRecursiveFlavor_< UltraCircuitBuilder >, false, 1, { 2 }>, HonkRecursionTestParams< UltraRollupRecursiveFlavor_< UltraCircuitBuilder >, false, 1, { 2 }>, HonkRecursionTestParams< UltraRollupRecursiveFlavor_< UltraCircuitBuilder >, true, 1, { 2 }>, HonkRecursionTestParams< UltraZKRecursiveFlavor_< UltraCircuitBuilder >, false, 2, { 2, 1 }>, HonkRecursionTestParams< UltraZKRecursiveFlavor_< UltraCircuitBuilder >, false, 2, { 2, 2 }>, HonkRecursionTestParams< UltraRecursiveFlavor_< MegaCircuitBuilder >, false, 4, { 4, 3, 1, 1 }> > HonkRecursionTypesWithoutPredicate
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
TYPED_TEST_SUITE(BoomerangRecursiveVerifierTest, Flavors)
Entry point for Barretenberg command-line interface.
TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
static std::vector< Target > get_all()
static std::vector< std::string > get_labels()
static constexpr field one()