Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: range check arbitrary size word columns #463

Closed
wants to merge 5 commits into from

Conversation

Dustin-Ray
Copy link
Contributor

@Dustin-Ray Dustin-Ray commented Jan 10, 2025

Rationale for this change

Currently, it is possible to argue the correct ranges of scalars up to the word value size, but anything below or beyond this value (currently 256 for byte sized words) will fail to verify. This PR expands range check on a scalar column to arbitrary lengths.

What changes are included in this PR?

  • arbitrary lengths beyond maximum word value
  • arbitrary lengths below maximum word value
  • benches were carried out in criterion
  • refactored inner functions to make the loops more readable, will move back to idiomatic representations before marking this ready for merge

Benchmarks

  • Attempted to introduce rayon to optimize word decomposition and some of the matrix operations in the log deriv function, but this attempt didnt seem to yield any benefits:

  • 2^16 Columns:

    • Change in Mean Execution Time: +0.2633%
    • Observation: Within the noise threshold; no significant performance impact observed.
  • 2^20 Columns:

    • Change in Mean Execution Time: +1.8316%
    • Observation: Statistically significant regression (p < 0.05), indicating a measurable performance degradation.

The cost of range check is likely dominated by the many inversions that take place, and these are already optimized with rayon. Will try and find other areas of the current code to optimize.

Are these changes tested?

Benching analysis

Analysis: Scaling from 2^16 to 2^20 in Dory Range Check Proofs

Key Metrics

  • Columns up to 2^16:
    • Mean Execution Time: 10.586 seconds
  • Columns up to 2^20:
    • Mean Execution Time: 24.448 seconds

Scaling Analysis

  • Increase in Column Size:
    • $2^{20} / 2^{16} = 2^4 = 16$ → A 16x increase in the number of scalars.
  • Increase in Runtime:
    • 24.448 / 10.586 ≈ 2.31 → A 2.31x increase in runtime.

Observations

  • The runtime scales sub-linearly with respect to column size, as a 16x increase in column size resulted in only a 2.31x increase in execution time.

@Dustin-Ray
Copy link
Contributor Author

Failing to range check on column sizes less than 256

Summary of Changes Made

  • First Round: Added builder.produce_one_evaluation_length(scalars.len()) to produce evaluation length.

  • Verifier: Added let input_ones_eval = builder.try_consume_one_evaluation()? to consume the evaluation length, then used this to argue that (word_vals + α)⁻¹ * (word_vals + α) - 1 = 0 with this:

    builder.try_produce_sumcheck_subpolynomial_evaluation(
        SumcheckSubpolynomialType::Identity,
        word_value_constraint - input_ones_eval,
        2,
    )?;

verification currently fails with:

Verification failed: Verification error: round evaluation does not match claimed sum

on column sizes less than 256.

I think here:

fn prove_word_values<'a, S: Scalar + 'a>(
    alloc: &'a Bump,
    scalars: &[S],
    alpha: S,
    table_length: usize,
    builder: &mut FinalRoundBuilder<'a, S>,
) {
    // Allocate from 0 to 255
    let word_values: &mut [S] = alloc.alloc_slice_fill_with(max(256, scalars.len()), |_| S::ZERO);

    for i in 0..256 {
        word_values[i] = S::try_from(i.into()).expect("word value will always fit into S");
    }

    // Allocate a slice filled with zeros, with length equal to the larger of 256 or scalars.len()
    let word_vals_inv: &mut [S] = alloc.alloc_slice_fill_with(max(256, scalars.len()), |_| S::ZERO);

    // Set elements 0 to 255 to their respective values
    for i in 0..256 {
        word_vals_inv[i] = S::try_from(i.into()).expect("word value will always fit into S");
    }

    slice_ops::add_const::<S, S>(word_vals_inv, alpha);
    slice_ops::batch_inversion(&mut word_vals_inv[..]);
    builder.produce_intermediate_mle(word_vals_inv as &[_]);

    let input_ones = alloc.alloc_slice_fill_copy(table_length, true);

Specifically here:

    let input_ones = alloc.alloc_slice_fill_copy(table_length, true);

Is table length the correct value to use here?

@Dustin-Ray Dustin-Ray changed the title feat: range check arbitrary word columns feat: range check arbitrary size word columns Jan 10, 2025
@Dustin-Ray Dustin-Ray closed this Jan 15, 2025
@Dustin-Ray Dustin-Ray deleted the feat/range-check-arbitrary-word-columns branch January 23, 2025 22:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant