chore: use free witness for offset generator in batch_mul#21040
Conversation
| // ======================================== | ||
|
|
||
| inline constexpr size_t ROOT_ROLLUP_GATE_COUNT = 12998771; | ||
| inline constexpr size_t ROOT_ROLLUP_GATE_COUNT = 12933470; |
There was a problem hiding this comment.
The gate count reduction is because we do not sample the extra challenge
| // Sample a random curve point as the offset generator (free witness). | ||
| // The prover provides this point: the circuit only constrains it to lie on the curve. | ||
| C* builder = validate_context<C>(validate_context<C>(_points), validate_context<C>(_scalars)); | ||
| const typename G::affine_element native_offset_generator = typename G::affine_element(G::element::random_element()); |
There was a problem hiding this comment.
This is the main change. Previously we did the following:
Now we make
74b2003 to
00d554b
Compare
ledwards2225
left a comment
There was a problem hiding this comment.
Makes sense to me. Nice that it amounts to cleanup in a few places
| // choose it freely because it must satisfy the batched opening equation. | ||
| if constexpr (Curve::is_stdlib_type) { | ||
| const auto challenge_tag = masking_challenge.get_origin_tag(); | ||
| const auto challenge_tag = batch_opening_claim.evaluation_point.get_origin_tag(); |
There was a problem hiding this comment.
maybe I just don't remember the tag stuff well, but confused by this line - I'd expect us to just not have this challenge_tag now that we don't have the challenge? Why is it set to this evaluation_point.get_origin_tag?
There was a problem hiding this comment.
A little while ago we updated the tag mechanism to alert us to combinations like A*\alpha + B, where e.g. A, B are commitments, \alpha a hash that accounts only for A. (This for example would have caught the bug we had in the PG verifier where we converted a bunch of size 2 MSMs into one larger one without proper fiat shamir). But this can give false positives since sometimes B is constrained by some other aspect of the protocol, as is the case here. Here W acts like B (really its more like A + B*\alpha) but it's constrained by the pairing to be correct so the prover isn't free to tamper with it. Setting the tag of W to match that of the challenge z is just the way we tell the tool not to complain. This is what the comment // OriginTag false positive was trying to explain but it could be clearer
There was a problem hiding this comment.
I've added this in the comment, thanks for explaining Luke!
def69a6 to
16a7fbe
Compare
16a7fbe to
e019d39
Compare
…pected manifest The KZG opening protocol no longer sends a masking_challenge (removed in #21040). The ProverManifestConsistency test's expected manifest was not updated, causing a mismatch in round 26.
…pected manifest (#21371) ## Summary The `BatchedHonkTranslatorTests.ProverManifestConsistency` test was failing because its hardcoded expected manifest included a `KZG:masking_challenge` entry in round 26 (the KZG opening round), but the KZG protocol no longer sends this challenge (removed in #21040). ## Fix Removed the stale `m.add_challenge(round, "KZG:masking_challenge")` from `build_expected_batched_manifest()` and updated the corresponding comment. ## Test plan - [x] `BatchedHonkTranslatorTests.ProverManifestConsistency` passes - [x] All 4 `batched_honk_translator_tests` pass locally ClaudeBox log: https://claudebox.work/s/a26a429f5a7f3d3d?run=1
resolves AztecProtocol/barretenberg#1585
tldr: we make the offset generator a free witness while performing
batch_mulCurrent Way of Masking Points
While performing$[(s_1, s_2, \dots, s_n), (G_1, G_2, \dots, G_n)]$ then the ROM tables are of the form:
batch_mulwe create ROM tables of linear combinations of the group elements. If we have an MSM of the formTo avoid any entries of the ROM table to be a point at infinity, we add a multiple of an offset generator:
and then we create a ROM table with$(G'_1, G'_2, \dots, G'_6)$ . Here, $\delta$ is a verifier-sent challenge so the prover cannot know it beforehand.
Proposed Masking of Points
Instead of sampling a challenge$\delta$ , we make the offset generator $G_{\textsf{offset}}$ a free witness in the circuit, so the masked generators become:
We only constrain$G_{\textsf{offset}}$ to be a valid point on the curve. This approach should also be safe because if a malicious prover tries to exploit the fact that he can freely choose $G_{\textsf{offset}}$ the circuit will be unsatisfiable. An honest prover must choose a random point on the curve as $G_{\textsf{offset}}$ .