Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -113,7 +113,7 @@ constexpr std::tuple<size_t, size_t> HONK_RECURSION_CONSTANTS(
// ========================================

// Gate count for Chonk recursive verification (Ultra with RollupIO)
inline constexpr size_t CHONK_RECURSION_GATES = 1684546;
inline constexpr size_t CHONK_RECURSION_GATES = 1684865;

// ========================================
// Hypernova Recursion Constants
Expand Down Expand Up @@ -147,7 +147,7 @@ inline constexpr size_t HIDING_KERNEL_ULTRA_OPS = 124;
// ========================================

// Gate count for ECCVM recursive verifier (Ultra-arithmetized)
inline constexpr size_t ECCVM_RECURSIVE_VERIFIER_GATE_COUNT = 224139;
inline constexpr size_t ECCVM_RECURSIVE_VERIFIER_GATE_COUNT = 224458;

// ========================================
// Goblin AVM Recursive Verifier Constants
Expand Down
8 changes: 6 additions & 2 deletions barretenberg/cpp/src/barretenberg/eccvm/eccvm.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,16 @@ void complete_proving_key_for_test(bb::RelationParameters<FF>& relation_paramete
const FF beta = FF::random_element();
const FF gamma = FF::random_element();
const FF beta_sqr = beta * beta;
const FF beta_quartic = beta_sqr * beta_sqr;
relation_parameters.gamma = gamma;
relation_parameters.beta = beta;
relation_parameters.beta_sqr = beta_sqr;
relation_parameters.beta_cube = beta_sqr * beta;
relation_parameters.eccvm_set_permutation_delta =
gamma * (gamma + beta_sqr) * (gamma + beta_sqr + beta_sqr) * (gamma + beta_sqr + beta_sqr + beta_sqr);
relation_parameters.beta_quartic = beta_quartic;
auto first_term_tag = beta_quartic; // FIRST_TERM_TAG (= 1) * beta_quartic
relation_parameters.eccvm_set_permutation_delta = (gamma + first_term_tag) * (gamma + beta_sqr + first_term_tag) *
(gamma + beta_sqr + beta_sqr + first_term_tag) *
(gamma + beta_sqr + beta_sqr + beta_sqr + first_term_tag);
relation_parameters.eccvm_set_permutation_delta = relation_parameters.eccvm_set_permutation_delta.invert();

const size_t unmasked_witness_size = pk->circuit_size - NUM_DISABLED_ROWS_IN_SUMCHECK;
Expand Down
11 changes: 8 additions & 3 deletions barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,22 @@ void ECCVMProver::execute_log_derivative_commitments_round()

// TODO(#583)(@zac-williamson): fix Transcript to be able to generate more than 2 challenges per round! oof.
auto beta_sqr = beta * beta;
auto beta_quartic = beta_sqr * beta_sqr;
relation_parameters.gamma = gamma;
relation_parameters.beta = beta;
relation_parameters.beta_sqr = beta_sqr;
relation_parameters.beta_cube = beta_sqr * beta;
relation_parameters.beta_quartic = beta_quartic;
// `eccvm_set_permutation_delta` is used in the set membership gadget in eccvm/ecc_set_relation.hpp, specifically to
// constrain (pc, round, wnaf_slice) to match between the MSM table and the Precomputed table. The number of rows we
// add per short scalar `mul` is slightly less in the Precomputed table as in the MSM table, so to get the
// permutation argument to work out, when `precompute_select == 0`, we must implicitly _remove_ (0, 0, 0) as a tuple
// on the wNAF side. This corresponds to dividing by (γ)·(γ + β²)·(γ + 2β²)·(γ + 3β²).
relation_parameters.eccvm_set_permutation_delta =
gamma * (gamma + beta_sqr) * (gamma + beta_sqr + beta_sqr) * (gamma + beta_sqr + beta_sqr + beta_sqr);
// on the wNAF side. This corresponds to dividing by
// (γ+t·β⁴)·(γ+β²+t·β⁴)·(γ+2β²+t·β⁴)·(γ+3β²+t·β⁴), where t = FIRST_TERM_TAG.
auto first_term_tag = beta_quartic; // FIRST_TERM_TAG (= 1) * beta_quartic
relation_parameters.eccvm_set_permutation_delta = (gamma + first_term_tag) * (gamma + beta_sqr + first_term_tag) *
(gamma + beta_sqr + beta_sqr + first_term_tag) *
(gamma + beta_sqr + beta_sqr + beta_sqr + first_term_tag);
relation_parameters.eccvm_set_permutation_delta = relation_parameters.eccvm_set_permutation_delta.invert();
// Compute inverse polynomial for our logarithmic-derivative lookup method
compute_logderivative_inverse<typename Flavor::FF,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ bool ECCVMTraceChecker::check(Builder& builder,
const FF beta = FF::random_element(engine_ptr);
const FF beta_sqr = beta.sqr();
const FF beta_cube = beta_sqr * beta;
auto eccvm_set_permutation_delta =
gamma * (gamma + beta_sqr) * (gamma + beta_sqr + beta_sqr) * (gamma + beta_sqr + beta_sqr + beta_sqr);
const FF beta_quartic = beta_sqr * beta_sqr;
auto first_term_tag = beta_quartic; // FIRST_TERM_TAG (= 1) * beta_quartic
auto eccvm_set_permutation_delta = (gamma + first_term_tag) * (gamma + beta_sqr + first_term_tag) *
(gamma + beta_sqr + beta_sqr + first_term_tag) *
(gamma + beta_sqr + beta_sqr + beta_sqr + first_term_tag);
eccvm_set_permutation_delta = eccvm_set_permutation_delta.invert();
bb::RelationParameters<typename Flavor::FF> params{
.eta = 0,
Expand All @@ -31,6 +34,7 @@ bool ECCVMTraceChecker::check(Builder& builder,
.public_input_delta = 0,
.beta_sqr = beta_sqr,
.beta_cube = beta_cube,
.beta_quartic = beta_quartic,
.eccvm_set_permutation_delta = eccvm_set_permutation_delta,
};

Expand Down
10 changes: 7 additions & 3 deletions barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,16 @@ typename ECCVMVerifier_<Flavor>::ReductionResult ECCVMVerifier_<Flavor>::reduce_
auto [beta, gamma] = transcript->template get_challenges<FF>(std::array<std::string, 2>{ "beta", "gamma" });

auto beta_sqr = beta * beta;
auto beta_quartic = beta_sqr * beta_sqr;
relation_parameters.gamma = gamma;
relation_parameters.beta = beta;
relation_parameters.beta_sqr = beta * beta;
relation_parameters.beta_sqr = beta_sqr;
relation_parameters.beta_cube = beta_sqr * beta;
relation_parameters.eccvm_set_permutation_delta =
gamma * (gamma + beta_sqr) * (gamma + beta_sqr + beta_sqr) * (gamma + beta_sqr + beta_sqr + beta_sqr);
relation_parameters.beta_quartic = beta_quartic;
auto first_term_tag = beta_quartic; // FIRST_TERM_TAG (= 1) * beta_quartic
relation_parameters.eccvm_set_permutation_delta = (gamma + first_term_tag) * (gamma + beta_sqr + first_term_tag) *
(gamma + beta_sqr + beta_sqr + first_term_tag) *
(gamma + beta_sqr + beta_sqr + beta_sqr + first_term_tag);
relation_parameters.eccvm_set_permutation_delta = relation_parameters.eccvm_set_permutation_delta.invert();

// Get commitment to permutation and lookup grand products
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ template <typename FF_> class ECCVMSetRelationImpl {
public:
using FF = FF_;

// Domain separation tags for the three tuple families in the set relation grand product.
// Each tuple family uses a distinct tag multiplied by beta^4 to prevent cross-family collisions.
// Without these tags, tuples from different families with identical packed values would produce
// identical fingerprints, allowing cross-family substitution in the multiset equality check.
static constexpr uint64_t FIRST_TERM_TAG = 1; // (pc, round, wnaf_slice)
static constexpr uint64_t SECOND_TERM_TAG = 2; // (pc, P.x, P.y, scalar)
static constexpr uint64_t THIRD_TERM_TAG = 3; // (pc, P.x, P.y, msm_size)

static constexpr std::array<size_t, 2> SUBRELATION_PARTIAL_LENGTHS{
22, // grand product construction sub-relation
3 // left-shiftable polynomial sub-relation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,15 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_numerator(const AllE
const auto& beta = params.beta;
const auto& beta_sqr = params.beta_sqr;
const auto& beta_cube = params.beta_cube;
const auto& beta_quartic = params.beta_quartic;
const auto& precompute_pc = View(in.precompute_pc);
const auto& precompute_select = View(in.precompute_select);

// Domain separation: each tuple family includes a distinct tag * beta^4 term to prevent cross-family collisions.
const auto first_term_tag = beta_quartic * FIRST_TERM_TAG;
const auto second_term_tag = beta_quartic * SECOND_TERM_TAG;
const auto third_term_tag = beta_quartic * THIRD_TERM_TAG;

/**
* @brief First term: tuple of (pc, round, wnaf_slice), computed when slicing scalar multipliers into slices, as
* part of ECCVMWnafRelation.
Expand All @@ -106,7 +112,8 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_numerator(const AllE
wnaf_slice += wnaf_slice;
wnaf_slice += s1;

const auto wnaf_slice_input0 = wnaf_slice + gamma + precompute_pc * beta + precompute_round4 * beta_sqr;
const auto wnaf_slice_input0 =
wnaf_slice + gamma + precompute_pc * beta + precompute_round4 * beta_sqr + first_term_tag;
numerator *= wnaf_slice_input0; // degree-1
}
{
Expand All @@ -117,7 +124,8 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_numerator(const AllE
wnaf_slice += wnaf_slice;
wnaf_slice += s1;

const auto wnaf_slice_input1 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 1) * beta_sqr;
const auto wnaf_slice_input1 =
wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 1) * beta_sqr + first_term_tag;
numerator *= wnaf_slice_input1; // degree-2
}
{
Expand All @@ -128,7 +136,8 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_numerator(const AllE
wnaf_slice += wnaf_slice;
wnaf_slice += s1;

const auto wnaf_slice_input2 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 2) * beta_sqr;
const auto wnaf_slice_input2 =
wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 2) * beta_sqr + first_term_tag;
numerator *= wnaf_slice_input2; // degree-3
}
{
Expand All @@ -138,23 +147,22 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_numerator(const AllE
auto wnaf_slice = s0 + s0;
wnaf_slice += wnaf_slice;
wnaf_slice += s1;
const auto wnaf_slice_input3 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 3) * beta_sqr;
const auto wnaf_slice_input3 =
wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 3) * beta_sqr + first_term_tag;
numerator *= wnaf_slice_input3; // degree-4
}
{
// skew product if relevant
const auto& skew = View(in.precompute_skew);
const auto& precompute_point_transition = View(in.precompute_point_transition);
const auto skew_input =
precompute_point_transition * (skew + gamma + precompute_pc * beta + (precompute_round4 + 4) * beta_sqr) +
(-precompute_point_transition + 1);
const auto skew_input = precompute_point_transition * (skew + gamma + precompute_pc * beta +
(precompute_round4 + 4) * beta_sqr + first_term_tag) +
(-precompute_point_transition + 1);
numerator *= skew_input; // degree-5
}
{
// in `EccvmProver` and `ECCVMVerifier`, we see that `eccvm_set_permutation_delta` is initially computed as
// (γ)·(γ + β²)·(γ + 2β²)·(γ + 3β²) and _then_ inverted. Therefore, `eccvm_set_permutation_delta` == 1 / (γ)·(γ
// + β²)·(γ + 2β²)·(γ
// + 3β²)
// (γ+t·β⁴)·(γ+β²+t·β⁴)·(γ+2β²+t·β⁴)·(γ+3β²+t·β⁴) (where t = FIRST_TERM_TAG) and _then_ inverted.
const auto& eccvm_set_permutation_delta = params.eccvm_set_permutation_delta;
// if `precompute_select == 1`, don't change the numerator. if it is 0, then to get the grand product argument
// to work (as we have zero-padded the rows of the MSM table), we must multiply by the inverse of the
Expand Down Expand Up @@ -237,7 +245,7 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_numerator(const AllE
auto precompute_point_transition = View(in.precompute_point_transition);

auto point_table_init_read =
(precompute_pc + table_x * beta + table_y * beta_sqr + scalar_sum_full * beta_cube);
(precompute_pc + table_x * beta + table_y * beta_sqr + scalar_sum_full * beta_cube + second_term_tag);
point_table_init_read =
precompute_point_transition * (point_table_init_read + gamma) + (-precompute_point_transition + 1);

Expand Down Expand Up @@ -282,7 +290,8 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_numerator(const AllE
// at row i + 1 we have updated `pc` to be `(pc at start of msm) + msm_count`
// at row i + 1 q_msm_transtiion = 1

auto msm_result_write = msm_pc_shift + msm_x_shift * beta + msm_y_shift * beta_sqr + msm_size * beta_cube;
auto msm_result_write =
msm_pc_shift + msm_x_shift * beta + msm_y_shift * beta_sqr + msm_size * beta_cube + third_term_tag;

// msm_result_write = degree 2
msm_result_write = msm_transition_shift * (msm_result_write + gamma) + (-msm_transition_shift + 1);
Expand All @@ -303,10 +312,16 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_denominator(const Al
const auto& beta = params.beta;
const auto& beta_sqr = params.beta_sqr;
const auto& beta_cube = params.beta_cube;
const auto& beta_quartic = params.beta_quartic;
const auto& msm_pc = View(in.msm_pc);
const auto& msm_count = View(in.msm_count);
const auto& msm_round = View(in.msm_round);

// Domain separation: must match the tags used in the numerator.
const auto first_term_tag = beta_quartic * FIRST_TERM_TAG;
const auto second_term_tag = beta_quartic * SECOND_TERM_TAG;
const auto third_term_tag = beta_quartic * THIRD_TERM_TAG;

/**
* @brief First term: tuple of (pc, round, wnaf_slice), used to determine which points we extract from lookup tables
* when evaluaing MSMs in ECCVMMsmRelation.
Expand All @@ -318,30 +333,34 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_denominator(const Al
const auto& msm_slice1 = View(in.msm_slice1);

auto wnaf_slice_output1 =
add1 * (msm_slice1 + gamma + (msm_pc - msm_count) * beta + msm_round * beta_sqr) + (-add1 + 1);
add1 * (msm_slice1 + gamma + (msm_pc - msm_count) * beta + msm_round * beta_sqr + first_term_tag) +
(-add1 + 1);
denominator *= wnaf_slice_output1; // degree-2
}
{
const auto& add2 = View(in.msm_add2);
const auto& msm_slice2 = View(in.msm_slice2);

auto wnaf_slice_output2 =
add2 * (msm_slice2 + gamma + (msm_pc - msm_count - 1) * beta + msm_round * beta_sqr) + (-add2 + 1);
add2 * (msm_slice2 + gamma + (msm_pc - msm_count - 1) * beta + msm_round * beta_sqr + first_term_tag) +
(-add2 + 1);
denominator *= wnaf_slice_output2; // degree-4
}
{
const auto& add3 = View(in.msm_add3);
const auto& msm_slice3 = View(in.msm_slice3);

auto wnaf_slice_output3 =
add3 * (msm_slice3 + gamma + (msm_pc - msm_count - 2) * beta + msm_round * beta_sqr) + (-add3 + 1);
add3 * (msm_slice3 + gamma + (msm_pc - msm_count - 2) * beta + msm_round * beta_sqr + first_term_tag) +
(-add3 + 1);
denominator *= wnaf_slice_output3; // degree-6
}
{
const auto& add4 = View(in.msm_add4);
const auto& msm_slice4 = View(in.msm_slice4);
auto wnaf_slice_output4 =
add4 * (msm_slice4 + gamma + (msm_pc - msm_count - 3) * beta + msm_round * beta_sqr) + (-add4 + 1);
add4 * (msm_slice4 + gamma + (msm_pc - msm_count - 3) * beta + msm_round * beta_sqr + first_term_tag) +
(-add4 + 1);
denominator *= wnaf_slice_output4; // degree-8
}

Expand Down Expand Up @@ -371,10 +390,10 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_denominator(const Al
const auto& lookup_second = (-z2_zero + 1);
FF cube_root_unity = FF(bb::fq::cube_root_of_unity());

auto transcript_input1 =
transcript_pc + transcript_Px * beta + transcript_Py * beta_sqr + z1 * beta_cube; // degree = 1
auto transcript_input1 = transcript_pc + transcript_Px * beta + transcript_Py * beta_sqr + z1 * beta_cube +
second_term_tag; // degree = 1
auto transcript_input2 = (transcript_pc - 1) + transcript_Px * cube_root_unity * beta -
transcript_Py * beta_sqr + z2 * beta_cube; // degree = 2
transcript_Py * beta_sqr + z2 * beta_cube + second_term_tag; // degree = 2

// The following diagram expresses a fingerprint of part of the tuple. It does not include `transcript_pc` and
// has not weighted the X and Y with beta and beta_sqr respectively. The point is nonetheless to show exactly
Expand Down Expand Up @@ -432,8 +451,8 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_denominator(const Al
auto full_msm_count =
transcript_msm_count + transcript_mul * ((-z1_zero + 1) + (-z2_zero + 1)) * (-base_infinity + 1);
// msm_result_read = degree 2
auto msm_result_read =
transcript_pc_shift + transcript_msm_x * beta + transcript_msm_y * beta_sqr + full_msm_count * beta_cube;
auto msm_result_read = transcript_pc_shift + transcript_msm_x * beta + transcript_msm_y * beta_sqr +
full_msm_count * beta_cube + third_term_tag;
msm_result_read = transcript_msm_transition * (msm_result_read + gamma) + (-transcript_msm_transition + 1);
denominator *= msm_result_read; // degree-20
}
Expand Down
Loading
Loading