Skip to content
This repository has been archived by the owner on Jul 5, 2024. It is now read-only.

Remove minimal_rows in the Bytecode circuit #1633

Merged
merged 4 commits into from
Oct 2, 2023

Conversation

ChihChengLiang
Copy link
Collaborator

Description

  • Remove minimal_rows
  • Configure the bytecode circuit with the circuit degree instead of size.

Issue Link

#1607

Type of change

[x] Bug fix (non-breaking change which fixes an issue)

Note

Please review this after #1632 is merged.

@github-actions github-actions bot added crate-zkevm-circuits Issues related to the zkevm-circuits workspace member T-bench Type: benchmark improvements crate-circuit-benchmarks Issues related to the circuit-benchmarks workspace member labels Sep 28, 2023
@ChihChengLiang ChihChengLiang linked an issue Sep 28, 2023 that may be closed by this pull request
@hero78119 hero78119 self-requested a review September 28, 2023 12:39
Copy link
Member

@hero78119 hero78119 left a comment

Choose a reason for hiding this comment

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

LGTM

zkevm-circuits/src/bytecode_circuit.rs Outdated Show resolved Hide resolved
Base automatically changed from move-bytecode-circuit to main September 28, 2023 14:14
@ChihChengLiang ChihChengLiang force-pushed the fix-bytecode-circuit-configuration branch from 337a838 to 1c56c0d Compare September 28, 2023 14:16
@ChihChengLiang ChihChengLiang marked this pull request as ready for review September 28, 2023 14:16
Copy link
Member

@ed255 ed255 left a comment

Choose a reason for hiding this comment

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

Please take a look at my long discussion :P

}

impl<F: Field> BytecodeCircuit<F> {
/// new BytecodeCircuitTester
pub fn new(bytecodes: CodeDB, size: usize) -> Self {
pub fn new(bytecodes: CodeDB, degree: u32) -> Self {
Copy link
Member

Choose a reason for hiding this comment

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

I think that parametrizing the circuit with just the degree has some downsides, in particular for testing with the MockProver.
Most of the times when running the MockProver we want the verification to only apply to rows that contain actual data. The only case where we want more than that would be to test the padding strategy that the circuit applies to support a fixed size circuit with a smaller than max capacity data; but that's usually a single test.

By configuring with degree, when running the MockProver we'll be checking more rows than strictly necessary. Let's say we have some bytecodes that need 1200 rows. We would need to verify 2048 rows with the current approach.

Also this is specially important when testing the SuperCircuit with the MockProver. Let's imagine that for a block we need 4000 rows for the TxCircuit and 100 for the block circuit. Then the SuperCircuit degree would be k=12 (4096 rows). Would you pass degree=12 to the TxCircuit? Maybe you'd pass degree=7 (128 rows) to have a better verification time, but that feels strange because that degree is not the real one.

We have other circuits that don't receive the degree, and instead receive how many rows to enable, or the maximum number of operations to verify.

  • CopyCircuit takes max_copy_rows
  • KeccakCircuit takes num_rows
  • ExpCircuit takes max_exp_steps

To avoid dynamic circuits on real proofs, we have the DynamicCParams and FixedCParams types in bus-mapping/src/circuit_input_builder.rs. The first allows the circuit input builder to chose the circuit parameters dynamically based on a specific block input; and the second allows us to pick static parameters regardless of the input (so we get fast MockProver verification, and constant circuits for the real prover).

Copy link
Member

Choose a reason for hiding this comment

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

On the other hand: I agree that saying:

let last_row_offset = 2usize.pow(degree) - unusable_rows - 1;

Is correct and clear.
Whereas if we only have the parameters max_rows and unusable_rows, I would argue that

let last_row_offset = max_rows - 1;

But then we don't know if last_row_offset <= 2^k - unusable_rows - 1, which is a nice check to have as early as possible.

As a possible solution, 2 ideas come to my mind:

  • a) Pass the max_rows and degree to each circuit so that we can have the full view and do all the early checks, while supporting fast MockProver.verify. Note that for a real proof we would need to set max_rows = 2^degree - unusable_rows(), but we already have that API in the SubCircuit trait
  • b) Extend halo2 (either the Layouter or the ConstraintSystem) to expose the circuit degree, so that we can get that value during configuration or synthesis time, and do all the checks we want with it.

Copy link
Collaborator Author

@ChihChengLiang ChihChengLiang Sep 29, 2023

Choose a reason for hiding this comment

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

I see the reasoning now.

  • To save the testing time on Mock prover, I'll change the parameter from "degree" back to "size." Or even better, rename "size" to "max_rows."
  • I'll comment on the rationale for using size.
  • I'll comment on DynamicCParams and FixedCParams

For validating max_rows, I like the idea for Halo2 to expose the circuit degree. For the quick fix, I'll use the SubCircuit trait.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hi @ed255,
I've addressed the feedback, can you check again?

@ChihChengLiang ChihChengLiang force-pushed the fix-bytecode-circuit-configuration branch from 1c56c0d to 381969d Compare September 29, 2023 09:02
@github-actions github-actions bot added crate-bus-mapping Issues related to the bus-mapping workspace member and removed T-bench Type: benchmark improvements crate-circuit-benchmarks Issues related to the circuit-benchmarks workspace member labels Sep 29, 2023
@@ -24,7 +24,7 @@ impl<F: Field> BytecodeCircuit<F> {
}

fn verify(&self, success: bool) {
let prover = MockProver::<F>::run(log2_ceil(self.size), self, Vec::new()).unwrap();
let prover = MockProver::<F>::run(log2_ceil(self.max_rows), self, Vec::new()).unwrap();
Copy link
Member

Choose a reason for hiding this comment

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

Following the change in assign_internal, now line 23 (in from_bytes) should be:

Suggested change
let prover = MockProver::<F>::run(log2_ceil(self.max_rows), self, Vec::new()).unwrap();
Self::new(bytecodes.into(), 2usize.pow(k) - Self::<Fr>::unusable_rows())

I think this is the reason why tests are failing.

@ChihChengLiang ChihChengLiang force-pushed the fix-bytecode-circuit-configuration branch from 381969d to 86636c1 Compare October 2, 2023 13:29
Copy link
Member

@ed255 ed255 left a comment

Choose a reason for hiding this comment

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

LGTM!

@ChihChengLiang ChihChengLiang added this pull request to the merge queue Oct 2, 2023
Merged via the queue into main with commit 4f1f56e Oct 2, 2023
13 checks passed
@ChihChengLiang ChihChengLiang deleted the fix-bytecode-circuit-configuration branch October 2, 2023 14:21
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
crate-bus-mapping Issues related to the bus-mapping workspace member crate-zkevm-circuits Issues related to the zkevm-circuits workspace member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

refactor(bytecode): unify circuit style
3 participants