-
Notifications
You must be signed in to change notification settings - Fork 234
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
fix: challenge generation update #2628
Conversation
barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. I left some minor comments (reflecting our discussion). In general I would request that you 1) review the analogous code for the Plonk transcript to understand how/if it differs and whether that's important, 2) ensure you have thorough comments indicating the new logic, and 3) add a test demonstrating the new capability (since we should now be able to generate an arbitrary number of challenges IIUC)
if (round_number > 0) { | ||
full_buffer.insert(full_buffer.end(), previous_challenge_buffer.begin(), previous_challenge_buffer.end()); | ||
} | ||
full_buffer.insert(full_buffer.end(), previous_challenge_buffer.begin(), previous_challenge_buffer.end()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be able to condition on previous_challenge_buffer != empty_challenge_buffer to avoid appending zeros. But actually I'm confused as to why the ASSERT a few lines above does not trigger for the first round..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the assert doesn't trigger because current_round_data isn't empty the first time we call this function
barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp
Outdated
Show resolved
Hide resolved
barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp
Outdated
Show resolved
Hide resolved
updated comments and minor refactoring
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getting close! just a couple of questions/comments and minor formatting things
// copy half of the hash to lower 128 bits of challenge | ||
std::copy_n(next_challenge_buffer.begin(), | ||
HASH_OUTPUT_SIZE / 2, | ||
field_element_buffer.begin() + HASH_OUTPUT_SIZE / 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how this serialization works but I would've assumed the byte at index 0 would correspond to the lowest byte of the deserialized result. If thats the case then you'd be writing to the highest 16 bytes of the field element. I assume you checked this and I'm wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah actually good point. I did check this, but I'm not sure why this happens. I believe the Adrian's old code actually made this mistake and put it in the upper 16 bytes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bizarre. Maybe there was good reason for doing this but its not intuitive. Worth a comment I would say
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so it actually reads the buffer like an integer; not entirely sure if some of the bytes get reversed or anything like that, but the resulting challenge is indeed 128 bits.
barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp
Outdated
Show resolved
Hide resolved
barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp
Outdated
Show resolved
Hide resolved
|
||
// concatenate the hash of the previous round (if not the first round) with the current round data. | ||
// Empty buffer to compare against | ||
std::array<uint8_t, HASH_OUTPUT_SIZE> empty_challenge_buffer{}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this only needed to check if there was a previous challenge or not? It seems clearer to just use Adrians original if (round_number > 0)
check. Maybe I'm missing something? if (!no_previous_challenge)
is kind of icky :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can't use round_number because in the 0th round, we might want to call this function multiple times. I could change the bool to first_challenge instead to avoid double negative?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. Maybe just a first_challenge
bool that's initialized to true then gets set to false. I just find it a bit hard to understand what the intent is as you have it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea, just did this instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
🤖 I have created a release *beep* *boop* --- <details><summary>aztec-packages: 0.8.8</summary> ## [0.8.8](aztec-packages-v0.8.7...aztec-packages-v0.8.8) (2023-10-09) ### Features * Actually compute selectors ([#2686](#2686)) ([dcb65e1](dcb65e1)) * Add otterscan to sandbox ([#2648](#2648)) ([6986649](6986649)) * **aztec.js:** Remove attach method ([#2715](#2715)) ([c03c654](c03c654)) * Create .gitattributes in aztec-nr ([#2661](#2661)) ([8084fc3](8084fc3)) * GCC 13 preset ([#2623](#2623)) ([4881414](4881414)) * Update noir to v0.16 ([#2718](#2718)) ([e8d0675](e8d0675)) ### Bug Fixes * Avoid ambiguity on blank and blank-react (prefix issue) ([#2729](#2729)) ([68cdb3f](68cdb3f)) * Block encoding ([#2719](#2719)) ([c4796ac](c4796ac)) * Canary tests to use a fork ([#2739](#2739)) ([4906142](4906142)) * Challenge generation update ([#2628](#2628)) ([68c1fab](68c1fab)) * Docs: Sandbox version numbers ([#2708](#2708)) ([34b0209](34b0209)) * Docs: Update Sandbox page to use #include_aztec_version ([#2703](#2703)) ([d5b78af](d5b78af)) * Remove npx from extract_tag_version ([#2697](#2697)) ([fe4484a](fe4484a)) * Version in sandbox deployment ([#2730](#2730)) ([b1d8efd](b1d8efd)) ### Miscellaneous * `foundation/src/serialization` tech debt ([#2722](#2722)) ([e92154b](e92154b)) * Add node10 entrypoint to Foundation ([#2706](#2706)) ([30c7935](30c7935)) * Add storage slot to docs ([#2601](#2601)) ([a7710f0](a7710f0)) * Add visibility modifiers ([#2728](#2728)) ([d9ae189](d9ae189)) * **benchmark:** Measure time to decrypt notes in pxe ([#2714](#2714)) ([33a230a](33a230a)) * Build boxes as part of workspace ([#2725](#2725)) ([d18349f](d18349f)) * Bump ACIR deserializer ([#2675](#2675)) ([502ee87](502ee87)) * **circuits:** Delete old code that set a different generator index per vector entry in pedersen commitment ([#2700](#2700)) ([4eabfd1](4eabfd1)) * **log:** Show log level in debug logs ([#2717](#2717)) ([2b87381](2b87381)) * Move { Fr } imports to foundation/fields ([#2712](#2712)) ([f6fc7f2](f6fc7f2)) * **uniswap_tests:** Test edge cases around uniswap flow ([#2620](#2620)) ([7a58fe9](7a58fe9)) * Use `serialize` functions in `getInitialWitness` ([#2713](#2713)) ([93cc668](93cc668)) </details> <details><summary>barretenberg.js: 0.8.8</summary> ## [0.8.8](barretenberg.js-v0.8.7...barretenberg.js-v0.8.8) (2023-10-09) ### Miscellaneous * **barretenberg.js:** Synchronize aztec-packages versions </details> <details><summary>barretenberg: 0.8.8</summary> ## [0.8.8](barretenberg-v0.8.7...barretenberg-v0.8.8) (2023-10-09) ### Features * GCC 13 preset ([#2623](#2623)) ([4881414](4881414)) ### Bug Fixes * Challenge generation update ([#2628](#2628)) ([68c1fab](68c1fab)) ### Miscellaneous * Bump ACIR deserializer ([#2675](#2675)) ([502ee87](502ee87)) </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
🤖 I have created a release *beep* *boop* --- <details><summary>aztec-packages: 0.8.8</summary> ## [0.8.8](AztecProtocol/aztec-packages@aztec-packages-v0.8.7...aztec-packages-v0.8.8) (2023-10-09) ### Features * Actually compute selectors ([#2686](AztecProtocol/aztec-packages#2686)) ([dcb65e1](AztecProtocol/aztec-packages@dcb65e1)) * Add otterscan to sandbox ([#2648](AztecProtocol/aztec-packages#2648)) ([6986649](AztecProtocol/aztec-packages@6986649)) * **aztec.js:** Remove attach method ([#2715](AztecProtocol/aztec-packages#2715)) ([c03c654](AztecProtocol/aztec-packages@c03c654)) * Create .gitattributes in aztec-nr ([#2661](AztecProtocol/aztec-packages#2661)) ([8084fc3](AztecProtocol/aztec-packages@8084fc3)) * GCC 13 preset ([#2623](AztecProtocol/aztec-packages#2623)) ([4881414](AztecProtocol/aztec-packages@4881414)) * Update noir to v0.16 ([#2718](AztecProtocol/aztec-packages#2718)) ([e8d0675](AztecProtocol/aztec-packages@e8d0675)) ### Bug Fixes * Avoid ambiguity on blank and blank-react (prefix issue) ([#2729](AztecProtocol/aztec-packages#2729)) ([68cdb3f](AztecProtocol/aztec-packages@68cdb3f)) * Block encoding ([#2719](AztecProtocol/aztec-packages#2719)) ([c4796ac](AztecProtocol/aztec-packages@c4796ac)) * Canary tests to use a fork ([#2739](AztecProtocol/aztec-packages#2739)) ([4906142](AztecProtocol/aztec-packages@4906142)) * Challenge generation update ([#2628](AztecProtocol/aztec-packages#2628)) ([68c1fab](AztecProtocol/aztec-packages@68c1fab)) * Docs: Sandbox version numbers ([#2708](AztecProtocol/aztec-packages#2708)) ([34b0209](AztecProtocol/aztec-packages@34b0209)) * Docs: Update Sandbox page to use #include_aztec_version ([#2703](AztecProtocol/aztec-packages#2703)) ([d5b78af](AztecProtocol/aztec-packages@d5b78af)) * Remove npx from extract_tag_version ([#2697](AztecProtocol/aztec-packages#2697)) ([fe4484a](AztecProtocol/aztec-packages@fe4484a)) * Version in sandbox deployment ([#2730](AztecProtocol/aztec-packages#2730)) ([b1d8efd](AztecProtocol/aztec-packages@b1d8efd)) ### Miscellaneous * `foundation/src/serialization` tech debt ([#2722](AztecProtocol/aztec-packages#2722)) ([e92154b](AztecProtocol/aztec-packages@e92154b)) * Add node10 entrypoint to Foundation ([#2706](AztecProtocol/aztec-packages#2706)) ([30c7935](AztecProtocol/aztec-packages@30c7935)) * Add storage slot to docs ([#2601](AztecProtocol/aztec-packages#2601)) ([a7710f0](AztecProtocol/aztec-packages@a7710f0)) * Add visibility modifiers ([#2728](AztecProtocol/aztec-packages#2728)) ([d9ae189](AztecProtocol/aztec-packages@d9ae189)) * **benchmark:** Measure time to decrypt notes in pxe ([#2714](AztecProtocol/aztec-packages#2714)) ([33a230a](AztecProtocol/aztec-packages@33a230a)) * Build boxes as part of workspace ([#2725](AztecProtocol/aztec-packages#2725)) ([d18349f](AztecProtocol/aztec-packages@d18349f)) * Bump ACIR deserializer ([#2675](AztecProtocol/aztec-packages#2675)) ([502ee87](AztecProtocol/aztec-packages@502ee87)) * **circuits:** Delete old code that set a different generator index per vector entry in pedersen commitment ([#2700](AztecProtocol/aztec-packages#2700)) ([4eabfd1](AztecProtocol/aztec-packages@4eabfd1)) * **log:** Show log level in debug logs ([#2717](AztecProtocol/aztec-packages#2717)) ([2b87381](AztecProtocol/aztec-packages@2b87381)) * Move { Fr } imports to foundation/fields ([#2712](AztecProtocol/aztec-packages#2712)) ([f6fc7f2](AztecProtocol/aztec-packages@f6fc7f2)) * **uniswap_tests:** Test edge cases around uniswap flow ([#2620](AztecProtocol/aztec-packages#2620)) ([7a58fe9](AztecProtocol/aztec-packages@7a58fe9)) * Use `serialize` functions in `getInitialWitness` ([#2713](AztecProtocol/aztec-packages#2713)) ([93cc668](AztecProtocol/aztec-packages@93cc668)) </details> <details><summary>barretenberg.js: 0.8.8</summary> ## [0.8.8](AztecProtocol/aztec-packages@barretenberg.js-v0.8.7...barretenberg.js-v0.8.8) (2023-10-09) ### Miscellaneous * **barretenberg.js:** Synchronize aztec-packages versions </details> <details><summary>barretenberg: 0.8.8</summary> ## [0.8.8](AztecProtocol/aztec-packages@barretenberg-v0.8.7...barretenberg-v0.8.8) (2023-10-09) ### Features * GCC 13 preset ([#2623](AztecProtocol/aztec-packages#2623)) ([4881414](AztecProtocol/aztec-packages@4881414)) ### Bug Fixes * Challenge generation update ([#2628](AztecProtocol/aztec-packages#2628)) ([68c1fab](AztecProtocol/aztec-packages@68c1fab)) ### Miscellaneous * Bump ACIR deserializer ([#2675](AztecProtocol/aztec-packages#2675)) ([502ee87](AztecProtocol/aztec-packages@502ee87)) </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
This PR updates challenge generation to not be powers of each other, fixing AztecProtocol/barretenberg#583.
Before, we generated multiple challenges by generating one by hashing the round data and the previous challenge, and then taking powers of this challenge as the other challenges. Now, we generate challenges by taking a hash each time of the previous challenge (and the round data, which is only nonempty in the first iteration).
Using powers of one challenge does not lead to soundness bugs in how we currently use challenges, but theoretically, we would want challenges to be "independent" of each other.
Challenges are 128 bits. I truncate every 256-bit hash to 128 bits for 2 reasons. First, it is easier on the verifier to multiply with 128 challenges as opposed to 256 bits. Second, the 256-bit challenges were not actually uniformly distributed in a nice way because the challenges get modded by the 254-bit scalar field modulus. In this approach, the challenges should be distributed more uniformly (over 128-bit numbers).
Optimization(AztecProtocol/barretenberg#741) - I could split every hash into 2 challenges, so I use all 256 bits of a hash (when we need it), instead of throwing away 128 bits every time.
Checklist:
Remove the checklist to signal you've completed it. Enable auto-merge if the PR is ready to merge.