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: removed redundant scalar muls from the verifiers using shplemini #9392

Merged
merged 25 commits into from
Nov 14, 2024

Conversation

iakovenkos
Copy link
Contributor

@iakovenkos iakovenkos commented Oct 24, 2024

  • Reduced the number of scalar multiplications to be performed by the native and recursive verifiers running shplemini
  • Slightly re-shuffled the entities in Translator and ECCVM, so that entitied to be shifted and their shifts form contiguous ranges
  • This is useful for amortizing the verification costs in the case of ZK sumcheck
  • The Translator recursive verifier circuit is now around 820K gates as opposed to 1700K. For other Flavors, the numbers are not as dramatic, but there's still around -10% in scalar muls and the sizes of recursive verifiers.

Copy link
Contributor

github-actions bot commented Oct 24, 2024

Changes to circuit sizes

Generated at commit: a50fedb8152b39e1e3b863fdae8f14b0008761b8, compared to commit: 7766c8e714185d6e8b9fa392d7f371fb30da8f1a

🧾 Summary (100% most significant diffs)

Program ACIR opcodes (+/-) % Circuit size (+/-) %
rollup_base 0 ➖ 0.00% -78,088 ✅ -2.33%
public_kernel_tail 0 ➖ 0.00% -78,087 ✅ -3.44%
public_kernel_merge 0 ➖ 0.00% -78,087 ✅ -7.08%
rollup_block_merge 0 ➖ 0.00% -156,173 ✅ -8.19%
rollup_root 0 ➖ 0.00% -156,173 ✅ -8.19%
rollup_merge 0 ➖ 0.00% -156,141 ✅ -8.20%
rollup_block_root 0 ➖ 0.00% -234,229 ✅ -8.22%
parity_root 0 ➖ 0.00% -312,315 ✅ -8.24%
private_kernel_empty 0 ➖ 0.00% -78,055 ✅ -8.30%

Full diff report 👇
Program ACIR opcodes (+/-) % Circuit size (+/-) %
rollup_base 478,886 (0) 0.00% 3,278,882 (-78,088) -2.33%
public_kernel_tail 258,538 (0) 0.00% 2,191,958 (-78,087) -3.44%
public_kernel_merge 52,901 (0) 0.00% 1,024,210 (-78,087) -7.08%
rollup_block_merge 7,499 (0) 0.00% 1,751,100 (-156,173) -8.19%
rollup_root 7,483 (0) 0.00% 1,751,086 (-156,173) -8.19%
rollup_merge 3,876 (0) 0.00% 1,747,898 (-156,141) -8.20%
rollup_block_root 4,502 (0) 0.00% 2,614,728 (-234,229) -8.22%
parity_root 5,717 (0) 0.00% 3,478,203 (-312,315) -8.24%
private_kernel_empty 671 (0) 0.00% 861,907 (-78,055) -8.30%

@@ -96,53 +96,58 @@ class TranslatorCircuitBuilder : public CircuitBuilderBase<bb::fr> {
X_LOW_Y_HI,
X_HIGH_Z_1,
Y_LOW_Z_2,
P_X_LOW_LIMBS, // P.xₗₒ split into 2 68 bit limbs
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

had to sort the entities differently to get a contiguous range of repeating commitments

@@ -122,91 +128,91 @@ class ECCVMFlavor {
template <typename DataType> class WireEntities {
public:
DEFINE_FLAVOR_MEMBERS(DataType,
transcript_add, // column 0
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

had to sort the entities differently to get a contiguous range of repeating commitments

@@ -77,7 +90,7 @@ class MegaFlavor {
static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = MAX_PARTIAL_RELATION_LENGTH + 1;
static constexpr size_t NUM_RELATIONS = std::tuple_size_v<Relations>;
// The total number of witnesses including shifts and derived entities.
static constexpr size_t NUM_ALL_WITNESS_ENTITIES = 23;
static constexpr size_t NUM_ALL_WITNESS_ENTITIES = NUM_WITNESS_ENTITIES + NUM_SHIFTED_WITNESSES;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Luke pointed out that this constant got stale. Now it should be more robust

@@ -439,5 +439,71 @@ template <typename Curve> class ShpleminiVerifier_ {
commitments.emplace_back(std::move(fold_commitments[j]));
}
}

Copy link
Contributor Author

@iakovenkos iakovenkos Oct 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the main feature introduced in this PR

@iakovenkos iakovenkos added the e2e-prover-full CI: Enables this CI job. label Oct 25, 2024
@iakovenkos iakovenkos self-assigned this Oct 25, 2024
Copy link
Contributor

@maramihali maramihali left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this work should be restructed a bit differently, as I mentioned in the other comments I think a single data structure with the required index constants should be created in the flavors (well maybe two given the concatenation edge case) and passed to Shplemini. Also I think remove_shifted_commitments should be a method isolated in Shplemini not called from the verifiers. I added some more thoughts in my comments.

* of scalars. This method iterates over the commitments and scalars in a BatchOpeningClaim object
*
*/
static void remove_shifted_commitments(BatchOpeningClaim<Curve>& accumulator,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this method should probably not be called from the verifier classes, but rather be part of the "reduce_verify" stage in Shplemini, in which a BatchOpeningClaim is computed and then the shifted commitments are removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Commitment::one(),
transcript);
Shplemini::remove_shifted_commitments(opening_claim,
Flavor::TO_BE_SHIFTED_WITNESSES_START,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These indexes should be passed as a single data structure constructed in the flavor

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, created a struct for this


// Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a random
// point.
auto mle_opening_point = this->random_evaluation_point(log_n); // sometimes denoted 'u'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We really need to clean up these pcs test files by having single methods that generate input rather than duplicating code over and over again (similar to what we do for circuits). I previously added an issue on this. Just saying, not suggesting that it's something that should be done in this PR

Flavor::NUM_SHIFTED_WITNESSES,
Flavor::TO_BE_CONCATENATED_START,
Flavor::CONCATENATED_START,
Flavor::NUM_CONCATENATED);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think NUM_CONCATENATED can be determined from the other inputs no?

* verifier.
*
* @details The Shplemini verifier gets the access to multiple groups of commitments, some of which are duplicated
* by design. This method combines the scalars associated with these repeating commitments, reducing the total
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will you please explain why here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expanded slightly
I think, the real answer - it's just easier to have those entities and shifts

static constexpr size_t NUM_SHIFTED_TABLES = 4;

// A container to be fed to ShpleminiVerifier to avoid redundant scalar muls
static constexpr RepeatedCommitmentsData REPEATED_COMMITMENTS =
Copy link
Contributor Author

@iakovenkos iakovenkos Nov 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still somewhat ugly here, but I think expressing everything in terms of numbers of entities is a better practice than just constants with the required indexes. e.g. someone would delete shifted tables - delete the constant - nothing would be broken

Copy link
Contributor

@maramihali maramihali left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approved, pending a follow-up cleanup PR to remove the use of erase if possible, also a small comment

static constexpr size_t SHIFTED_WITNESSES_START = 90;
static constexpr size_t NUM_ALL_WITNESS_ENTITIES = NUM_WITNESS_ENTITIES + NUM_SHIFTED_ENTITIES;
// Container to be fed to ShpleminiVerifier to avoid redundant scalar muls, the first number is the index of the
// first witness to be shifted. -1 appears because WitnessEntities contain
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unfinished comment?

@iakovenkos iakovenkos enabled auto-merge (squash) November 14, 2024 17:33
@iakovenkos iakovenkos merged commit e07cac7 into master Nov 14, 2024
42 checks passed
@iakovenkos iakovenkos deleted the si/shplemini-shifts-removal branch November 14, 2024 17:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
e2e-prover-full CI: Enables this CI job.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants