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

Generic vertical gate assignment #129

Merged
merged 3 commits into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion halo2-base/src/gates/flex_gate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ pub struct BasicGateConfig<F: ScalarField> {
}

impl<F: ScalarField> BasicGateConfig<F> {
/// Constructor
pub fn new(q_enable: Selector, value: Column<Advice>) -> Self {
Self { q_enable, value, _marker: PhantomData }
}

/// Instantiates a new [BasicGateConfig].
///
/// Assumes `phase` is in the range [0, MAX_PHASE).
Expand Down Expand Up @@ -103,7 +108,7 @@ pub struct FlexGateConfig<F: ScalarField> {
pub basic_gates: Vec<Vec<BasicGateConfig<F>>>,
/// A [Vec] of [Fixed] [Column]s for allocating constant values.
pub constants: Vec<Column<Fixed>>,
/// Max number of rows in flex gate.
/// Max number of usable rows in the circuit.
pub max_rows: usize,
}

Expand Down
2 changes: 1 addition & 1 deletion halo2-base/src/gates/flex_gate/threads/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
mod multi_phase;
mod parallelize;
/// Thread builder for a single phase
mod single_phase;
pub mod single_phase;

pub use multi_phase::{GateStatistics, MultiPhaseCoreManager};
pub use parallelize::parallelize_core;
Expand Down
20 changes: 17 additions & 3 deletions halo2-base/src/gates/flex_gate/threads/single_phase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ impl<F: ScalarField> VirtualRegionManager<F> for SinglePhaseCoreManager<F> {
assign_witnesses(&self.threads, config, region, break_points);
} else {
let mut copy_manager = self.copy_manager.lock().unwrap();
let break_points = assign_with_constraints(
let break_points = assign_with_constraints::<F, 4>(
&self.threads,
config,
region,
Expand All @@ -165,13 +165,17 @@ impl<F: ScalarField> VirtualRegionManager<F> for SinglePhaseCoreManager<F> {
///
/// For proof generation, see [assign_witnesses].
///
/// This is generic for a "vertical" custom gate that uses a single column and `ROTATIONS` contiguous rows in that column.
///
/// ⚠️ Right now we only support "overlaps" where you can have the gate enabled at `offset` and `offset + ROTATIONS - 1`, but not at `offset + delta` where `delta < ROTATIONS - 1`.
///
/// # Inputs
/// - `max_rows`: The number of rows that can be used for the assignment. This is the number of rows that are not blinded for zero-knowledge.
/// - If `use_unknown` is true, then the advice columns will be assigned as unknowns.
///
/// # Assumptions
/// - All `basic_gates` are in the same phase.
pub fn assign_with_constraints<F: ScalarField>(
pub fn assign_with_constraints<F: ScalarField, const ROTATIONS: usize>(
threads: &[Context<F>],
basic_gates: &[BasicGateConfig<F>],
region: &mut Region<F>,
Expand Down Expand Up @@ -206,11 +210,21 @@ pub fn assign_with_constraints<F: ScalarField>(
.insert(ContextCell::new(ctx.type_id, ctx.context_id, i), cell);

// If selector enabled and row_offset is valid add break point, account for break point overlap, and enforce equality constraint for gate outputs.
if (q && row_offset + 4 > max_rows) || row_offset >= max_rows - 1 {
// ⚠️ This assumes overlap is of form: gate enabled at `i - delta` and `i`, where `delta = ROTATIONS - 1`. We currently do not support `delta < ROTATIONS - 1`.
if (q && row_offset + ROTATIONS > max_rows) || row_offset >= max_rows - 1 {
break_points.push(row_offset);
row_offset = 0;
gate_index += 1;

// safety check: make sure selector is not enabled on `i - delta` for `0 < delta < ROTATIONS - 1`
if ROTATIONS > 1 && i + 2 >= ROTATIONS {
for delta in 1..ROTATIONS - 1 {
assert!(
!ctx.selector[i - delta],
"We do not support overlaps with delta = {delta}"
);
}
}
// when there is a break point, because we may have two gates that overlap at the current cell, we must copy the current cell to the next column for safety
basic_gate = basic_gates
.get(gate_index)
Expand Down